从后台启动Activity的限制
Android 10 (API 级别 29) 及更高版本对后台应用可启动 Activity进行限制。Android10中, 当App的Activity不在前台时,其启动Activity会被系统拦截,导致无法启动。当然,这么做的目的是为了用户在使用其他APP过程中,不会被强制打断。
例如,典型的闹钟类APP。预定闹钟本该启动一个Activity对用户进行提醒,结果Activity被拦截,无法执行之后响铃等操作,导致整个程序失去意义。
解决方案一:
官方给予的折中方案是使用全屏Intent(full-screen intent), 既创建通知栏通知时, 加入full-screen intent 设置。示例代码如下(基于官方文档修改):
Intent fullScreenIntent = new Intent(this, CallActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Incoming call")
.setContentText("(919) 555-1234")
//以下为关键的3行
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(fullScreenPendingIntent, true);
NotificationManager notifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notifyManager.notify(notifyId, builder.build());
注意:在Target SDk为29及以上时,需要在AndroidManifest上增加USE_FULL_SCREEN_INTENT申明
//AndroidManifest中
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
解决方案二:
向用户申请 SYSTEM_ALERT_WINDOW 权限,系统就不会拦截该程序后台启动的Activity
示例代码如下:
- 在清单中申请权限
//AndroidManifest中
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- 判断是否拥有权限,未授权则请求权限(>=Android6.0)
//检查是否已经授予权限
if (!Settings.canDrawOverlays(this)) {
//若未授权则请求权限
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}
其中,Settings.canDrawOverlays(this)方法是在API level 23也就是Android M中新加入的用于检查当前是否拥有出现在“出现在其他应用上”权限的方法。在6.0以前的系统版本,悬浮窗权限是默认开启的,直接使用即可。

image.png