Android14 适配之——targetSdkVersion 升级到 34 需要注意些什么?(上)

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
简介: Android14 适配之——targetSdkVersion 升级到 34 需要注意些什么?(上)

据上一篇文又是一个月过去了,虽说金九银十,但今年的氛围实在是太冷清了,能有一份工就不错了吧。但愿美元加息早点结束,经济早点好起来~

上一篇所说内容是所有 App 安装到 Android14 设备上的影响和需要注意的内容,本篇接下来就要介绍当 targetSdkVersion 升级到 34 时,App 需要注意和修改的地方。


1. 核心功能变更


1.1 前台服务类型


在 targetSdkVersion >= 34 的情况下,必须为应用内的每个前台服务(Foreground Service)指定至少一种前台服务类型。

什么是前台服务?前台服务(Foreground Service)是一种特殊类型的服务,用于执行与用户当前活动相关的长时间运行的任务,这些服务会在系统状态栏中显示通知,以告知用户应用正在前台执行任务,并且正在使用系统资源。在 Android12(API级别31)及更高版本的设备上,系统对短时间运行的前台服务进行了优化。系统会等待10秒,然后才显示与前台服务相关联的通知,以改善用户体验,减少即时通知的干扰。使用时需要在 Manifest 文件中申请 android.permission.FOREGROUND_SERVICE 权限。

前台服务类型是在 Android10 引入的,通过 android:foregroundServiceType 可以指定 <service> 的服务类型,可供选择的前台服务类型有:

1、camera:需要在后台时继续访问摄像头,比如支持多任务处理的视频聊天应用。

2、connectedDevice:与需要蓝牙、NFC、IR、USB 或网络连接的外部设备进行交互。

3、dataSync:数据传输操作,例如:数据上传或下载、备份与恢复操作、导入或导出操作、获取数据、本地文件处理、通过网络在设备和云之间传输数据。(这种类型可能会在后续 Android 版本中废弃,建议使用 WorkManager 或 user-initiated data transfer jobs 替换)

4、health:用于任何需要长期运行的用例,以支持健身类应用程序,如运动追踪器。

5、location:需要位置访问的长时间运行的用例,例如导航和位置共享。

6、mediaPlayback:需要在后台持续播放音频或视频,或在 Android TV 上支持数字视频录制(DVR)功能。

7、mediaProjection:使用 MediaProjection API 可以将内容投影到非主显示器或外部设备。这些内容不一定是专门的媒体内容。

8、microphone:需要持续在后台 (如录音机或通信应用程序) 进行麦克风捕获。

9、phoneCall:需要持续使用 ConnectionService API 的场景。

10、remoteMessaging:将短信从一台设备转移到另一台设备。在用户切换设备时,帮助确保用户消息任务的连续性。

11、shortService:需要快速完成不能打断或推迟的重要工作;有 5 个特点:1)只能运行较短的时长,大概 3 分钟;2)不支持粘性前台服务;3)无法启动其他前台服务;4)不需要另外申请特定类型的权限,但少不了 FOREGROUND_SERVICE 权限;5)正在运行的前台服务不能在 shortService 类型之间切换。超时之后会调用 Service.onTimeout(),这个 API 是 Android14 新增的,为了避免 ANR 建议实现 onTimeout 回调。

12、specialUse:如果不是上述所有类型所包含的,则使用这个类型。除了声明FOREGROUND_SERVICE_TYPE_SPECIAL_USE 前台服务类型外,还应该在 Manifest 中声明用例。即需要在 <service> 元素中指定元素,如下所示。在 Google Play Console 中提交应用时,这些值和相应的用例将被审查。

// code 1
<service android:name="fooService" android:foregroundServiceType="specialUse">
  <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="foo"/>
</service>


13、systemExempted:预留给系统应用程序和特定的系统集成,以继续使用前台服务。普通 App 开发者不用管。

另外,上述 13 种类型中,做有彩色标记 的是 Android14 上新增的;其他的则是之前就有的。

举个常见的后台播放的例子,先在 Manifest 文件中申明权限,并设置好 foregroundServiceType

// code 2
<manifest ...>
 <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
   <application ...>
     <service
         android:name=".MusicPlayerService"
         android:foregroundServiceType="mediaPlayback"
         android:exported="false">
     </service>
   </application>
</manifest>

然后再去实现 MusicPlayerService 类,主要就是在 onStartCommand 回调中打开通知并开始播放音乐:

// code 3
class MusicPlayerService : Service() {
    private var mediaPlayer: MediaPlayer? = null
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val NOTIFICATION_CHANNEL_ID = "com.example.foregroundservice"
        val notificationManager = NotificationManagerCompat.from(this)
        // If the notification supports a direct reply action, use
        // PendingIntent.FLAG_MUTABLE instead.
        val pendingIntent: PendingIntent =
            Intent(this, NotificationFullActivity::class.java).let { notificationIntent ->
                PendingIntent.getActivity(
                    this, 0, notificationIntent,
                    PendingIntent.FLAG_IMMUTABLE
                )
            }
        // 创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name: CharSequence = "Notification Channel Name"
            val description = "Description of Notification Channel"
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance)
            channel.description = description
            notificationManager.createNotificationChannel(channel)
        }
        // 构建通知
        val builder: NotificationCompat.Builder =
            NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setSmallIcon(android.R.drawable.ic_lock_idle_alarm)
                .setContentTitle("音乐播放中")
                .setContentText("艺术家 - 音乐")
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // 启动通知
        val notificationId = 1 // 每个通知的唯一标识符
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.POST_NOTIFICATIONS
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            notificationManager.notify(notificationId, builder.build())
        }
        // Notification ID cannot be 0.
        startForeground(notificationId, builder.build())
        // 播放音乐
        mediaPlayer = MediaPlayer.create(this, R.raw.music1)
        mediaPlayer?.isLooping = true
        mediaPlayer?.start()
        return START_STICKY
    }
}

