一、Android 14——34 适配[详细地址]https://juejin.cn/post/7231835495557890106
1、对隐式 intent 和待处理 intent 的限制
隐式 intent 只能传送到导出的组件。应用必须使用显式 intent 传送到未导出的组件 带包名的去跳转,或将该组件标记为已导出。如果应用通过未指定组件或软件包的 intent 创建可变待处理 intent,系统现在会抛出异常。
<activity
android:name=".AppActivity"
android:exported="false"> //false 不可导出 true可导出
<intent-filter>
<action android:name="com.example.action.APP_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Intent explicitIntent =new Intent("com.example.action.APP_ACTION")
//跳转不可导出,需要设置包名
explicitIntent.setPackage(context.getPackageName());
context.startActivity(explicitIntent);
2、在运行时注册的广播接收器必须指定导出行为
在 Android 14 上,运行时通过 Context#registerReceiver() 动态注册广播接收器,需要设置标记 RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED ,标识是否导出该广播,避免应用程序出现安全漏洞,如果注册的是系统广播,则不需要指定标记。
三方SDK兼容修改方式:
如果三方SDK适配困难可以先在Activity或者Application中复写广播注册方法,如果有未添加是否可导出标记可以手动添加上
@Override
public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED或者Context.RECEIVER_NOT_EXPORTED);
}
@Override
public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter, int flags) {
Intent intent=null;
try {
boolean flagExported = (flags & Context.RECEIVER_EXPORTED) != 0;
boolean flagNotExported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0;
if(!flagExported && !flagNotExported){
intent = super.registerReceiver(receiver, filter, flags|Context.RECEIVER_EXPORTED或者Context.RECEIVER_NOT_EXPORTED);
return intent;
}
intent = super.registerReceiver(receiver, filter,flag);
} catch (Throwable e) {
}
return intent;
}
3、启动前台服务必须设置前台服务类型
如果有使用[startForeground()] 在清单文件中必须要指定服务的前台类型,例如音频播放类的可以使用mediaPlayback
为了帮助开发者更有目的地定义面向用户的[前台服务]Android 10 在 [<service>]元素内引入了 android:foregroundServiceType
属性。
二、Android 13——33 适配[详细地址]https://blog.csdn.net/as425017946/article/details/127530660
1、细分媒体权限 图片、视频、音频
从Android 13开始,以Android13(API 33+)为目标平台的应用,系统新增运行时权限READ_MEDIA_IAMGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO 替代原有的READ_EXTERNAL_STORAGE权限。
2、静态广播注册
从Android 13开始,以Android13(API 33+)为目标平台的应用,注册静态广播时,需设置对其他应用的可见性:
若对其他应用可见,广播注册时设置:Context.RECEIVER_EXPORTED
若仅应用内使用,广播注册时设置:Context.RECEIVER_NOT_EXPORTED
private void registerTestReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction("com.xiaxl.test.action");
// api >= 33
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// 跨应用间使用
MainActivity.this.registerReceiver(mTestReceiver, filter, Context.RECEIVER_EXPORTED);
// 应用内使用
//MainActivity.this.registerReceiver(mTestReceiver, filter, Context.RECEIVER_EXPORTED);
}
// api <= 32
else {
MainActivity.this.registerReceiver(mTestReceiver, filter);
}
}
3、剪切板内容隐藏
从Android 13(API 33)开始,Android剪切板新增了一项新API:
Android 13(API 33)开始,用户可以选择使用API PersistableBundle#(ClipDescription.EXTRA_IS_SENSITIVE, true)隐藏要复制到剪切板的用户账户、密码登敏感信息。
private void addData2Clipboard() {
ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newPlainText("111111", "我是密码");
ClipDescription description = clipData.getDescription();
// 隐私内容:剪切板加密
PersistableBundle persistableBundle = new PersistableBundle();
if (Build.VERSION.SDK_INT >= 33) {
persistableBundle.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
} else {
persistableBundle.putBoolean("android.content.extra.IS_SENSITIVE", true);
}
description.setExtras(persistableBundle);
// 剪切板添加加密内容
clipboardManager.setPrimaryClip(clipData);
}
三、Android 12——31 适配[详细地址]https://www.jianshu.com/p/60e061165667
四、Android 11——30 适配[详细地址]https://blog.csdn.net/JasonXu94/article/details/129290096
五、Android 10——29 适配[详细地址]https://blog.csdn.net/qq_33979657/article/details/106919681