语聊类应用存在应用进入后台依然通过语音交流的特点,因此如果使用普通服务承载核心功能将会被系统限制麦克风资源访问和网络访问等情况进而导致功能不可能问题,因此我们必须使用前台服务的形式,通知栏绑定通知,并且关闭系统电池优化,如此三项措施才能符合Google规范的最大程度的保证核心功能稳定可用.
后台执行限制
Android 8.0 为提高电池续航时间而引入的变更之一是,当您的应用进入已缓存状态时,如果没有活动的组件,系统将解除应用具有的所有唤醒锁。
此外,为提高设备性能,系统会限制未在前台运行的应用的某些行为。具体而言:
- 现在,在后台运行的应用对后台服务的访问受到限制。
- 应用无法使用其清单注册大部分隐式广播(即,并非专门针对此应用的广播)。
默认情况下,这些限制仅适用于针对 O 的应用。不过,用户可以从 Settings 屏幕为任意应用启用这些限制,即使应用并不是以 O 为目标平台。
Android 8.0 还对特定函数做出了以下变更: - 如果针对 Android 8.0 的应用尝试在不允许其创建后台服务的情况下使用 startService() 函数,则该函数将引发一个 IllegalStateException。
- 新的
Context.startForegroundService()
函数将启动一个前台服务。现在,即使应用在后台运行,系统也允许其调用Context.startForegroundService()
。不过,应用必须在创建服务后的五秒内调用该服务的startForeground() 函数。
如需了解详细信息,请参阅[后台执行限制]
忽略电池优化
(https://developer.android.com/preview/features/background?hl=zh-cn)。
在默认情况下,系统出于性能优化角度考虑是允许电池优化的,但是在特定场景下,我们需要应用进入后台也能保持活跃,那么我们可以考虑申请忽略电池优化. 可以参考 Android 忽略电池优化.
应用退到后台系统释放麦克风资源,导致系统无法采集声音资源
后台对传感器的访问受限
Android 9 限制后台应用访问用户输入和传感器数据的能力。 如果您的应用在运行 Android 9 设备的后台运行,您的应用不能访问麦克风或摄像头.在这种情况下,我们则需要使用前台服务来解决该问题.
关于前台服务类型
在 Android 11 中,前台服务何时可以访问设备的位置信息、摄像头和麦克风发生了一些变化。这有助于保护敏感的用户数据。
前台服务类型 camera 和 microphone
如果您的应用以 Android 11 或更高版本为目标平台,且在前台服务中访问摄像头或麦克风,则必须添加前台服务类型 camera
和 microphone
.
对在使用时访问的限制
如果您的应用在后台运行时启动了某项前台服务,则该前台服务无法访问麦克风或摄像头。
作为前台服务通常在通知栏都会挂一个通知,并且点击该通知也会需要打开某一个具体的应用内页面,但是出于Android系统兼容问题可能会出现不能打开页面的问题
在Android 10 用户隐私设置中有如下描述:
屏蔽意外中断 - Android 10 可阻止应用从后台启动,从后台启动会使应用意外跳转到前台并从其他应用获得焦点
针对从后台启动 Activity 的限制
从 Android 10 开始,系统会增加针对从后台启动 Activity 的限制。此项行为变更有助于最大限度地减少对用户造成的中断,并且可以让用户更好地控制其屏幕上显示的内容。只要您的应用启动 Activity 是因用户互动直接引发的,该应用就极有可能不会受到这些限制的影响.官方示例代码如下
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 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)
val incomingCallNotification = notificationBuilder.build()
并且可以通过startForeground(notificationId, notification)将其与现有前台服务关联,从而实现点击通知打开指定页面的功能.
通知的运行时权限
Android 13(API 级别 33)引入了运行时通知权限:POST_NOTIFICATIONS
。 此更改有助于用户专注于最重要的通知
可以关闭前台服务通知
从 Android 13(API 级别 33)开始,默认情况下,用户可以关闭与前台服务关联的通知。为此,用户可以在通知上执行滑动手势。一直以来,除非停止前台服务或将其从前台移除,否则通知不会被关闭。
如果您希望用户无法关闭通知,请在使用 Notification.Builder
创建通知时将 true
传入 setOngoing()
方法
前台服务通知的用户体验延迟
除了一些例外情况之外,为了为短时间运行的前台服务提供流畅体验,搭载 Android 12 或更高版本的设备可以将前台服务通知的显示延迟 10 秒。此更改使某些短期任务可在显示通知之前完成。
立即显示通知的服务
如果某项前台服务至少具有以下特征之一,系统会在服务启动后立即显示关联的通知,即使在搭载 Android 12 或更高版本的设备上也是如此:
- 该服务与包含操作按钮的通知相关联。
- 该服务的
foregroundServiceType
为mediaPlayback
、mediaProjection
或phoneCall
。 - 该服务根据通知的类别属性中的定义,提供与通话、导航或媒体播放相关的用例。
- 该服务通过在设置通知时将
FOREGROUND_SERVICE_IMMEDIATE
传入setForegroundServiceBehavior()
,已停用行为变更。
在 Android 13(API 级别 33)或更高版本中,如果用户拒绝授予通知权限,他们仍会在任务管理器中看到与前台服务相关的通知,但不会在抽屉式通知栏中看到这些通知
更安全的组件导出
如果您的应用以 Android 12 或更高版本为目标平台,且包含使用 intent 过滤器的 activity、服务或广播接收器,您必须为这些应用组件显式声明 android:exported
属性。
警告:如果 activity、服务或广播接收器使用 intent 过滤器,并且未显式声明 android:exported
的值,您的应用将无法在搭载 Android 12 或更高版本的设备上进行安装。
如果应用组件包含 LAUNCHER
类别,请将 android:exported
设置为 true
。在大多数其他情况下,请将 android:exported
设置为 false
。
以下代码段显示了一个服务示例,该服务包含一个 android:exported
属性设置为 false
的 intent 过滤器:
<service android:name="com.example.app.backgroundService"
android:exported="false">
<intent-filter>
<action android:name="com.example.app.START_BACKGROUND" />
</intent-filter>
</service>
参考
Android 8.0 行为变更
Android 9.0 行为变更
Android 10.0 行为变更
电源管理限制