最后就是启动这个 Service 了:

// code 4
requireActivity().startForegroundService(Intent(requireActivity(), MusicPlayerService::class.java))

如果没在 Manifest 文件中写明类型,那么在调用 startForeground() 方法时将会抛出 MissingForegroundServiceTypeException 异常。

对于上面的示例代码需要额外注意的是,在 Android13 及以上的手机上弹出 Notification 通知时,需要动态申请 android.permission.POST_NOTIFICATIONS 权限,当然还需要需要创建一个 NotificationChannel 渠道,这在 Android8 及以上就已经要求了。

再说回前台服务,上述每个前台服务类型所需要的权限是不一样的,并且这些权限都被定义成了普通权限,在默认情况下是已经授予的,用户不能撤销这些权限。例如 Camera 服务类型,需要在 Manifest 文件中声明 FOREGROUND_SERVICE_CAMERA 权限,并在运行时申请 Camera 权限。其他的服务类型都是如此:

Foreground Service Type

Manifest requirements

Runtime requirements

Camera FOREGROUND_SERVICE_CAMERA CAMERA
Connected device FOREGROUND_SERVICE_CONNECTED_DEVICE

在 Manifest 声明 CHANGE_NETWORK_STATE or CHANGE_WIFI_STATE or CHANGE_WIFI_MULTICAST_STATE or NFC or TRANSMIT_IR 或者请求运行时权限 BLUETOOTH_CONNECT or BLUETOOTH_ADVERTISE or BLUETOOTH_SCAN or UWB_RANGING 或者调用 UsbManager.requestPermission()

Data sync FOREGROUND_SERVICE_DATA_SYNC -
Health FOREGROUND_SERVICE_HEALTH 在 Manifest 声明 HIGH_SAMPLING_RATE_SENSORS 或申请运行时权限 (BODY_SENSORS or ACTIVITY_RECOGNITION)
Location FOREGROUND_SERVICE_LOCATION ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION
MediaPlayback FOREGROUND_SERVICE_MEDIA_PLAYBACK -
Media projection FOREGROUND_SERVICE_MEDIA_PROJECTION 需要在之前调用 createScreenCaptureIntent()
Microphone FOREGROUND_SERVICE_MICROPHONE RECORD_AUDIO
Phone call FOREGROUND_SERVICE_PHONE_CALL 在 Manifest 声明 MANAGE_OWN_CALLS
Remote messaging FOREGROUND_SERVICE_REMOTE_MESSAGING -
Short service - -
Special use FOREGROUND_SERVICE_SPECIAL_USE -
System exempted FOREGROUND_SERVICE_SYSTEM_EXEMPTED -

当然,肯定有特殊情况。如果自己的前台服务与上面提到的这 13 种都不太相关,那么官方建议将这些服务迁移到 WorkManager 或者 user-initiated data transfer jobs.

user-initiated data transfer jobs 就是由用户发起的数据传输任务。此 API 是 Android14 新增的,适用于需要由用户发起的持续时间较长的数据传输,例如从远程服务器下载文件。这些任务需要在通知栏中显示一个通知,会立即启动,并且可能在系统条件允许的情况下长时间运行。我们可以同时运行多个由用户发起的数据传输作业。

小结:如果目前应用中已用到了前台服务,且 targetSdkVersion 想升到 34,那么就得添加这个前台服务的类型;否则不用管。

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
目录
相关文章
|
6月前
|
安全 API 开发工具
Android14 适配之——targetSdkVersion 升级到 34 需要注意些什么?(下)
Android14 适配之——targetSdkVersion 升级到 34 需要注意些什么?(下)
358 0
|
8月前
|
安全 测试技术 API
Android 14适配指南
Android 14应用适配
1492 0
|
10月前
|
传感器 安全 测试技术
Android 13适配
Android 13适配
585 0
|
10月前
|
API Android开发
Android 12适配指南
Android 12适配指南
125 0
|
10月前
|
SQL 缓存 安全
Android 14适配
Android 14适配
571 0
|
API 网络安全 Android开发
Android 设备唯一标识(适配Android版本)
Android 设备唯一标识(适配Android版本)
790 0
Android 设备唯一标识(适配Android版本)
|
API Android开发 开发者
Android12 新特性及适配指南
Android 12(API 31)于2021年10月4日正式发布,正式版源代码也于当日被推送到AOSP Android开源项目。截止到笔者撰写这篇文章时,国内各终端厂商的在售Android设备,已经逐步开启了Android 12正式版本的更新。当前,对于Android应用开发者来说,Android 12 的软件兼容适配已迫在眉睫。
1151 0
Android12 新特性及适配指南
|
存储 安全 API
Android Q 适配指南
在Android 10开始版本中,官方的改动较大,相应的开发者适配成本还是很高的。 这里按照`2019.11.11 google android q workshop`流程,大概说明一下Android Q适配需要注意的内容。虽然是大概介绍,但应该是目前最全的适配攻略了...
656 0
Android Q 适配指南
|
XML 开发工具 Android开发
Android 8.0 简单适配那些事儿
迟到的 Android 8.0 适配!
943 0