Android 8 Oreo中Gcm RegistrationIntentService失效问题求助
我来帮你搞定这个问题!Android 8.0(API 26)开始引入了严格的后台服务限制,这正是你的RegistrationIntentService在高版本系统上失效的核心原因。先看看你的代码:
public class RegistrationIntentService extends JobIntentService { private static final String TAG = "RegIntentService"; private static final String[] TOPICS = {"global"}; private static Context context1; private String SENDER_ID; private AppActivity appActivityContext; private SharedPreferences.Editor editor; public RegistrationIntentService() { super(); } @Override protected void onHandleWork(@NonNull Intent intent) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); try { sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, true).apply(); // [END register_for_gcm] } catch (Exception e) { Log.d(TAG, "Failed to complete token refresh", e); sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false).apply(); } Intent registrationComplete = new Intent(QuickstartPreferences.REGISTRATION_COMPLETE); LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete); } ... }
核心问题分析
在Android 8+系统中,JobIntentService不再以普通后台服务的方式运行,而是通过JobScheduler来调度执行。如果你的启动方式不对,或者Manifest声明缺失关键配置,系统就会拦截任务,导致onHandleWork完全不执行。而Android 8以下版本不受这个限制,所以能正常运行。
具体修复步骤
1. 修正Service的Manifest声明
确保你的RegistrationIntentService在AndroidManifest.xml中声明时,加上android.permission.BIND_JOB_SERVICE权限——这是JobScheduler绑定服务的必要条件,缺失的话任务根本无法被调度:
<service android:name=".RegistrationIntentService" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" />
2. 改用正确的启动方式
不要再用startService()启动服务,必须使用JobIntentService提供的enqueueWork()方法,它会根据系统版本自动选择启动方式(8以下用Service,8以上用JobScheduler):
// 定义一个唯一的Job ID,比如1001(自己随便选个整数就行) private static final int REGISTRATION_JOB_ID = 1001; // 启动服务的代码 Intent intent = new Intent(context, RegistrationIntentService.class); // 替换原来的startService调用 RegistrationIntentService.enqueueWork(context, RegistrationIntentService.class, REGISTRATION_JOB_ID, intent);
3. 优化构造函数(可选但推荐)
默认构造函数的super()会使用通用的服务名称,改成显式传入TAG更方便日志排查:
public RegistrationIntentService() { super(TAG); // 用自定义TAG作为服务名称 }
额外注意事项
如果你的任务执行时间较长(超过10秒),在Android 8+上可能会被系统终止,这时需要在onHandleWork开头调用startForeground(),把服务提升为前台服务(需要申请FOREGROUND_SERVICE权限)。不过从你的代码来看,只是处理Token刷新,应该属于短任务,暂时不需要这一步。
按照上面的步骤修改后,你的RegistrationIntentService应该就能在所有版本的Android系统上正常执行onHandleWork方法了。
内容的提问来源于stack exchange,提问作者Shubham Goel

