官方链接: https://developer.android.com/preview/privacy/background-activity-starts

后台开启界面

这个限制主要限制的是: 当你的应用没有 Activity 在前台时, 后台应用无法主动开启界面

流氓应用是可以这么干的, 只是大部分应用还算有节操, 没有这么做而已

我自己遇到的除了我写的 Demo 以外,只有微信发生过这样的情况,还有一些其他应用是代码疏漏造成的

作用范围

只要你的 app 运行在 androidQ 的设备上, 就不行,哪怕你的 targetVersion 是 28 也一样

微信

微信也仅仅是在你登录以前登录过的电脑端时, 在你点击电脑端的确认后,才会在手机端弹出手动确认的弹框, 这一步原则上来讲也是客户自己的行为, 所以没有太大问题, 当然以后理论上就做不到了

代码疏漏

一些应用的启动页, 比如设定了一个 Handler 的倒计时, 在 3 秒后关闭启动页,然后开启主页面

然后,用户在启动页点了 home 键/back 键,过 3 秒后主页面依然出来了

很遗憾,以后不行了 😁

迁移需要修改的代码

一个简单的示例代码

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Handler().postDelayed({
            startActivity(Intent(this, this.javaClass))
            finish()
        }, 3000)
    }
}

这就完成了一个”流氓”式启动

Kapture 2019-05-21 at 10.07.29.gif

SYSTEM_ALERT_WINDOW

如果在以前的版本获得过SYSTEM_ALERT_WINDOW权限的应用可以从后台启动 Activity

通知用户

官方给出的建议: 在通知栏通知用户, 由用户决定是否开启界面, 而不是直接启动 Activity

  1. 创建高优先级的通知
val fullScreenIntent = Intent(this, CallActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

val notificationBuilder = 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 Q, you
    // need to request the USE_FULL_SCREEN_INTENT permission in order for the
    // platform to invoke this notification.
    .setFullScreenIntent(fullScreenPendingIntent, true)

val incomingCallNotification = notificationBuilder.build()
  1. 显示与前台服务关联的通知
// Provide a unique integer for the "notificationId" of each notification.
startForeground(notificationId, notification)

通知的好处

(这部分也是官方说的, 未校验)

  1. 这个通知遵循用户的免打扰
  2. 锁屏时, 全屏意图会立刻启动

如何测试这个变更

  1. 开发者选项=>启动后台活动启动
  2. 输入 $ adb shell settings put global background_activity_starts_enabled 1

后记

本篇对于常规应用的开发者来说没有任何变化, 一般情况下可以忽视

以上