Android 适配之——targetSdkVersion 30升级到31-34需要注意些什么?

在Android 16即将到来的之际。也就是targetSdkVersion即将出现36,而30已然会成为历史。那么我的项目已经停留在30很久了。是时候要适配一下适用市场的主流机型了。正常来查找资料的,无非就是已经升级和准备升级targetSdkVersion开发版本。所以你是哪一种情况呢?其实最有效的解决方法就是去查询官方文档,无一例外。因为规则都是由他们决定的,他们有主导权,我在文章中会插入一些链接文档,需要有想深入了解的,最好还是去官网了解一下。那么现在就开始你的升级之路吧!现在按升级顺序来讲讲可能遇到的问题吧!

1).targetSdkVersion (31-32) Android 12

https://developer.android.google.cn/about/versions/12/behavior-changes-12?hl=zh-cn

1、在Android 12及以上版本中,如果创建PendingIntent时没有指定FLAG_IMMUTABLE或FLAG_MUTABLE,应用将抛出异常并崩溃。这是因为系统无法确定PendingIntent的预期用途和行为,从而无法确保其安全性。FLAG_IMMUTABLE 通常是最安全的选择,适用于绝大多数情况。
解决方法: 注释掉的代码就是修改的位置
复制代码
private Notification createNotification() {
        Notification.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);
            getNotifyMgr(MQTTService.this.getApplicationContext()).createNotificationChannel(channel);
            builder = new Notification.Builder(MQTTService.this.getApplicationContext(), id);
        } else {
            builder = new Notification.Builder(MQTTService.this.getApplicationContext());
        }

        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setContentTitle(PackageUtils.getAppName(MQTTService.this.getApplicationContext()));
        builder.setContentText("订单消息接收中...");
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),
                R.mipmap.ic_launcher));
        builder.setWhen(System.currentTimeMillis());
        Intent activityIntent = MainActivity.getIntent(MQTTService.this.getApplicationContext());
        @SuppressLint("UnspecifiedImmutableFlag") PendingIntent pendingIntent = PendingIntent.getActivity(MQTTService.this.getApplicationContext(),
                1,
                activityIntent,
                android.os.Build.VERSION.SDK_INT >= 31?PendingIntent.FLAG_IMMUTABLE:PendingIntent.FLAG_UPDATE_CURRENT);
                //PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(pendingIntent);
        return builder.build();
    }
2、( 精确的闹钟权限)为了鼓励应用节省系统资源,以 Android 12 及更高版本为目标平台且设置了精确的闹钟的应用必须能够访问"闹钟和提醒"功能,该功能显示在系统设置的特殊应用访问权限屏幕中。
解决方法: 如果你的项目中有引用到类似功能的就会出现这个问题,解决的方案就是动态申请一下权限就行
复制代码
 <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
         requestPermissions(granted -> {
                if (!granted) {}
            }, Manifest.permission.SCHEDULE_EXACT_ALARM);
 }
3、( 针对从后台启动前台服务的限制) 以 Android 12(API 级别 31)或更高版本为目标平台的应用无法在后台运行时启动前台服务,但少数特殊情况除外。如果应用在后台运行时尝试启动前台服务,并且前台服务不符合任何特殊情况,则系统会抛出 ForegroundServiceStartNotAllowedException。如果你在项目有引用service 且开启是前台服务。如果切换到后台。就大概率可能出现这个bug
解决方法:就是如下的这个链接,最下面的是示例代码:定位类型 foregroundServiceType 跟用户权限是一 一对应的,豁免的条件可以是继承系统服务。或者是申请通知权限。通知交互获取豁免条件。
查阅的相关博主的博客说是推荐WorkerManger来替代。但是好像还是不能有效的解决问题。因为归根结底还是因为系统拦截导致的。官网介绍说WorkerManger的内容如下:

https://zhuanlan.zhihu.com/p/712108383

复制代码
<uses-permission
        android:name="android.permission.FOREGROUND_SERVICE_LOCATION"
        android:minSdkVersion="34" /> <!-- 启动类型为location的前台服务 -->

    <application>
		<service
			android:name=".MainService"
			android:directBootAware="true"
			android:enabled="true"
			android:exported="true"
			android:foregroundServiceType="connectedDevice|location"
			android:permission="android.permission.FOREGROUND_SERVICE" />
	</application>
