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

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据同步 1个月
简介: 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,那么就得添加这个前台服务的类型;否则不用管。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
目录
相关文章
|
6月前
|
数据库 Android开发
Android 通过升级SettingsProvider数据强制覆盖用户的设置项
Android 通过升级SettingsProvider数据强制覆盖用户的设置项 【5月更文挑战第7天】
154 5
|
2月前
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
173 6
|
3月前
|
编解码 Android开发 UED
【性能狂飙!】揭秘Android应用极速变身秘籍:内存瘦身+用户体验升级,打造丝滑流畅新境界!
【8月更文挑战第12天】构建高效Android应用需全方位优化,尤其重视内存管理和用户体验。通过弱引用降低内存占用,懒加载资源减少启动负担。运用Kotlin协程确保UI流畅不阻塞,响应式设计适配多屏需求。这些策略共同提升了应用性能与用户满意度。
54 1
|
4月前
|
Dart API 开发工具
Flutter Android 14 强制升级说明 2024
猫哥我也是心大,当群友问我 flutter 如何升级编译 Android 14 时才发现需要提交新版本。
Flutter Android 14 强制升级说明 2024
|
4月前
|
IDE API Android开发
安卓与iOS开发环境的差异及适配策略
在移动应用开发的广阔舞台上,Android和iOS两大操作系统各据一方,各自拥有独特的开发环境和工具集。本文旨在深入探讨这两个平台在开发环境上的关键差异,并提供有效的适配策略,帮助开发者优化跨平台开发流程。通过比较Android的Java/Kotlin和iOS的Swift/Objective-C语言特性、IDE的选择、以及API和系统服务的访问方式,本文揭示了两个操作系统在开发实践中的主要分歧点,并提出了一套实用的适配方法,以期为移动开发者提供指导和启示。
|
3月前
|
安全 Java Android开发
Android 14适配Google play截止时间临近,适配注意点和经验
本文介绍了Android 14带来的关键更新,包括性能优化、定制化体验、多语言支持、多媒体与图形增强等功能。此外,还强调了适配时的重要事项,如targetSdkVersion升级、前台服务类型声明、蓝牙权限变更等,以及安全性与用户体验方面的改进。开发者需按官方指南更新应用,以充分利用新特性并确保兼容性和安全性。
257 0
|
5月前
|
存储 Linux 开发工具
Linux手动升级替换Android Studio
【6月更文挑战第22天】
124 8
|
5月前
|
Android开发
如何 将Android Studio升级至最新版(4.0)
如何 将Android Studio升级至最新版(4.0)
943 0
|
6月前
|
存储 缓存 Android开发
Android系统分区与升级
Android系统分区与升级
117 4