My public programmer Xu Gong, four years of work experience in Dachang, reply dark horse, receive Android learning video, reply Xu Gong 666, you can get my carefully organized resume template, take you close to Dachang.
Author: only deer source: https://juejin.cn/post/694821…
Android 11 adaptations have finally started. Write it down for anyone who needs it.
1. Preparation
As usual, first change the targetSdkVersion in our project to 30. Or use a compatibility debugging tool, which I’ll talk about later.
2. Storage mechanism update
Scoped Storage
Specific adaptation method and the last 10 adaptation strategy [Android] (https://weilu.blog.csdn.net/a…
Note, however, that targetSdkVersion >= 30 is applied to enforce the partitioned storage mechanism. Before the AndroidManifest. Add android: XML requestLegacyExternalStorage = “true” way of adaptation has no effect.
One more change: Android 11 allows for direct access to media files in a shared storage space via file paths using APIs other than the Mediastore API. These include:
File
API.- Native libraries, for example
fopen()
.
This is good news if you haven’t adapted to Android 10 before. Android 10 in AndroidManifest. Add Android: XML requestLegacyExternalStorage = “true” to adaptation, Android using the File directly on 11 API access media files. I have to say, wait for the party’s victory?
However, direct access to media files in the shared storage space using the original file path results in a redirect to the Mediastore API, which has a performance impact (random reads and writes are about twice as slow). It is also strongly recommended that you use the Mediastore API directly because there is no advantage to using the original file path directly over using the Mediastore API.
MANAGE_EXTERNAL_STORAGE
There is, of course, a simple and crude way to adapt, which is to get access to external storage management. If your application is a mobile phone manager, file manager, such as the need to access a large number of files of the APP, you can apply for the MANAGE_EXTERNAL_STORAGE authority, the user will be directed to the system Settings page open. The code is as follows:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
public static void checkStorageManagerPermission(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&! Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); }}
Note that even if you have the MANAGE_EXTERNAL_Storage privilege, you will not be able to access files in the Android/data/ directory.
For the MANAGE_EXTERNAL_STORAGE permission, domestic usage should have no effect. But on Google Play, you need to explain why your existing SAF or Mediastore doesn’t meet your app’s needs, and then you need to approve it. So in general, I personally do not recommend that you apply for the MANAGE_EXTERNAL_STORAGE permission directly for easy adaptation.
Other details see changes to the document: [11 storage mechanism of the Android update] (https://developer.android.goo…
Relevant API changes and use the recommended Guo Lin this great god: [Android 11 new features, Scoped Storage has a new figure] (https://guolin.blog.csdn.net/…
Storage Access Framework (SAF) changes
Android 11 adds the following limitations to SAF:
- use
ACTION_OPEN_DOCUMENT_TREE
或ACTION_OPEN_DOCUMENT
, cannot be browsedAndroid/data/
和Android/obb/
Directory and all its subdirectories. - use
ACTION_OPEN_DOCUMENT_TREE
Cannot authorize access to the storage root, Download folder.
REQUEST_INSTALL_PACKAGES
In Adaptation 8.0, we need to apply for the “Install Unknown Source Apps” permission before installing the APK package. Generally speaking, the first step is to jump to the authorization page for the user to manually open, and then return to the app for installation.
In Android 11, the app will be killed when the user turns on the “install apps from unknown sources” option. This behavior is related to forcing partitioned storage, because applications that hold REQUEST_INSTALL_PACKAGES can access other applications’ Android/ OBB directories.
Fortunately, after the user grants permission, the app will be killed, but the installation page will still pop up.
Now I have not found for this change can fit the means of processing, details see: [Android features 11 adjustment: the installation of external sources need to restart the APP] (https://news.51cto.com/art/20…
Just to add, other apps can’t access your app’s Android/data/ and Android/obb/ directories and all of their subdirectories. So you need to pay attention to whether the files stored here can be accessed by other programs.
For example, when I was using the cropping function of the system, the cropped image could not be generated correctly because the MediaStore. Extra_Output file was set under the private directory. So it needs to be adapted for Android 11:
String fileName = System.currentTimeMillis() + ".jpg"; If (build.version.sdk_int >= build.version_CODES.r) {// You cannot access your App's private directory, ContentValues = new ContentValues(); contentValues = new ContentValues(); values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/Crop"); Uri uri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } else { ... }
Or save to the Android/ Media shared file directory, so no adaptor version is needed.
String fileName = System.currentTimeMillis() + ".jpg";
File file = new File(this.getExternalMediaDirs()[0].getAbsolutePath() + File.separator + fileName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
Of course, if you implement the clipping function yourself, it will not be affected.
3. Permission changes
Single permission authorization
From Android 11
Initially, whenever an application requests permissions related to location information, microphone, or camera, the user-facing permissions dialog box will contain a once-only option. If the user selects this option in the dialog box, the application is granted a temporary single authorization.
A single permission grant allows an application to access data over a period of time, depending on the behavior of the application and the actions of the user:
- When an application’s Activity is visible, the application can access relevant data.
- If the user runs the application in the background, the application can continue to access the relevant data for a short time.
- If you start a foreground service while your Activity is visible, and the user then moves your application to the background, your application can continue to access the relevant data until the foreground service stops.
- If the user revokes the authorization a single time (for example, in system Settings), the application will not be able to access the relevant data, whether or not you started the foreground service. As with any permission, if the user revokes a single authorization of the application, the application process terminates.
The next time the user opens the app and a feature in the app requests access to location information, microphone or camera, the user is prompted again to grant permission.
If you previously requested permission only for a limited time, this change will have no effect on your application.
Request location permission
This part of the Android 10 adaptation has been adjusted, at the time the rules are as follows:
request
ACCESS_FINE_LOCATION
or
ACCESS_COARSE_LOCATION
Permission means that you have access to device location information while in the foreground. In the request pop-up box, “Always allowed” means that both foreground and background can obtain location information, and “Only allowed during application use” means that the foreground has permission.
In Android 11, the “Always Allow” option is removed from the request pop-up. This means that background access to device location information is not granted by default. If you try to request the ACCESS_BACKGROUND_LOCATION permission along with any other permissions, the system throws an exception and does not grant any of these permissions to the application.
Official recommendations and reasons for adaptation are as follows:
It is recommended that the application execute an incremental request for location permissions, first requesting the foreground location information access permissions, and then requesting the background location information access permissions. Performing incremental requests provides users with greater control and transparency because they can better understand which functions in the application require access to background location information.
To sum up, there are two points:
- First request the foreground location information access authority, then request the background location information access authority.
- Request access to background location information alone, do not request with other permissions.
It’s also important to note how apps on different target platforms perform on Android 11:
- Android 10 apps will allow access to both front and back location information, but there will also be no “always allow” option.
- When there is no permission for location information in front and back:
- When the location information of the front desk is authorized:
- Android 11 is the target platform
- If there is no permission of location information of front and background, it can only request the permission of location information of front and background:
- Has the foreground location information permission, request the background location information when the system will jump to the following setting page.
Selecting “Always Allow” means that the user has access to the front and back location information. If the user rejects the application location access request twice (direct return, etc.), the subsequent request for the same permission will be directly prompted that the request failed. (Here we need to give the user guidance)
To explain “deny twice”, this is the visibility of the permissions dialog added to Android 11. Previously, we clicked “ask no more” to deny authorization. Now it also includes things like going to system Settings and then hitting the back button to deny authorization. Of course, the user presses the back button to close the permissions dialog box, this action does not count.
To sum up, the difference with Android 10 is that it separates requests for background permissions and adds a “reject” condition to prevent the application from repeatedly requesting permissions that the user has already denied.
Package visibility
Package visibility is Android
A new feature to improve system privacy security on the 11. Its function is to restrict the app from freely accessing information and installation status of other apps. Avoid the use of virus software, spyware, causing phishing, user installation information disclosure and other security incidents.
Get a list of automatically visible applications. You can execute the ADB Shell Dumpsys Package Queries command to find the forceQueryable part. Here are the results of the implementation of the Vivo iqoo phone.
Queries: system apps queryable: false forceQueryable: [com.android.BBKCrontab,com.vivo.fingerprint,com.vivo.epm,com.vivo.abe,com.vivo.fingerprintengineer,com.vivo.contentcatc her,com.vivo.floatingball,com.vivo.agent,com.vivo.nightpearl,android,com.wapi.wapicertmanage,com.vivo.vms,co m.android.providers.settings,com.vivo.upslide,com.vivo.assistant,com.vivo.vivokaraoke,com.vivo.fingerprintui,com.android .wallpaperbackup,com.bbk.facewake,com.vivo.faceunlock,com.vivo.doubleinstance,com.vivo.audiofx,com.iqoo.powersav ing,com.bbk.SuperPowerSave,com.vivo.vibrator4d,com.vivo.smartunlock,com.vivo.globalanimation,com.vivo.appfilter,com.vivo .voicewakeup,com.vivo.minscreen,com.android.bbklog,com.mobile.cos.iroaming,com.vivo.networkstate,com.vivo.daemon Service,com.vivo.smartshot,com.vivo.vtouch,com.android.networkstack.tethering.inprocess,com.android.localtransport,com.v ivo.pem,com.vivo.wifiengineermode,com.android.server.telecom,com.vivo.gamecube,com.vivo.aiengine,com.vivo.multin lp,com.vivo.smartmultiwindow,com.vivo.permissionmanager,com.qti.diagservices,com.vivo.bsptest,com.qti.snapdragon.qdcm_ff ,com.vivo.dr,com.vivo.sps,com.android.dynsystem,com.vivo.setupwizard,com.vivo.gamewatch,com.android.keychain,com .vivo.faceui,com.android.networkstack.inprocess,com.android.location.fused,com.android.inputdevices,com.android.settings ,com.iqoo.engineermode,com.vivo.fuelsummary] [com.qualcomm.uimremoteserver,com.vivo.devicereg,com.qti.qualcomm.deviceinfo,com.volte.config,com.android.mms.service,co m.android.ons,com.qualcomm.qcrilmsgtunnel,com.vivo.sim.contacts,com.qualcomm.qti.uimGbaApp,com.qualcomm.qti. modemtestmode,com.android.stk,com.android.vendors.bridge.softsim,com.qualcomm.uimremoteclient,com.qti.qualcomm.datastatu snotification,com.qualcomm.qti.uim,com.android.phone,com.qualcomm.qti.dynamicddsservice,com.qualcomm.qti.telepho nyservice,com.android.cellbroadcastservice,com.android.providers.telephony,com.qti.dpmserviceapp,com.android.incallui] [com.android.vivo.tws.vivotws,com.android.bluetooth] com.android.nfc com.android.se com.android.networkstack.permissionconfig com.android.shell com.android.providers.media.module com.android.wifi.resources.overlay.common com.android.theme.icon_pack.filled.themepicker com.android.theme.icon_pack.circular.themepicker com.android.server.telecom.overlay.common ......
As you can see, they are all system application package names, so our third party application is invisible by default. Most of the changes affect features such as shared payments that require interaction with other apps. Here’s a simple example:
private static boolean hasActivity(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
return packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
public void test() {
Intent intent = new Intent();
intent.setClassName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareImgUI");
Log.d("hasActivity:", hasActivity(this, intent) + "");
}
The queryInentActivities in the hasActivity method are used to determine whether the page exists. But in ‘targetSdkVersion >= 30, these three parties are not visible by default. So they all return false. Similar methods getInstalledPackages, getPackageInfo ‘are also subject to corresponding restrictions.
The solution is simple: add the Queries element to the AndroidManifest.xml, which contains the application package names that you want to see.
<manifest package="com.example.app"> < query > <package android:name=" com.t06.mm "/> <- </manifest>
I also used the following package names for adaptations, which we can add as needed:
<queries> <! <package android:name="com.sina.weibo" /> <! -- QQ --> <package android:name="com.tencent.mobileqq" /> <! - pay treasure - > < package android: name = "com. Eg. Android. AlipayGphone" / > <! -- AlipayHK --> <package android:name="hk.alipay.wallet" /> </queries>
In addition to adding the package name directly, we can press Intent and Provider to add it:
<manifest package="com.example.app">
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/jpeg" />
</intent>
<provider android:authorities="com.example.settings.files" />
</queries>
...
</manifest>
For detailed rules, see Managing Package Visibility
There is, of course, an easy and brutal way to apply for permissions QUERY_ALL_PACKAGES directly. If your app needs to be listed on Google Play, you may want to pay attention to the policy. In order to respect user privacy, it is recommended that our application be adapted to the minimum package visibility required to function properly.
It is important to note that the startActivity method we use on a daily basis is not affected by the visibility behavior of the system package and can jump even if hasActivity is false. If we do a HasActivity-like judgment before making a jump, it will be affected.
Finally, it is important to note that using the Queries element requires the Android Gradle plugin version 4.1 or higher, because older versions of the plugin are not compatible with this element and have a merge manifest error.
Front desk service type
In Android 10, to access location information in the foreground service, you need to add the Location service type to the corresponding service.
Similarly, in Android 11, to access the camera or microphone in the foreground service, you need to add the camera or microphone service type to the corresponding service.
<manifest>
...
<service
android:name="MyService"
android:foregroundServiceType="microphone|camera" />
</manifest>
This restriction change makes it impossible for applications to launch services in the background to access cameras and microphones. If you need to use it, only the front desk can open the front desk service. Unless:
- Services are started by system components.
- The service is started through the application widget.
- The service is started by interacting with notifications.
- A service is
PendingIntent
Launched, which is sent from another visible application. - The service is started by an application that is a DPC and runs in device owner mode.
- Services are provided by one
VoiceInteractionService
The application starts. - A service consists of one with
START_ACTIVITIES_FROM_BACKGROUND
The permission of the application is started.
Automatic permission reset
If an app is targeted at Android 11 or higher and has not been used for months, the system protects user data by automatically resetting run-time sensitive permissions that the user has granted the app. As shown in the figure below:
Note that there is a switch in the image above that initiates automatic reset. If our application has a special need, we can guide the user to turn it off. The sample code is as follows:
Public void checkAutoRevokePermission Context (Context) {/ / determine whether to open the if (Build) VERSION) SDK_INT > = Build. VERSION_CODES. The R && ! Context. GetPackageManager (). IsAutoRevokeWhitelisted ()) {/ / jump Settings page Intent Intent = new Intent(Intent.ACTION_AUTO_REVOKE_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setData(Uri.fromParts("package", context.getPackageName(), null)); context.startActivity(intent); }}
SYSTEM_ALERT_WINDOW permissions
I didn’t use this part in the adaptation, so I directly copied the document:
In Android 11, the system automatically grants SYSTEM_ALERT_WINDOW permissions to certain types of applications on request:
- The system will automatically have to
ROLE_CALL_SCREENING
And requestSYSTEM_ALERT_WINDOW
Grant this permission to all applications of. If the application is lostROLE_CALL_SCREENING
, the permission will be lost. - The system will pass automatically
MediaProjection
Intercept the screen and requestSYSTEM_ALERT_WINDOW
This permission is granted to all applications of the This permission is lost when the application stops capturing the screen. This use case is primarily used for game live streaming applications.
Instead of sending ACTION_MANAGE_OVERLAY_PERMISSION to obtain SYSTE_ALERT_WINDOW permissions, these applications can simply request SYSTE_ALERT_WINDOW directly.
Manage_overlay_Permission Intent always redirects the user to the system permissions screen
Starting with Android 11, the ACTION_MANAGE_OVERLAY_PERMISSION intent always directs the user to the top-level Settings screen where the user can grant or revoke the application’s SYSTEM_ALERT_WINDOW permissions. Any package: data in the intent is ignored.
In lower versions of Android, ACTION_MANAGE_OVERLAY_PERMISSION intent can specify a package that redirects the user to an application-specific screen to manage permissions. Starting with Android 11, this feature will no longer be supported. Instead, the user must first choose which apps to grant or revoke. This change protects users by making the granting of permissions more targeted.
Read the phone number
If you get the phone number through TelecomManager’s getLine1Number method, or TelephonyManager’s getMSISDN method. Then you need to add the READ_PHONE_NUMBERS permission in Android 11. The use of other methods is not limited.
<manifest> <! -- If the application only uses this permission on Android 10 and lower, (maxSdkVersion="29" --> < uses-mission Android :name=" android.mission. READ_phone_state ") android:maxSdkVersion="29" /> <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> </manifest>
4. Other behavioral changes
Customize the Toast of the View
For Android 11 apps, the system will block Toast messages that send custom views from the background. Front desk use is not affected. The Toast corresponding setView and getView have also been deprecated and are not recommended for use.
If you want to use it in the background, it is recommended to use the default Toast or Snackbar instead.
APK signature
Android 11 is the target platform. Apps signed with V1 alone cannot be installed or updated on Android 11 devices. You must use v2 or later to sign.
At the same time the Android 11 has added to the APK v4] [signature scheme (https://developer.android.goo… Support.
AsyncTask
AsyncTask is deprecated on Android 11 and is recommended to migrate to Kotlin’s coroutine.
In additionHandler
Is not specifiedLooper
The constructor for the.
It is recommended to explicitly specify Looper:
private Handler handler = new Handler(Looper.myLooper()); // private Handler Handler = new Handler(Looper.getMainLooper());
Status bar height
Found that the system for Android 11 mobile phone targetSdkVersion is 30 when the obtain status bar height is 0, below 30 to obtain the value of normal… Therefore, we need to use WindowMetrics to adapt:
public static int getStatusBarHeight(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); WindowMetrics windowMetrics = wm.getCurrentWindowMetrics(); WindowInsets windowInsets = windowMetrics.getWindowInsets(); Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars() | WindowInsets.Type.displayCutout()); return insets.top; }... }
WindowMetrics is a new Android 11 class for getting window boundaries, which can also be used to get navigation bar heights.
5. Add new tools
Compatibility debugging tool
In the past, when we do adaptation, we need to modify the targetSdkVersion in our project to the corresponding version. This makes it possible for you to be affected by other changes during the adaptation process, and the new compatibility debugging tool allows you to turn on adaptations for each change without updating targetSdkVersion.
Usage:
- Find application compatibility change options in developer options.
- Click Enter to find the app you need to debug
- In the changelist, find the change you want to turn on or off and click the appropriate switch.
The first line up hereDEFAULT_SCOPED_STORAGE
To enable partition storage, see [Android 11] for more details on what these constants mean
Change List](https://developer.android.goo…
For detailed use of compatibility debugging tools see: compatibility framework tools, here is limited to space will not be expanded to say.
Wireless debugging
A wireless debugging feature has been added to Android 11’s developer options. Similar to the function of connecting Bluetooth headset, it can carry out daily development and debugging work without USB cable. (Different from the old Android WiFi ADB, this is really wireless, haha)
Usage:
- Locate wireless debugging in the developer options and turn it on.
- For the first pairing, click “Match Device with Pairing Code”.
- run
adb pair ipaddr:port
After the input of the pairing code for connection.
Note:
- Keep your computer and phone on the same network.
- Platform Tools version greater than 30.0. You can use
adb --version
Look at it.
However, after my own experience, I feel that the connection is not very stable. I wonder whether it is the AS problem or the mobile phone problem. At the same time, the lock screen will also disconnect, the experience is not very good… Expect further optimizations.
This is a bit too much. To summarize, Android 11 has a lot of changes to permissions, but if you’ve been following best practices for requesting permissions, there’s little extra adaptation effort required.
Finally, for single authorization, visibility of permissions dialogs, SYSTEM_ALERT_WINDOWS permissions, and installing APK these changes will take effect on Android 11, whether or not you are Android 11 compliant. For other changes and APIs (camera, 5G, waterfall screen, keyboard, etc.), since I haven’t encountered them at the moment, they are not listed. If necessary, you can click the official documentation link at the end of this article to check.
As of this post, I only found Bilibili with Android 11 on my phone. Most of them are stuck at 28, 29, and even 26 (the minimum fit standard for Android 8.0).
So I also attached the Android 9 and 10 Adapter Guide that I wrote earlier:
- Android 9.0 Adaptation Guide
- Android 10 Adaptation Guide
Maybe you won’t need it for a while. You can, but you can’t. Thumb up collection wave is not too much ~~
reference
- Official Android 11 documentation
- Storage updates in Android 11
- WeChat development platform – Android 11 system policy update
- Oppo – Android 11 app compatibility and adaptation guide
If you feel helpful to you, you can pay attention to my WeChat public number programmer Xu Gong
- Public number programmer Xu Gong reply dark horse, access to Android learning video
- Public number programmer Xu Gong reply Xu Gong 666, get resume template, teach you how to optimize resume, into the big factory
- Public number programmer Xu Gong replied to the interview, you can get the interview common algorithm, sword refers to the offer question solution
- Public number programmer Xu Gong replies horse soldier, can obtain a horse soldier study video