目前国内做消息推送的有云巴,百度,蝴蝶,极光,个推哪个比较好点? - 知乎918被浏览235822分享邀请回答105 条评论分享收藏感谢收起31 条评论分享收藏感谢收起更多21 个回答被折叠()关于推送的一些补充 - 知乎专栏
{"debug":false,"apiRoot":"","paySDK":"/api/js","wechatConfigAPI":"/api/wechat/jssdkconfig","name":"production","instance":"column","tokens":{"X-XSRF-TOKEN":null,"X-UDID":null,"Authorization":"oauth c3cef7c66aa9e6a1e3160e20"}}
{"database":{"Post":{"":{"title":"关于推送的一些补充","author":"stormzhang","content":"昨天的文章「」不少人的留言有不同的声音,这里补充一下,顺便表示下我的不服!\n
1. 收了小米多少钱?很多人留言表示这软广不错,收了小米多少钱?不管你们是开玩笑还是认真的,我只想告诉你们,这篇文章是我自己的实践加上业内同行的交流总结出来的,没有任何人给我钱,而且我自己不是米粉,本身是不愿意推荐任何产品的,我完全是抱着能帮你们解决问题的角度出发的,等你们实际中遇到这个问题你们就会明白我文章中的观点了。\n
认为我是软广的我表示不服,我之前确实发过一些广告,而且我甚至希望多些广告商找我,毕竟没人愿意跟钱过不去,但是我都是堂堂正正的发,光明正大的告诉你们,是广告的从不藏着掖着!另外,小米,你丫的欠我一条广告费!\n
我很欣赏一些质疑文中观点,然后给我留言有理有据摆事实讲道理的行为,我的观点不一定正确,毕竟一家之言,但是能一起探讨我是完全乐意的,比如有人给我提了以下几个观点,我觉得很有意义,这里补充下:\n
2. 友盟的数据可靠么?讲真,没有任何数据来源是绝对可靠的,目前国内大多数 app 的数据统计基本都是用的友盟,也就意味着友盟的数据不是绝对正确的,但是起码数据来源参考作用非常大,如果你能给我提供一个更靠谱的数据来源,那不妨可以结合下,否则,我宁愿相信友盟的数据。\n
3. 根据市场份额来选择推送?友盟的那份数据小米市场份额第一,但是紧跟其后的三星、华为等市场份额加起来比小米要多,如果以市场份额来选择推送为什么只认准小米呢?\n
关于这点我文中说的很清楚,小米推送的优势是在 MIUI 系统不会被杀死,这个绝对的优势加上他的市场份额,才会推荐优先选择小米。三星市场份额也很大,但是你没有这个优势,对于三星手机,选择小米推送还是信鸽推送没绝对性的区别。\n
所以我文中的结论是:如果你只能选择一种推送的话,那么建议优先选择小米。如果你想更优化的话完全可以根据不同渠道选择不同的提送方案。\n
4. 自己写推送可以么?当然可以,但是不建议这么做,一是浪费资源,二是即使你有资源有能力去自己实现,但是你被杀死之后你很难启动。而使用第三方服务之后,有互相唤醒机制,只要有一个集成了该推送的 app 被用户打开,那么你家的 app 就会被唤醒,避免了永远保持沉默。你自己做的话就没有这优势,除非,你们有阿里、百度这样的全家桶。\n
5. 腾讯信鸽能被微信唤醒么?信鸽推送号称是微信的推送解决方案,但是注意只是说是用了微信的解决方案,并不是说微信也用的信鸽推送,这两者有天壤之别,所以那些幻想集成信鸽之后就能被微信唤醒的还是洗洗睡吧。\n
另外很多人纳闷为什么微信的服务不会被杀死?因为技术很牛逼么?\n
微信的技术确实很牛逼,在保活上面做了很多优化,但是不管你做的如何牛逼,某些 rom 系统级别的依然可以把你干掉。那为什么感觉微信永远不会被杀死呢?\n
其实最重要的一个原因是微信已经是各大厂商的白名单了,很多手机甚至出厂系统自带微信,对它的服务有特殊照顾。所以别幻想着能做成跟微信一样牛逼不被杀死,也别幻想着集成信鸽就能靠微信能把你家 app 唤醒。\n
6. 最后我的所有文章都是我一家之言,没有权威性质,你完全可以质疑,也欢迎探讨,毕竟技术本身就需要交流才能共同进步。但是你没有任何理由的一顿乱喷,说我写的垃圾,什么玩意,好歹说个理由吧,让你写又写不出来,你再牛逼,不分享出来有什么用?觉得垃圾的大可以取关,毕竟没人逼着你看,也没人问你收费,我这里不欢迎「嘴强王者」!最最后,再牛的保活方案都不能真正保活,充其量是多撑一会,这反而还会加重系统负担且耗电,如果你的产品本身很糟糕,这反而更激发用户卸载你的 app ,Android 的后台已经一团糟,这点跟 iOS 比简直相差太远,希望大家不要再去迫害它,改善体验,优化自家 app 才是正道!本文原创发布于微信公众号 AndroidDeveloper「googdev」,不仅是Android原创干货分享,也许是最有人情味的技术公众号,转载请务必注明出处!","updated":"T05:59:45.000Z","canComment":false,"commentPermission":"anyone","commentCount":20,"collapsedCount":0,"likeCount":39,"state":"published","isLiked":false,"slug":"","isTitleImageFullScreen":false,"rating":"none","titleImage":"/f82abd4ad0dfb84e096fd80_r.jpg","links":{"comments":"/api/posts//comments"},"reviewers":[],"topics":[{"url":"/topic/","id":"","name":"Android"},{"url":"/topic/","id":"","name":"Android 开发"}],"adminClosedComment":false,"titleImageSize":{"width":800,"height":600},"href":"/api/posts/","excerptTitle":"","column":{"slug":"stormzhang","name":"stormzhang"},"tipjarState":"inactivated","annotationAction":[],"sourceUrl":"","pageCommentsCount":20,"snapshotUrl":"","publishedTime":"T13:59:45+08:00","url":"/p/","lastestLikers":[{"bio":"Android程序员","isFollowing":false,"hash":"0eb14bbd097c6affbdb98c00082cf7eb","uid":938200,"isOrg":false,"slug":"wang-yuan-39-70-57","isFollowed":false,"description":"","name":"王元","profileUrl":"/people/wang-yuan-39-70-57","avatar":{"id":"f6c834d0a33e7fe6de1e","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"谷歌粉,android开发者,专注app开发架构","isFollowing":false,"hash":"eb274aee1a8d","uid":52,"isOrg":false,"slug":"sheng-fu-qiang","isFollowed":false,"description":"/ShengFQ","name":"盛富强","profileUrl":"/people/sheng-fu-qiang","avatar":{"id":"2eab7d1eed07bf9eb52fc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"自己动手,丰衣足食。","isFollowing":false,"hash":"6fd4d4fb72ddf374c4a5","uid":88,"isOrg":false,"slug":"shu-dai-ma-zhu-xian-sen-si","isFollowed":false,"description":"泯然众人矣。","name":"忄代码丶先森灬","profileUrl":"/people/shu-dai-ma-zhu-xian-sen-si","avatar":{"id":"b48902a6afe1c3da628473f","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"","isFollowing":false,"hash":"5dcf1b1de101d","uid":80,"isOrg":false,"slug":"he1s","isFollowed":false,"description":"","name":"He1S","profileUrl":"/people/he1s","avatar":{"id":"bb3a05f43a55","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"","isFollowing":false,"hash":"d7d74bb9afa","uid":68,"isOrg":false,"slug":"ling-yun-xuan-ya","isFollowed":false,"description":"","name":"凌云轩雅","profileUrl":"/people/ling-yun-xuan-ya","avatar":{"id":"d4a2059e6","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false}],"summary":"昨天的文章「」不少人的留言有不同的声音,这里补充一下,顺便表示下我的不服!\n 1. 收了小米多少钱?很多人留言表示这软广不错,收了小米多少钱?不管你们是开玩笑还是认真的,我只想告诉你们,这篇文章是我自己的实践加上业内同行…","reviewingCommentsCount":0,"meta":{"previous":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"/77df3cb15b1ac0bce056da8_r.jpg","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"Android"},{"url":"/topic/","id":"","name":"Android 开发"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"微信公众号: stormzhang","isFollowing":false,"hash":"926fa049f","uid":08,"isOrg":false,"slug":"stormzhang","isFollowed":false,"description":"个人博客:\n微信公众号: stormzhang\n不接受私信,有事公众号留言。","name":"stormzhang","profileUrl":"/people/stormzhang","avatar":{"id":"20d8a65bfbbeb","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"stormzhang","name":"stormzhang"},"content":"之前在群里有同学问我关于推送的一些问题,解答之后我觉得这个话题还挺有用,因为几乎大部分人都会遇到这个问题,那姑且就写篇文章总结给你们吧。
1. 为什么要用推送?推送功能可谓是现如今任何一个 App 的必备功能,因为每天可以推送消息,提升日活啊,用户长久没打开了,推个消息就把用户召回了啊。一般来说推送都是系统来做的,比如 iOS 的推送是苹果自己做的,系统级别的,任何时候都可以推送给用户。
而 Android 的推送本来 Google 自己也有一套推送服务,也是系统级别的,叫做 GCM ,Google Cloud Messaging,但是众所周知,Google 的服务在国内根本没法使用,也就意味着我们不得不用第三方的推送服务。
2. 为什么要使用第三方推送服务?因为 GCM 在国内的限制,所以这块也就是一个机会了,国内因此也衍生了很多推送服务公司。
大部分公司都会选择使用第三方推送服务,因为推送这个事自己做还挺麻烦的,需要服务器资源,开发以及后台管理、统计等,对于一些大公司来说本身有资源做这个事,而且出于安全考虑也会优先自己做,但是大部分中小型公司是不会浪费资源在这块的,尤其创业公司,还是把资源用在自己的核心业务上更急迫,所以大部分中小型互联网公司都会选择第三方推送服务。
3. 有哪些第三方的服务?
目前来说做的比较好的推送服务大概有小米推送、腾讯信鸽推送、百度推送、极光推送、友盟推送等。这些推送服务大都有以下特点:
免费当然部分公司也有收费的,号称更稳定、推送到达率更高,但大部分都还是用的免费版。
服务会被杀死由于 Android 系统的机制,后台推送 Service 会被各种主动的或是被动的行为给杀死,而服务一旦被杀死,意味着就接收不到推送消息。
多个 app 共用一条推送通道什么意思呢?就是如果有多个 app 都使用了同一家推送服务,那么这些 app 共用一条消息通道,即使你家的 app 推送服务被杀死了,那么只要用户打开了其他集成该推送服务的 app ,你家的推送就能接受到消息。
4. 哪家推送更好呢?每家的推送服务都号称推送到达率很高,号称自己家的推送服务更不容易被杀死,号称自己的推送更稳定更有保证,然而我要说的是,各家都差不多,技术上你能实现的,别家一样能实现,到达率也都差不多,据我观察平均推送到达率能达到 70% 左右都算不错的了,那么到底该怎么选择呢?
有一点比较特殊的是?有些推送服务有自己家品牌的手机,比如小米有自己的手机,而在 MIUI 系统上小米推送是作为系统级的服务,不会被杀死,毕竟一家人,总不至于傻到把自己家的服务给干掉吧?所以这就是一个巨大的优势了。类似的华为推送服务在自己家的手机系统上也不会被杀死。各大手机厂商都宣传自己家的手机市场份额第一,然而我要说的是如今市场上的 Android 手机只分小米手机跟其他手机,什么意思?就是小米手机是目前市场份额第一,而且远远领先其他手机,这个在我们自己家 app 的数据上看就是这样,而这里有一份友盟发布的 Android 设备活跃的排名数据,地址在这里:方便大家查看我截了张图:
上图可以看到,前十排名小米占了 7 席,总体小米手机确实是市场份额第一,其次是三星、华为紧随其后,接着 oppo、vivo、魅族平分秋色。
所以小米手机的市场份额,加上小米推送在 MIUI 上不被杀死这一大特性,致使选择小米推送是第一选择。
所以综合下来,如果你的 app 想省事的话那么建议直接集成小米推送。
如果你的 app 想要把推送更优化下,那么可以集成多个推送服务,针对不同的渠道用不同的推送,比如小米渠道用小米推送,华为渠道用华为推送,其他渠道用信鸽推送等,但是这种也比较麻烦,具体怎么做看你们自己的权衡了。
PS: 我以我 stormzhang 的帅来保证,本篇文章绝对没收任何广告费,全都是自己实践下来的良心推荐!本文原创发布于微信公众号 AndroidDeveloper「googdev」,不仅是Android原创干货分享,也许是最有人情味的技术公众号,转载请务必注明出处!","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T00:20:06+08:00","url":"/p/","title":"Android 推送到底哪家强","summary":"之前在群里有同学问我关于推送的一些问题,解答之后我觉得这个话题还挺有用,因为几乎大部分人都会遇到这个问题,那姑且就写篇文章总结给你们吧。 1. 为什么要用推送?推送功能可谓是现如今任何一个 App 的必备功能,因为每天可以推送消息,提升日活啊,用…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":0,"likesCount":0},"next":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"/f3e069bb77b0c799db2ff5f6eee7859b_r.jpg","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"Android"},{"url":"/topic/","id":"","name":"Android 开发"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"微信公众号: stormzhang","isFollowing":false,"hash":"926fa049f","uid":08,"isOrg":false,"slug":"stormzhang","isFollowed":false,"description":"个人博客:\n微信公众号: stormzhang\n不接受私信,有事公众号留言。","name":"stormzhang","profileUrl":"/people/stormzhang","avatar":{"id":"20d8a65bfbbeb","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"stormzhang","name":"stormzhang"},"content":"好文优秀开源项目可能是你见过的最酷炫的加载动画。酷炫的碎纸机动画。一个 简单、优雅、易用 的滚动数字控件!Android水波动画帮助类,一行代码实现View显示/隐藏/startActivity特效。一个支持四个方向循环滚动的自定义控件。本文原创发布于微信公众号 AndroidDeveloper「googdev」,不仅是Android原创干货分享,也许是最有人情味的技术公众号,转载请务必注明出处!","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T20:26:57+08:00","url":"/p/","title":"AndroidDeveloper Weekly No.2","summary":"好文优秀开源项目可能是你见过的最酷炫…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":0,"likesCount":0}},"annotationDetail":null,"commentsCount":20,"likesCount":39,"FULLINFO":true}},"User":{"stormzhang":{"isFollowed":false,"name":"stormzhang","headline":"个人博客:\n微信公众号: stormzhang\n不接受私信,有事公众号留言。","avatarUrl":"/20d8a65bfbbeb_s.jpg","isFollowing":false,"type":"people","slug":"stormzhang","bio":"微信公众号: stormzhang","hash":"926fa049f","uid":08,"isOrg":false,"description":"个人博客:\n微信公众号: stormzhang\n不接受私信,有事公众号留言。","profileUrl":"/people/stormzhang","avatar":{"id":"20d8a65bfbbeb","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"badge":{"identity":null,"bestAnswerer":null}}},"Comment":{},"favlists":{}},"me":{},"global":{},"columns":{"stormzhang":{"following":false,"canManage":false,"href":"/api/columns/stormzhang","name":"stormzhang","creator":{"slug":"stormzhang"},"url":"/stormzhang","slug":"stormzhang","avatar":{"id":"02ad8fdce4cac9a8a8d4","template":"/{id}_{size}.jpeg"}}},"columnPosts":{},"postComments":{},"postReviewComments":{"comments":[],"newComments":[],"hasMore":true},"favlistsByUser":{},"favlistRelations":{},"promotions":{},"switches":{"couldAddVideo":false},"draft":{"titleImage":"","titleImageSize":{},"isTitleImageFullScreen":false,"canTitleImageFullScreen":false,"title":"","titleImageUploading":false,"error":"","content":"","draftLoading":false,"globalLoading":false,"pendingVideo":{"resource":null,"error":null}},"config":{"userNotBindPhoneTipString":{}},"recommendPosts":{"articleRecommendations":[],"columnRecommendations":[]},"env":{"isAppView":false,"appViewConfig":{"content_padding_top":128,"content_padding_bottom":56,"content_padding_left":16,"content_padding_right":16,"title_font_size":22,"body_font_size":16,"is_dark_theme":false,"can_auto_load_image":true,"app_info":"OS=iOS"},"isApp":false},"sys":{}}Android(56)
这几天接了一下友盟,小米,华为三方的推送。
总的流程下来,小米的api是最友好的,华为的文档和demo有点脱节。这两个推送在特定的手机上都挺稳定的的。
友盟的就有点麻烦,过程中遇到几个问题
1,接入友盟之后,APK方法数超过64K了
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
minSdkVersion 14
targetSdkVersion 21
// Enabling multidex support.
multiDexEnabled true
dependencies {
compile 'com.android.support:multidex:1.0.0'
MultiDex.install(getTargetContext());
2,第二个问题是要自定义点击通知栏要调整到特定页面,需要重写
public void dealWithNotificationMessage(Context context, UMessage msg){
if ( msg.extra == null) {
super.dealWithNotificationMessage(context, msg)
Notification notification = new Notification.Builder(context)
.setContentTitle(msg.title)
.setContentText(msg.text)
.setSmallIcon(R.drawable.share_default_logo)
notification.flags |= FLAG_AUTO_CANCEL
notification.defaults = DEFAULT_ALL
notification.ledARGB = Color.BLUE
notification.ledOnMS = 5000
((NotificationManager) SeeYouApp.getInstance().getSystemService(NOTIFICATION_SERVICE)
).notify(0, notification)
3,要识别一下友盟的channel进程,允许它注册。
测试起来很麻烦,因为杀应用,如果我们原有的进程没有被杀,那么友盟的推送就不会被杀,我们的进程被杀,友盟也被杀。这叫我怎么测…后来同事提醒,可以相互唤醒。
所以就是安装一个友盟的官方的App,然后设置允许相互唤醒(这个各个手机的设置都不同,在设置里面找相互唤醒类似的字眼)
后台那边就是判断一下原有通道是不是通的,如果不通就走第三方渠道。
之前一直在测弱网络,所以我以为会有一个心跳的误差。其实杀APP,后台立刻就能知道长连接断了,因为socket断了,系统会发eof(从抓包上看就是FIN)。
5,其他有的没的
华为只支持企业级应用,所以我是用公司账号注册两个app,去测试的。华为客户端这边的识别就直接是包名,要有手机卡,手机必须是华为手机才能推到。
小米接入小米推送之后,手动杀进程居然只杀了前台应用,得去应用里面强制关闭。没接入之前我记得手动杀进程是什么都不剩的,也许是官方推送保活福利吧。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:103368次
积分:1897
积分:1897
排名:千里之外
原创:129篇
转载:20篇
评论:16条公司的 app 一直使用的是极光推送,最近反馈比较多的是推送消息收不到,看来需要找新的推送服务了,在国内目前手机品牌占有率比较多的是华为和小米,且这两家都有自己的推送服务,同时一个合作的友商说他们使用的是友盟推送,推送率还不错,那么就测试这三个推送服务了。
按照集成的难易程度排序
官网有提供了视频和文档,很详细,而且很简单。
在小米推送运营平台创建应用,, 获取到 AppID , AppKey
把从小米下载的 jar 放到 libs 下
在 AndroidManifest.xml 中添加权限
&uses-permission android:name="android.permission.INTERNET" /&
&uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&
&uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /&
&uses-permission android:name="android.permission.READ_PHONE_STATE" /&
&uses-permission android:name="android.permission.GET_TASKS" /&
&uses-permission android:name="android.permission.VIBRATE"/&
&permission android:name="com.xxx.xxx.permission.MIPUSH_RECEIVE" android:protectionLevel="signature" /&
&uses-permission android:name="com.xxx.xxx.permission.MIPUSH_RECEIVE" /&
配置推送服务需要的service和receiver
android:enabled="true"
android:process=":pushservice"
android:name="com.xiaomi.push.service.XMPushService"/&
android:name="com.xiaomi.push.service.XMJobService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"
android:process=":pushservice" /&
&!--注:此service必须在3.0.1版本以后(包括3.0.1版本)加入--&
android:enabled="true"
android:exported="true"
android:name="com.xiaomi.mipush.sdk.PushMessageHandler" /&
&service android:enabled="true"
android:name="com.xiaomi.mipush.sdk.MessageHandleService" /&
&!--注:此service必须在2.2.5版本以后(包括2.2.5版本)加入--&
android:exported="true"
android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver" &
&intent-filter&
&action android:name="android.net.conn.CONNECTIVITY_CHANGE" /&
&category android:name="android.intent.category.DEFAULT" /&
&/intent-filter&
&/receiver&
android:exported="false"
android:process=":pushservice"
android:name="com.xiaomi.push.service.receivers.PingReceiver" &
&intent-filter&
&action android:name="com.xiaomi.push.PING_TIMER" /&
&/intent-filter&
&/receiver&
自定义一个BroadcastReceiver类
public class MiMessageReceiver extends PushMessageReceiver {
private static final String TAG = "MiMessageReceiver";
private String mRegId;
private String mT
private String mA
private String mA
private String mStartT
private String mEndT
public void onNotificationMessageClicked(Context context, MiPushMessage message) {
Log.v(MyApplication.TAG,
"onNotificationMessageClicked is called. " + message.toString());
if (!TextUtils.isEmpty(message.getTopic())) {
mTopic = message.getTopic();
Log.e(TAG, mTopic);
} else if (!TextUtils.isEmpty(message.getAlias())) {
mAlias = message.getAlias();
Log.e(TAG, mAlias);
public void onNotificationMessageArrived(Context context, MiPushMessage message) {
Log.v(MyApplication.TAG,
"onNotificationMessageArrived is called. " + message.toString());
String log = "Arrived a notification message. Content is " + message.getContent();
if (!TextUtils.isEmpty(message.getTopic())) {
mTopic = message.getTopic();
} else if (!TextUtils.isEmpty(message.getAlias())) {
mAlias = message.getAlias();
public void onCommandResult(Context context, MiPushCommandMessage message) {
Log.v(TAG,
"onCommandResult is called. " + message.toString());
String command = message.getCommand();
List&String& arguments = message.getCommandArguments();
String cmdArg1 = ((arguments != null && arguments.size() & 0) ? arguments.get(0) : null);
String cmdArg2 = ((arguments != null && arguments.size() & 1) ? arguments.get(1) : null);
if (MAND_REGISTER.equals(command)) {
if (message.getResultCode() == ErrorCode.SUCCESS) {
mRegId = cmdArg1;
Log.e(TAG, "Register push success.");
Log.e(TAG, "Register push fail.");
log = message.getReason();
public void onReceiveRegisterResult(Context context, MiPushCommandMessage message) {
Log.v(TAG,
"onReceiveRegisterResult is called. " + message.toString());
String command = message.getCommand();
List&String& arguments = message.getCommandArguments();
String cmdArg1 = ((arguments != null && arguments.size() & 0) ? arguments.get(0) : null);
if (MAND_REGISTER.equals(command)) {
if (message.getResultCode() == ErrorCode.SUCCESS) {
mRegId = cmdArg1;
Log.e(TAG, "Register push success.");
Log.e(TAG, "Register push fail.");
在 AndroidManifest.xml 中注册该广播
android:name=".MiMessageReceiver"
android:exported="true"&
&intent-filter&
&action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE"/&
&/intent-filter&
&intent-filter&
&action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED"/&
&/intent-filter&
&intent-filter&
&action android:name="com.xiaomi.mipush.ERROR"/&
&/intent-filter&
&/receiver&
在 Application 中初始化推送服务
private void initMiPush() {
//初始化push推送服务
if (shouldInit()) {
MiPushClient.registerPush(this, MI_APP_ID, MI_APP_KEY);
LoggerInterface newLogger = new LoggerInterface() {
public void setTag(String tag) {
public void log(String content, Throwable t) {
Log.d(TAG, content, t);
public void log(String content) {
Log.d(TAG, content);
Logger.setLogger(this, newLogger);
private boolean shouldInit() {
ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
List&ActivityManager.RunningAppProcessInfo& processInfos = am.getRunningAppProcesses();
String mainProcessName = getPackageName();
int myPid = android.os.Process.myPid();
for (ActivityManager.RunningAppProcessInfo info : processInfos) {
if (info.pid == myPid && mainProcessName.equals(info.processName)) {
接入步骤(HMS-SDK版本:2.4.0.300):
把从华为 Push 推送官网下载的 aar ,位于:...\HMS-2.4.0.300\HWHMS-SDK-v2.4.0.300\libs\HMS-SDK-2.4.0.300.aar,放到工程目录的 aars 下(没有该目录的新建一个)
在 AndroidManifest.xml 文件的 Application 节点添加: meta-data 和自定义的 Receiver,如下(其中 meta-data 中的 appId 是在网页上创建应用的 id,我的是一个 8 位的数字):
&meta-data
android:name="com.huawei.hms.client.appid"
android:value="appId"&
&/meta-data&
&!-- 第三方相关 :接收Push消息(注册、Push消息、Push连接状态)广播 --&
&receiver android:name=".HuaweiPushReceiver"&
&intent-filter&
&!-- 必须,用于接收token --&
&action android:name="com.huawei.android.push.intent.REGISTRATION"/&
&!-- 必须,用于接收消息 --&
&action android:name="com.huawei.android.push.intent.RECEIVE"/&
&!-- 可选,用于点击通知栏或通知栏上的按钮后触发onEvent回调 --&
&action android:name="com.huawei.android.push.intent.CLICK"/&
&!-- 可选,查看push通道是否连接,不查看则不需要 --&
&action android:name="com.huawei.intent.action.PUSH_STATE"/&
&/intent-filter&
&meta-data
android:name="CS_cloud_ablitity"
android:value="@string/hwpush_ability_value"/&
&/receiver&
在 AndroidManifest.xml 文件中添加权限
&uses-permission android:name="android.permission.READ_PHONE_STATE" /&
&uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&
&uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /&
&uses-permission android:name="android.permission.WAKE_LOCK" /&
&uses-permission android:name="android.permission.INTERNET"/&
&uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&
在 MainActivity 或者 BaseAcitivty 中初始化华为 Push ,放在 onCreate() 中初始化华为 Push
private void initHuaweiPush(Context context) {
HuaweiIdSignInOptions options = new HuaweiIdSignInOptions.Builder(HuaweiIdSignInOptions.DEFAULT_SIGN_IN)
mClient = new HuaweiApiClient.Builder(context)
.addApi(HuaweiPush.PUSH_API)
.addConnectionCallbacks(new HuaweiApiClient.ConnectionCallbacks() {
public void onConnected() {
getToken();
runOnUiThread(new Runnable() {
public void run() {
tv.setText("HUAWEI onConnected, IsConnected: " + mClient.isConnected());
Log.e(TAG, "HUAWEI onConnected, IsConnected: " + mClient.isConnected());
public void onConnectionSuspended(final int i) {
runOnUiThread(new Runnable() {
public void run() {
tv.setText("HUAWEI onConnectionSuspended, cause: " + i + ", IsConnected:" +
mClient.isConnected());
Log.e(TAG, "HUAWEI onConnectionSuspended, cause: " + i + ", IsConnected:" +
mClient.isConnected());
.addOnConnectionFailedListener(new HuaweiApiClient.OnConnectionFailedListener() {
public void onConnectionFailed(@NonNull final ConnectionResult
connectionResult) {
runOnUiThread(new Runnable() {
public void run() {
tv.setText("HUAWEI onConnectionFailed, ErrorCode: " + connectionResult.getErrorCode());
Log.e(TAG, "HUAWEI onConnectionFailed, ErrorCode: " + connectionResult.getErrorCode());
mClient.connect();
protected void onStart() {
super.onStart();
mClient.connect();
private void getToken() {
if (!isConnected()) {
tv.setText("get token failed, HMS is disconnect.");
// 同步调用方式,不会返回token,通过广播的形式返回。
new Thread(new Runnable() {
public void run() {
PendingResult&TokenResult& token = HuaweiPush.HuaweiPushApi.getToken(mClient);
token.await();
}).start();
public boolean isConnected() {
if (mClient != null && mClient.isConnected()) {
新建 HuaweiPushReceiver ,继承 PushReceiver,重写 onToken() ,onPushMsg(),onEvent(),onPushState(),在 onToken() 中可以获取到 token。
public class HuaweiPushReceiver extends PushReceiver {
private static final String TAG = "Huawei PushReceiver";
public void onToken(Context context, String token, Bundle extras) {
String belongId = extras.getString("belongId");
String content = "get token and belongId successful, token = " + token + ",belongId = " + belongId;
Log.d(TAG, content);
public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {
String content = "-------Receive a Push pass-by message: " + new String(msg, "UTF-8");
Log.d(TAG, content);
} catch (Exception e) {
e.printStackTrace();
public void onEvent(Context context, PushReceiver.Event event, Bundle extras) {
if (Event.NOTIFICATION_OPENED.equals(event) || Event.NOTIFICATION_CLICK_BTN.equals(event)) {
int notifyId = extras.getInt(BOUND_KEY.pushNotifyId, 0);
if (0 != notifyId) {
NotificationManager manager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(notifyId);
String content = "--------receive extented notification message: " + extras.getString
(BOUND_KEY.pushMsgKey);
Log.d(TAG, content);
super.onEvent(context, event, extras);
public void onPushState(Context context, boolean pushState) {
String content = "---------The current push status: " + (pushState ? "Connected" :
"Disconnected");
Log.d(TAG, content);
} catch (Exception e) {
e.printStackTrace();
获取到 token 以后就连接成功了。可以测试推送了。
非华为手机使用华为推送需要安装-华为移动服务.apk
各个版本EMUI对push的支持情况
华为手机上:
Emui3.0上,Push广播有很大概率被限制,如: Mate7 3.0版本,荣耀6plus,P7 3.0版本,4X, 4A等。
Emui3.1上,Push广播基本不被限制,但个别型号机型存在问题,如:荣耀5x等。
Emui4.0及以上,Push广播有较高概率被限制,不被限制的机型如:荣耀畅玩4C,荣耀畅玩4X,Mate S,P8 MAX等。
Emui4.1 , ROM升级到了最新版本的(80%已升),通知消息不走广播,不会被限制,透传消息走广播,会被限制。
Emui5.0以上 ,通知消息不走广播,不会被限制,透传消息走广播,会被限制。
如广播被限制,需要将应用设为开机启动项。所以对于及时性或到达率要求非常高的应用,我们建议应用要考虑替代方案。
非华为手机:
第三方手机(如:小米、OPPO、三星等),由于rom的限制,需要将应用 设为开机启动项。
Samsung S4(Android 5.0)
HTC D820u(Android 6.0)
Huawei P8(Android 6.0)
Xiaomi Note(Android 7.0)
Samsung S7(Android 7.0)
LG Nexus 6(Android 7.0)
Huawei Mate8(Android 7.0)
Huawei Mate9(Android 7.0)
三家推送比较
华为推送在非华为手机上必须安装华为移动服务,这点比较的坑,用户可能不会同意安装的,那就没得玩了,只适合在华为手机上使用。
华为推送还得区别 Emui 的版本,这玩意也不是个小坑,虽然官方QQ群公告说 Emui 5.0 以后都可以收到消息推送,但是不知道靠谱不靠谱
友盟推送的话,在测试阶段,发现三星S7(Android 7.0),三星S4(Android 5.0),华为P8(Android 6.0)无法获取到 token,没有 token ,那就推送不了了。
小米推送还可以,但是在三星 S4(Android 5.0) 上无法接收到推送。
综上,app 需要集成华为推送和小米推送比较的靠谱点,针对华为手机使用华为推送,其他手机使用小米推送。
使用中的大坑,在华为手机上假如华为移动服务不是最新版本或者被卸载了,推送服务无法使用。必须在 app 中提示用户更新或安装,真是一个大坑,关键是更新界面丑的要死,还会出现更新失败的情况,坑人呀。
针对小米推送,在非小米设备上会出现重启以后无法获得推送,因为是重启以后,小米的 XMPushService 没有起来,目前采用的办法是监听手机启动广播,然后启动小米的 XMPushService。
阅读(...) 评论()