4、( 蓝牙权限) Android 12 引入了 BLUETOOTH_SCANBLUETOOTH_ADVERTISEBLUETOOTH_CONNECT 权限。这些权限可让以 Android 12 为目标平台的应用更轻松地与蓝牙设备互动,尤其是不需要访问设备位置信息的应用。为了让您的设备做好准备以 Android 12 或更高版本为目标平台,请更新应用的逻辑。请声明一组更现代的蓝牙权限,而不是声明一组旧版蓝牙权限
解决方法:判断当前版本是否大于Android 12 动态申请权限
复制代码
    <uses-permission
        android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" /> <!-- 申明该权限不适用于安卓12及以上 -->
    <uses-permission
        android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" /> <!-- 申明该权限不适用于安卓12及以上 -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <!-- Android 11+ 新增的蓝牙扫描权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

String[] permission = new String[Build.VERSION.SDK_INT >= Build.VERSION_CODES.S?4:2];
        permission[0] = Manifest.permission.ACCESS_FINE_LOCATION;// 精确位置
        permission[1] = Manifest.permission.ACCESS_COARSE_LOCATION;// 粗略位置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12及以上
            permission[2] = Manifest.permission.BLUETOOTH_CONNECT;
            permission[3] = Manifest.permission.BLUETOOTH_SCAN;
        }

requestMustPermissions(granted -> {
            if(!granted) showMessage("请打开申请相关的权限");
            else PrintBlueActivity.startActivity(requireActivity());
        }, permission));// 搜索蓝牙操作
2).targetSdkVersion (33) Android 13
1、( 细化的媒体权限) 如果您的应用以 Android 13 或更高版本为目标平台,并且需要访问其他应用已经创建的媒体文件,您必须请求以下一项或多项细化的媒体权限,而不是READ_EXTERNAL_STORAGE 权限:
复制代码
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="32"
        tools:ignore="ScopedStorage" />
    <!--Android 13版本适配,细化存储权限-->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>

String[] permission = new String[(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) ? 4 : 3];
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permission[0] = Manifest.permission.CAMERA;
            permission[1] = Manifest.permission.READ_MEDIA_AUDIO;
            permission[2] = Manifest.permission.READ_MEDIA_IMAGES;
            permission[3] = Manifest.permission.READ_MEDIA_VIDEO;
        }else {
            permission[0] = Manifest.permission.CAMERA;
            permission[1] = Manifest.permission.READ_EXTERNAL_STORAGE;
            permission[2] = Manifest.permission.WRITE_EXTERNAL_STORAGE;
        }

requestMustPermissions(granted -> {
                            if (!granted) {
                                Tip.toast(getString(R.string.tip_permission));
                            } else {
                               // 操作图片动作。。。
                            }
                        }, permission);
2、( 蓝牙连接) 废弃了 BluetoothAdapter#enable() 和 BluetoothAdapter#disable()对于以 Android 13(API 级别 33)或更高版本为目标平台的应用,BluetoothAdapter#enable()BluetoothAdapter#disable() 方法已废弃,并且始终返回 false

2).targetSdkVersion (34) Android 14

1、( 前台服务类型是必填项) 如果您的应用以 Android 14(API 级别 34)或更高版本为目标平台,则必须为应用中的每个前台服务至少指定一项前台服务类型。您应选择一个能代表应用用例的前台服务类型。系统需要特定类型的前台服务满足特定用例。
相对于Android 12和13来说,14感觉是他们的延伸。更多的是对之前的补充。暂时先设置为34版本吧。如果要想更高的版本的以官网为主啊!希望能帮助到你们哈!加油!共勉!
随着现在Android 版本越来越高。权限是越来越收紧。未来会更加注重用户的隐私,所以是利好用户。对开发者是越来越不友好了。这是趋势。同时也是跟苹果看齐,设计的方向越来越注重用户体验。如果对文章内容还不能深入的了解到内容主体,可以查阅的资料如下:
https://zhuanlan.zhihu.com/p/712108383
Android14 适配之------targetSdkVersion 升级到 34 需要注意些什么?_android sdk 34-CSDN博客
https://juejin.cn/post/7302348032544866316https://developer.android.google.cn/develop/background-work/services/fgs/restrictions-bg-start?hl=zh-cn
相关推荐
雨白8 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹9 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空11 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭11 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日12 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安12 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑13 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟17 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡18 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0018 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体