我们晋级到Targetsdk29有大半年时间了,本年为了满意检查去除蓝牙的准确定位权限,以及满意上架Google Play的要求,需求将Targetsdkversion晋级到31,适配到Android12。这个进程遇到不少坑,这里记载一下,期望能对大家有所帮助。转载请注明来源「申国骏」
由于我们在适配Android 29的时分现已适配了Scoped storage,因而这篇文章里边没有这部分的描绘。
安全组件输出,exported
编译时报错:
android:exported needs to be explicitly specified for element <activity#xxxActivity>. Apps targeting Android 12 and higher are required to specify an explicit value for android:exported
when the corresponding component has an intent filter defined. See developer.android.com/guide/topic… for details.
问题描绘:
在target到Android12之后,一切设置了intent filters的activity、services、broadcast receivers都需求设置 android:exported
,否则会导致编译异常。
解决方法:
假如需求被外部其他app拜访的component(例如设置了android.intent.category.LAUNCHER 的页面),那么需求exported=true
,其他状况设置为exported=false
。
-
Activity
true表明当时Activity需求被外部运用调用,例如桌面和运用需求翻开当时运用首页,false表明当时Activity只能被当时的运用,或许具有相同userID的运用,或许有调用特权的体系components
-
Service
true表明能够跟外部运用的component进行交互,false表明只有自己运用内的component以及具有相同userID的运用的component能够发动并绑定这个服务。
-
Receiver
true表明能够非体系的其他运用的播送,false表明只能收到体系的、自己运用的、具有相同userID运用的播送
关于一些aar或许依靠库有里边component的报错,有两个解决方法:1. 尝试晋级对应的依靠库版别,并看看是否现已进行了target android12适配;2. 在主工程中xml拷贝相关component声明,并掩盖exported设置,例如:
android:exported="true"
tools:replace="android:exported"
PendingIntent mutability
运行时报错:
java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}: java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
问题描绘:
在target到Android12之后,PendingIntent创立需求指定可变性FLAG_IMMUTABLE 或许 FLAG_MUTABLE
解决方法:
大部分状况下假如不期望创立的PendingIntent被外部运用修正,那么需求设置成PendingIntent.FLAG_IMMUTABLE既可。一些特殊状况能够设置成FLAG_MUTABLE(参阅:developer.android.com/guide/compo…
PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE);
传感器改写频率问题
运行时报错:
java.lang.SecurityException: To use the sampling rate of 0 microseconds, app needs to declare the normal permission HIGH_SAMPLING_RATE_SENSORS. at android.hardware.SystemSensorManager$BaseEventQueue.enableSensor(SystemSensorManager.java:884) at android.hardware.SystemSensorManager$BaseEventQueue.addSensor(SystemSensorManager.java:802) at android.hardware.SystemSensorManager.registerListenerImpl(SystemSensorManager.java:272) at android.hardware.SensorManager.registerListener(SensorManager.java:835) at android.hardware.SensorManager.registerListener(SensorManager.java:742)
问题描绘:
当运用SensorManager
时,假如监听的频率太快,例如sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
,且没有改界说permission HIGH_SAMPLING_RATE_SENSORS
权限的话会有这个溃散。
解决方法:
大部分状况下我们并不需求太快的监听频率,能够设置成SensorManager.SENSOR_DELAY_UI
。在某些确实需求快速频率监听的话,需求加上HIGH_SAMPLING_RATE_SENSORS
权限
ijkplayer
运行时溃散:
运行时的native溃散
问题描绘:
在target到Android11并且在64位的安卓体系版别11及以上的手机,运用ijkplayer会产生溃散。这里的原因是Android11关于64位的处理器中,每个指针的第一个字节将被用作符号位,用于ARM的内存符号扩展(MTE)支撑。在释放内存的时分假如修正这个符号位程序就会溃散。
那么ijkplayer在哪里会导致第一个字节被修正了呢,检查这个issues github.com/bilibili/ij… 以及提交记载 github.com/bilibili/ij… 能够看出,首要的原因是之前将指针转化成了int64_t类型导致了精度丢掉,修正的地方是将指针转成String或许无符号整形,防止精度丢掉导致的首位字节丢掉。
例如,在上面的图中,拜访0x8000的内存是可行的,由于用于进行拜访的指针具有与被拜访的内存相同的标签(用色彩表明)。可是,对0x9000的拜访将会失败,由于指针对内存有不同的符号。
解决方法:
解决方法有两个,一个是拉一下ijkplayer最新的代码从头build一个依靠库更新一下,由于ijkplayer现已修正了这个错误。第二个方法是经过设置<application android:allowNativeHeapPointerTagging="false">
暂时禁用Pointer Tagging功用。
TelephonyManager.getNetworkType
运行时溃散:
************* Crash INFO AT 04/01/2022 10:16 *************java.lang.SecurityException: getDataNetworkTypeForSubscriber android.os.Parcel.createExceptionOrNull(Parcel.java:2389) android.os.Parcel.createException(Parcel.java:2373) android.os.Parcel.readException(Parcel.java:2356) android.os.Parcel.readException(Parcel.java:2298) com.android.internal.telephony.ITelephony$Stub$Proxy.getNetworkTypeForSubscriber(ITelephony.java:8762) android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:3024) android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:2988)
问题描绘:
我们运用到的一个一键登录的库调用的TelephonyManager.getNetworkType
被符号为deprecated
,需求改成运用 getDataNetworkType
,并且需求加上权限READ_PHONE_STATE
或许 READ_BASIC_PHONE_STAT
解决方法:
晋级一键登录的库,并且加上对应权限
webview拜访文件
运行时问题:
加载file://data目录底下数据时webview报错: 网页无法加载,net:ERR_ACCESS_DENIED
问题描绘:
在target到Android11及以上的时分,默认setAllowFileAccess从true改成了false,无法拜访到context.getDir()里边的文件,参阅:developer.android.com/reference/a…
解决方法:
手动调用一下webSettings.setAllowFileAccess(true)
Package可见性
运行时问题:
当运用[queryIntentActivities()
](developer.android.com/reference/a…, int)), [getPackageInfo()
](developer.android.com/reference/a…, int))或许 getInstalledApplications()
查询是其他运用信息的话会查不到
问题描绘:
当运用target到Android11之后,Package可见性受到了限制,查询其他运用信息需求加上QUERY_ALL_PACKAGES
权限或许运用queries方法获取。
解决方法:
-
在AndroidManifest.xml中加入权限
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
,这个需求谨慎运用,由于运用市场上线检查可能会需求供给运用的必要性阐明,例如Google Play政策:support.google.com/googleplay/… -
在AndroidMainifest.xml中界说需求拜访的运用信息,例如
-
需求拜访某个运用信息,直接指定运用包名
<queries> <package android:name="com.example.store" /> </queries>
-
需求拜访具有某些intent的外部组件,指定需求拜访的intent
<queries> <intent> <action android:name="android.intent.action.SEND" /> <data android:mimeType="image/jpeg" /> </intent> </queries>
-
需求拜访某些外部content provider,指定authoritites
<queries> <provider android:authorities="com.example.settings.files" /> </queries>
-
微博SDK
运行时问题:
微博SDK更新到最新版支撑适配安卓11,遇到一个初始化的报错please init sdk before use it. Wb.install()
问题描绘:
在微博进行登录授权的时分,需求获取授权信息,不过获取授权信息的时分,有一个断语判断失败了。需求在初始化之后等待一段时间。
解决方法:
经过循环等待的方法等待初始化断语经过再进行其他SDK操作:
public static void waitForWeiboSDKValid() {
// 微博sdk初始化需求等待一下
// https://github.com/sinaweibosdk/weibo_android_sdk/issues/608
// https://xie.infoq.cn/article/974795351e87627681cc353b5
int retryCount = 0;
while (retryCount <= 10) {
try {
a.b();
break;
} catch (Exception ignore) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
retryCount++;
}
}
}
private void installWbSdk() {
WBAPIFactory.createWBAPI(getApplicationContext());
mWBAPI.registerApp(getApplicationContext(), authInfo);
waitForWeiboSDKValid();
}
后台发动前台服务
运行时溃散:
Caused by: android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service XXXXService 16 at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54) 17 at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50) 18 at android.os.Parcel.readParcelable(Parcel.java:3345) 19 at android.os.Parcel.createExceptionOrNull(Parcel.java:2432) 20 at android.os.Parcel.createException(Parcel.java:2421) 21 at android.os.Parcel.readException(Parcel.java:2404) 22 at android.os.Parcel.readException(Parcel.java:2346) 23 at android.app.IActivityManagerStubStubProxy.setServiceForeground(IActivityManager.java:8040) 24 at android.app.Service.startForeground(Service.java:733)
问题描绘:
运用在target到Android12之后,假如运用在后台启用前台服务,那么就会报ForegroundServiceStartNotAllowedException
解决方法:
- 运用WorkManager来处理后台任务
- 防止在后台发动前台服务
蓝牙权限
运行溃散:
Caused by: java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission for android.content.AttributionSource@db46d647: enable 37 at android.os.Parcel.createExceptionOrNull(Parcel.java:2425) 38 at android.os.Parcel.createException(Parcel.java:2409) 39 at android.os.Parcel.readException(Parcel.java:2392) 40 at android.os.Parcel.readException(Parcel.java:2334) 41 at android.bluetooth.IBluetoothManagerStubStubProxy.enable(IBluetoothManager.java:611) 42 at android.bluetooth.BluetoothAdapter.enable(BluetoothAdapter.java:1217)
问题描绘:
在target到Android12之后,查找蓝牙设备需求增加 BLUETOOTH_SCAN
权限,与匹配的蓝牙设备传输数据需求获取BLUETOOTH_CONNECT
权限
解决方法:
在查找和匹配蓝牙设备之前,先动态申请 BLUETOOTH_SCAN
权限以及BLUETOOTH_CONNECT
权限。
其他
检查依靠的SDK中是否有新的版别,并进行更新,由于安全组件输出Exported以及包可见性的问题关于大多数SDK都可能会存在,所以最好都检查一下,例如华为小米OV相关的产商推送SDK,以及微信QQ微博等登录和共享的SDK。
参阅
- Bluetooth permissions
- Target API level requirements for Play Console
- Sensor Rate-Limiting
- Behavior changes: Apps targeting Android 12
- Behavior changes: Apps targeting Android 11
- vivo Android 12运用适配指南
- vivo Android 11运用适配指南
- oppo Android 12 运用兼容性适配辅导
- oppo Android 11 运用兼容性适配辅导
- 小米 Android 12运用适配指南
- Tagged Pointers
- Memory Tagging Extension: Enhancing memory safety through architecture
- Package visibility filtering on Android
- Declaring package visibility needs