【问题描述】
这个问题只在Andoid上出现,因为iOS端使用APNS,所以推送都能及时送达。
在使用个推推送时,一旦用户把应用切换到后台,那么推送的时候就会显示 success_offline 也就是 cilentID离线。
而实际上,应用这时候还没有被系统杀死,但是再也无法接受到推送的消息。哪怕重新点开APP,也不会接受到消息,不管是之前的消息,还是从此之后推送的消息。
【解决方案】
首先,保证APP后台的进程没有被杀死。个推官方给出了各个系统的设置 点击这里查看
强烈大家先去读一读 蜡笔小鑫的《推送使用中的各种坑》 @蜡笔小鑫
-
简单版
如果不要求后台还能接收实时推送,只是想在用户重新点开APP时能够接受到之前的消息,并且让用户能够继续接收推送。那么只需要在APP切换到前台的时候,重新初始化个推sdk。
代码如下:
/** * resume 应用从后台切换到前台的事件 */ document.addEventListener("resume", function() { var pushManager = plus.android.importClass("com.igexin.sdk.PushManager"); var context = plus.android.runtimeMainActivity(); pushManager.getInstance().initialize(context); }, false);
-
复杂版
如果想要后台还能实时接收推送,那么只能进行离线打包,修改项目的 AndroidManifest.xml 文件。
增加一行代码,如下:
<!-- 整段位置在225行左右 --> <activity android:name="io.dcloud.PandoraEntryActivity" android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation|mcc|mnc|fontScale" android:hardwareAccelerated="true" android:label="5+Debug" android:launchMode="singleTask" android:screenOrientation="user" android:process=":pushservice" <!-- 这一行就是增加的代码 --> android:theme="@style/DCloudTheme" android:windowSoftInputMode="adjustResize" > </activity>
【解决过程】
原本以为是以为个推的SDK版本问题。5+SDK集成的个推版本是2.7.0.0,而现在官方发布的版本是2.9.3.0。但是把个推官方的SDK下载编译之后,后台仍然不能接受消息。
我用的开发机是小米5,在“更多应用”中检查的时候,发现当应用后台化的时候,“运行中”的应用列表中会显出APP的名字,显示“1个进程和0个服务”。 然后大概五秒钟后,应用就会从“运行中”列表消失,出现在“已缓存”的列表中。
但是个推的SDK是有一个后台服务的,名字叫做 NoticationCenter, 用来管理推送消息。也就是说,我们的应用没有成功唤起 NoticationCenter 这个服务。
但是鄙人只是了解过安卓开发的一点点知识 (web全栈就已经够费精力了好嘛~ 老板加工资好嘛~) ,只能尝试使用 Native.js 拉起个推的 PushService ,然并卵,失败了。
拉起服务的代码是这样的 :
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass('android.content.Intent');
var intent = new Intent();
var serviceName = 'com.igexin.sdk.PushService';//把这里换成其他Service的名字,也可以实现拉取自定义的Service
intent.setClassName(main, serviceName);
main.startService(intent);
注 : 把serviceName换成 'com.igexin.sdk.PushServiceForUser', 能够拉起一个NoticationCenterForUser服务,原本以为是和PushService一样的,结果发现这个服务对于推送啥一点用都没有……
然后又进行对比,发现个推的官方Demo里,在 AndroidManifest.xml 里,对于SDK的两个activity又些许的差别。
第一部分:
<!-- 第三方应用配置 -->
<activity
android:name=".GetuiSdkDemoActivity"
android:label="@string/app_name"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
第二部分
<activity
android:name="com.igexin.sdk.GActivity"
android:excludeFromRecents="true"
android:exported="true"
android:process=":pushservice" <!--就是这里,process属性-->
android:taskAffinity="com.igexin.sdk.PushActivityTask"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
这里的process属性的名字和核心推送服务一样
<!-- 配置SDK核心服务 -->
<service
android:name="com.igexin.sdk.PushService"
android:exported="true"
android:label="NotificationCenter"
android:process=":pushservice"> <!-- 这里也有process属性 -->
<intent-filter>
<action android:name="com.igexin.sdk.action.service.message"/>
</intent-filter>
</service>
然后我google了一下,这个属性的作用是:
android:process
应在其中运行 Activity 的进程的名称。正常情况下,应用的所有组件都在为应用创建的默认进程名称内运行,您无需使用该属性。 但在必要时,您可以使用该属性替换默认进程名称,以便让应用组件散布到多个进程中。
如果为该属性分配的名称以冒号(“:”)开头,则会在需要时创建应用专用的新进程,并且 Activity 会在该进程中运行。如果进程名称以小写字符开头,Activity 将在该名称的全局进程中运行,前提是它拥有相应的权限。这可以让不同应用中的组件共享一个进程,从而减少资源占用。
<application> 元素的 process 属性可为所有组件设置一个不同的默认进程名称。
所以,进行猜测,就因为主activity没有跑在 pushservice 进程里,才导致后台推送服务不能成功启动。
给主activity添加了
android:process=":pushservice"
这个属性,发现 NoticationCenter 进程正常启动了。并且应用后台化之后,服务正常运行,也能正常收到推送信息。
问题解决,不过不是很了解安卓开发,不知道这样会有什么副作用。不过目前看来,内存消耗和网络连接都正常,还没观察到什么严重后果。
前前后后花费了两个通宵和一个白天的时间,程序猿没人权啊~
27 个评论
要回复文章请先登录或注册
上上
上上
simiii
有问
赵明
有问
赵明
有问
1***@qq.com
1***@qq.com