安卓应用关闭状态下通话结束后无法唤起悬浮Widget如何解决?
问题根因
- 你在
CallReceiver类中自定义了一个空实现的startService()方法,该方法直接抛出运行时异常,没有实际执行启动服务的逻辑; - 没有使用
onReceive回调传入的Context对象调用系统的启动服务API,而是调用了自己实现的无效方法; - Android 8.0及以上系统对后台启动普通Service做了限制,没有适配对应规则会导致服务启动失败。
修复方案
第一步:删除自定义的无效startService方法
删掉CallReceiver中如下这段无意义的代码:
//*****Action: Start a particular service public ComponentName startService(Intent service) { throw new RuntimeException("Stub!"); }
第二步:修改startWidget方法,适配高版本系统启动规则
将startWidget方法修改为如下实现:
void startWidget(Context cotx) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 悬浮窗权限校验 if (!Settings.canDrawOverlays(cotx)) { // 无悬浮窗权限时可按需增加引导用户开启的逻辑,此处直接返回 return; } } Intent widgetIntent = new Intent(cotx, FloatingViewService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Android 8.0及以上后台启动服务必须调用startForegroundService cotx.startForegroundService(widgetIntent); } else { cotx.startService(widgetIntent); } }
第三步:给FloatingViewService适配前台服务要求
Android 8.0及以上调用startForegroundService后,必须在5秒内调用startForeground()展示前台通知,否则会触发ANR,需要在FloatingViewService的onCreate或onStartCommand中增加如下逻辑:
@Override public void onCreate() { super.onCreate(); // 适配Android 8.0+前台服务要求 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { String channelId = "floating_widget_channel"; NotificationChannel channel = new NotificationChannel(channelId, "悬浮窗服务", NotificationManager.IMPORTANCE_LOW); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, channelId) .setContentTitle("悬浮窗运行中") .setSmallIcon(R.mipmap.ic_launcher) // 替换为应用自身图标 .setPriority(NotificationCompat.PRIORITY_LOW) .build(); startForeground(1, notification); } // 保留原有悬浮窗创建逻辑 }
第四步:检查AndroidManifest.xml配置
确认已注册对应权限、服务和广播接收器:
<!-- 悬浮窗权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 读取通话状态权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 监听呼出通话权限 --> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <!-- 前台服务权限(Android 9.0+必填) --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- 注册悬浮窗服务 --> <service android:name=".FloatingViewService" android:enabled="true" android:exported="false" /> <!-- 注册通话状态广播接收器 --> <receiver android:name=".CallReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.PHONE_STATE" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver>
内容的提问来源于stack exchange,提问作者D Com
相关产品推荐
相关产品推荐

