从 Android 10 开始,系统会增加针对从后台启动 Activity 的限制。此项行为变更有助于最大限度地减少对用户造成的中断,并且可以让用户更好地控制其屏幕上显示的内容。只要您的应用启动 Activity 是因用户互动直接引发的,该应用就极有可能不会受到这些限制的影响。

谷歌官方建议将从后台启动的Activity改为显示通知。还可以选择提供全屏Intent。
以下以全屏Intent为适配范围。

1、影响范围
        在Android Q 上运行的所有应用,包括以 Android 9(API 级别 28)或更低版本为目标平台的应用。即使应用以 Android 9 或更低版本为目标平台并且最初安装在运行 Android 9 或更低版本的设备上,该行为变更仍会在设备升级到 Android Q 后生效。

2、增加权限
        如果应用以 Android 10 或更高版本为目标平台并使用涉及全屏 intent 的通知,则必须在应用的清单文件中请求 USE_FULL_SCREEN_INTENT 权限。这是普通权限,因此,系统会自动为请求权限的应用授予此权限。

即在AndroidManifest.xml中增加USE_FULL_SCREEN_INTENT权限:

<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>

如果以 Android 10 或更高版本为目标平台的应用尝试创建使用全屏 intent 的通知而未请求必要权限,则系统会忽略此全屏 intent 并输出以下日志消息:

Package your-package-name: Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission

3、创建全屏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")
         .setPriority(NotificationCompat.PRIORITY_HIGH)
         .setCategory(NotificationCompat.CATEGORY_CALL)
     
         // Use a full-screen intent only for the highest-priority alerts where you
         // have an associated activity that you would like to launch after the user
         // interacts with the notification. Also, if your app targets Android 10
         // or higher, you need to request the USE_FULL_SCREEN_INTENT permission in
         // order for the platform to invoke this notification.
         .setFullScreenIntent(fullScreenPendingIntent, true);
     
     Notification incomingCallNotification = notificationBuilder.build();

> 注意:创建通知时,请务必添加描述性标题和消息。

4、机型适配
(1)Android 10 适配攻略中提到部分机型直接设置setPriority无效(或者说以渠道优先级为准)。
需要创建通知渠道时将重要性设置为IMPORTANCE_HIGH:

NotificationChannel channel = new NotificationChannel(channelId, "xxx", NotificationManager.IMPORTANCE_HIGH);

(2)Android 10(Api 29)新特性适配 - 禁止后台启动Activity中提到:
 

在华为mate20(Api-28)上需要到设置中打开横幅通知;原生Android Q上有效

各厂商交互不统一

        通过上面为通知设置setFullScreenIntent属性可以实现后台唤起Activity,但是由于国内厂商的魔改(程序员何苦为难程序员呢)导致该功能交互在不同手机上的交互体验都不一样,因此该方案不太理想。

        后来经考虑,决定换个思路来实现该功能,因为我们的需求是要通知到用户有业务的到来,然后在触发具体页面。

因此大致思路如下:

1. 当在后台时,具体业务发生时,将业务数据保存在数据库中;
2. 在业务数据保存数据库同时发出一个带声音及震动的通知消息;
3. 在Application中监听应用前后台切换,在前台时添加一个永久的observe来监听数据变化,有数据则唤起业务Activity,再在业务Activity中将数据移除掉同时撤销通知消息;
4. 当用户点击通知消息时,将app切换到前台时,3预埋的操作就触发了;

        这个思路也符合Android 10加入这个的背景,即防止其他后台app打扰用户当前操作,比如你在打游戏,突然弹出一个非相关页面,是不是很崩溃。

难点有:

1. 应用前后台切换监听;
2. 数据库DAO获取数据的永久监听(ROOM数据操作);
3. 业务数据的处理,保证只做一次处理;

 原文

1. Android10适配-针对从后台启动 Activity 的限制]

参考

1. 关于Android 10.0适配,看这篇就够了 2. Android Q适配(4)-------针对后台 Activity 启动的限制

3. 适配AndroidQ,不能后台启动Activity限制