最近为了解决公司APP在一些手机出现的推送问题重新集成了最新版的友盟推送SDK,花费了几天时间终于把集成和测试工作完成,最终在华为,Nexus,三星,小米,HTC,魅族等10多部手机上测试并达到了预想效果,这里把期间遇到的问题和集成注意事项记录下来方便自己总结和迭代更新,也希望能给碰到相同问题的朋友带去一点帮助,在此特别感谢友盟团队的技术人员范亚杰(向睿)以及产品运营赵横(沐惶)对我给予的帮助,话不多说,进入正题:
一、SDK集成
SDK版本:V3.1.0a
官网下载地址:http://dev.umeng.com/push/android/sdk-download
具体集成步骤参考官网:http://dev.umeng.com/push/android/integration
集成过程并不复杂,大体如下
1、在官网(http://push.umeng.com)上使用应用包名创建应用,获取应用对应的AppKey和Umeng Message Secret。
2、下载SDK的压缩文件并解压缩(解压后的文件路径不能有中文),把解压缩后得到的目录下的PushSDK当做Module导入到自己的工程。
3、在官网PushSDK下载处,下载全平台so文件,添加缺少的so文件夹至 PushSDK下,使PushSDK的so文件夹与主工程的so文件夹保持一致。这里是否缺少so文件夹以及缺少那些文件夹可以通过解压缩自己项目的release apk,看看lib下有哪些so文件夹来确定,保证每个文件夹都有推送SDK的so文件即可(参考后文注意事项第5点)。全平台so库下载地址:http://dev.umeng.com/system/resources/W1siZiIsIjIwMTcvMDMvMTQvMTBfMzdfNDBfMjg5X3NvX2FsbF9wbGF0Zm9ybXMuemlwIl1d/so_all_platforms.zip
如图所示,则需要添加arm64-v8a以及arm64-v7a两个文件夹
4、配置Appkey和Secret,添加Channel ID
在工程的Application Module的AndroidManifest.xml中的<Application>标签下添加:
<meta-data
android:name="UMENG_APPKEY"
android:value="xxxxxxxxxxxxxxxxxxxxxxxxxxxx">
</meta-data>
<meta-data
android:name="UMENG_MESSAGE_SECRET"
android:value="xxxxxxxxxxxxxxxxxxxxxxxxxxxx">
</meta-data>
<meta-data
android:name="UMENG_CHANNEL"
android:value="Channel ID" >
</meta-data>
把步骤1中的AppKey和Umeng Message Secret添加到UMENG_APPKEY和UMENG_MESSAGE_SECRET的相应value。你可以自定义Channel ID来标识App的推广渠道,作为推送消息时给用户分组的一个维度添加到UMENG_CHANNEL的value处。
5、配置build.gradle
在Application Module的build.gradle文件的dependencies下添加compile project(':PushSDK'),另外必须在defaultConfig中设置applicationId并保证和自己的包名一致,否则PushSDK依赖库AndroidManifest中${applicationId}将不能正常替换成包名,例如:
6、注册推送服务(是否开启推送都要调用注册方法)
如果项目中没有用户开启关闭推送功能则只需要调用register方法,不用调用enable或者disable,否则按需调用enable和disable方法,例如我们项目有设置推送开关
7、统计应用启动数据(在BaseActiivty调用)
8、添加混淆配置(拷贝官网配置即可)
9、打包测试
测试可按照官网说明,根据deviceToken定向推送。
二、测试
测试条件:WIFI条件
测试内容:测试模式下推送消息查看手机通知栏是否有消息送到,根据deviceToken查询长连接Service在线状态
测试机型:红米note2,三星SM-E7009,华为Mate7,华为C199s,魅族M2 note,
ZTE N918St,三星Glaxy S6 edge+,海信 I639T,Coolpad8297-W01,HTC D816V,华为 TIT-CL00,HTC 2PQ93,Nexus 6P
测试系统版本范围:4.X-6.X
测试步骤:APP首次安装—>按home键,APP退至后台—>点击系统返回,退出APP—>
从最近打开列表清除进程—>重新打开APP—>设置-应用程序-清除数据—>重新打开APP
结果如下:
测试结果总结如下:
(1)所有手机在“APP首次安装”以及“按home键,APP退至后台”的操作都能正常获取deviceToken并保证长连接Service处于在线状态,并能及时收到推送消息。
(2)几乎所有手机在“点击系统返回键,退出APP”后长连接Service都能从离线状态恢复成在线状态,这个过程耗时10秒左右,并能收到离线时发送的历史消息以及在线状态的及时消息。一小部分特殊机型需要允许自启动或者关联启动才能在线,特殊机型参考后文。
(3)超过半数的手机能在用户“从最近打开列表清除进程”的操作后长连接Service能从离线状态恢复成在线状态,并接受到及时消息,原生系统手机基本都能正常工作,比如Nexsus,三星,HTC等等,不能正常工作的多为定制化厂商系统比如华为,小米等部分手机,因为这些手机系统底层做了限制,基本上无能为力。
(4)绝大多数手机在用户进行“设置-应用程序-清除数据”操作后长连接Service都处于离线,推送都不能送达,一小部分手机(原生系统手机)能正常工作。
(5)所有手机都能重新打开APP的时候保证长连接Service在线并接收到离线或者及时消息(不管是点击系统返回键退出后还是清除最近使用列表进程还是清除数据后都正常)。
(6)如果手机上有装有其他集成了友盟推送SDK的应用,比如UC浏览器,暴风影音,鲁大师等阿里系的应用基本都能一直保持长连接Service在线,从而正常工作,极大的提高推送成功率。因为友盟推送消息路由机制是复用长连接,能互相唤醒,只是宿主不同而已。
注:原生系统机器不会对推送做任何限制,长连接Service基本上不会被杀死,因为杀死还能自动起来,推送成功率很高(清除数据除外,因为这跟安装完后没打开差不多)。
三、注意事项汇总
1、 Android特殊机型整理&集成注意事项(不定期更新)
参考:http://bbs.umeng.com/thread-21334-1-1.html
2、 必须
在项目Application类的 onCreate()
方法中注册推送服务,无论推送是否开启都需要调用register方法
3、 device-token的生成规则及其变化条件
device token是【友盟+】生成的用于标识设备的id,长度为44位,不能定制和修改。同一台设备上不同应用对应的device token不一样。
(1)device-token是SDK在初始化的时候向服务器端发起注册请求,由服务器端生成之后颁发给客户端的。 SDK向服务器端注册的时候,要把设备的标识id(umid + utdid)和app的标识(appkey,包名)作为参数告知服务器,服务器以设备id和appkey为基础,结合一定的算法生成device-token。所以device-token可以近似认为是“设备id + appkey”的结合。
(2)设备device-token变化有两种最可能的情况:一种是设备卸载过,又重新安装,token可能会变化;另一种是设备没有SD卡,设备id变化导致的device-token变化。另外我发现清除数据再次打开APP,deviceToken也有概率性变化,应该也是属于设备id变化导致,经过测试,Nexus 6P手机清除数据或者卸载APP后每次都会变化。而其他手机变化的几率比较小。另外register方法的回调不一定每次都会返回deviceToken(有时候为null),只有进程被杀,重启app,才会有返回值(这是友盟技术人员告诉我的),如果没有被杀死则会返回null,所以不能在回调中存储deviceToken,而应该是通过mPushAgent.getRegistrationId()来获取。
参考: http://bbs.umeng.com/thread-11061-1-1.html 关于deviceToken的变化这个帖子说明的很详细,必须知悉。
4、 So库的引用导致的accs bindapp error以及获取不到deviceToken问题
解压缩我们的APK,发现APP主项目和依赖库总共引入了4个平台so文件,SDK标准提供了两个
所以得下载全平台的so库,添加另外两个文件夹到PushSDK,也能解决部分手机上获取不到DeviceToken的bug,比如红米note2(4个文件夹基本能满足需求了,关于这点我也向友盟技术人员确认过了)。
参考:http://bbs.umeng.com/thread-23018-1-1.html
5、 官网集成文档说明请勿在调用register方法时做进程判断处理,主进程和channel进程均需要调用register方法才能保证长连接的正确建立,事实上是可以只在主进程和channel进程两个中调用register方法即可(官方回复)。
6、 关闭推送方法disable调用后会同步到友盟SDK,如果没有调用enable打开推送功能是不会再次开启推送的,极端操作是我在设置中关闭推送,这个时候我清除APP数据功能,如果deviceToken没变化的手机上打开APP时没有调用enable则会出现推送不了的情况,因为会提示“用户未注册”,虽然在没调用disable时,不用调用enable方法就能推送,那么这个时候就需要在初始化时候加上一定条件条件判断,例如:
7、 Register方法必须放在Application中执行,如果滞后到MainActivity中则只能打开APP活着App处于前台才能收到推送消息,这个问题对于有特殊要求的应用有一定印象,比如说手机预装应用,因为预装应用中的联网,读取设备信息等操作都必须等待用户同意之后才能进行,所以register方法可能需要滞后,当然另外一种解决办法是第一次打开不进行register方法,直到用户某次允许后才初始化,那么在这之前推送功能则无效,这个问题也需要具体分析对待。
8、 读写SD卡权限以及read phone state权限都是非必须权限,没有也基本不影响推送功能,当然有最好,这是友盟技术人员告诉我的。
9、 清除数据后理论上进程会被杀死,但有的机子上也不一定,所以清除数据,一般都是要打开重新注册推送才能正常工作的。
10、SDK默认在“23:00”到“7:00”之间收到通知消息时不响铃,不振动,不闪灯。如果需要改变默认的静音时间,可以使用以下接口:
public void setNoDisturbMode(int startHour, intstartMinute, int endHour, int endMinute)
11、 默认情况下,同一台设备在1分钟内收到同一个应用的多条通知时,不会重复提醒,同时在通知栏里新的通知会替换掉旧的通知。可以通过如下方法来设置冷却时间:
mPushAgent.setMuteDurationSeconds(int seconds);
12、 mPushAgent.enable(newIUmengCallback())回调失败,返回300,bind Agoo service fail也不影响推送功能的使用。
13、集成测试可以PushAgent.setDebugMode(true)在logcat中过滤message标签查看具体的日志,也可以过滤在channel进程中查看所有推送SDK的操作日志,包括网络请求、响应的json以及心跳检测,ping等操作,对于长连接的保活能有一定的指导作用。
14、 同一个设备deviceToken变化后可以检测到在线,但是发送提示“设备号格式错误”。