API 29及以上应用被杀死后前台服务无法启动Activity怎么解决
问题原因
Android 10(API 29)开始新增后台Activity启动限制,应用处于后台状态时,即便已启动前台服务,也无法直接调用startActivity()拉起页面,必须满足官方指定的例外条件才可执行。
适配方案
方案一:申请悬浮窗权限(最通用)
- 新增清单权限
在AndroidManifest.xml中添加如下权限:
<!-- API29+ 后台启动Activity必需的悬浮窗权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 若targetSdkVersion >= 31,还需添加以下权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" android:usesPermissionFlags="neverForLocation" />
- 引导用户授权悬浮窗权限
该权限为特殊权限,需要引导用户手动到系统设置页开启,判断和跳转逻辑如下:
val REQUEST_OVERLAY_CODE = 1001 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(context)) { val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:${context.packageName}")) startActivityForResult(intent, REQUEST_OVERLAY_CODE) } }
- 调整Service执行顺序
你当前代码是先启动Activity再启动前台服务,调用startActivity时服务还未进入前台状态,会被判定为后台启动拦截,需要调换执行顺序:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { if (Build.VERSION.SDK_INT >= 26) { val channel = NotificationChannel( CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT ) val manager = getSystemService(NotificationManager::class.java) manager.createNotificationChannel(channel) } val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("setContentTitle") .setContentText("setContentText") .setSmallIcon(R.mipmap.ic_launcher) // 必须设置小图标,否则通知无法正常展示 .build() // 先启动前台服务,让应用进入前台状态 startForeground(NOTIFICATION_ID, notificationBuilder) // 再启动Activity val mIntent = Intent(applicationContext, MyActivity::class.java) mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK startActivity(mIntent) return START_NOT_STICKY }
方案二:使用全屏通知(无需悬浮窗权限,适合闹钟/来电类场景)
如果不想申请悬浮窗权限,可以给前台服务的通知设置全屏意图,系统会自动弹出对应Activity,修改通知构建逻辑即可:
val activityIntent = Intent(this, MyActivity::class.java) val pendingIntent = PendingIntent.getActivity( this, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("setContentTitle") .setContentText("setContentText") .setSmallIcon(R.mipmap.ic_launcher) .setPriority(NotificationCompat.PRIORITY_HIGH) .setCategory(NotificationCompat.CATEGORY_ALARM) // 设置全屏意图,true表示需要直接弹出Activity .setFullScreenIntent(pendingIntent, true) .build() startForeground(NOTIFICATION_ID, notificationBuilder)
内容的提问来源于stack exchange,提问作者Ahmet B.
相关产品推荐
相关产品推荐

