preface
Recently, I saw a news that the final Beta version of Android11 (Version 30, Android R) was released as scheduled. When I saw this news, I knew THAT I could not delay any longer. If I did not prepare well for the arrival of Android11, I would be criticized by customers. Even a letter of divorce from the boss 😂.
Let’s take a look at what Android11 has changed and, most importantly, how we need to adapt it. If targetVersion is not changed to 30, does it need to be adapted?
I will talk about it in two parts as follows
- In order to
Android11
For the target version of the application (targetSdkVersion>=30
To make a difference) ⭐ - All applications in
Android11
Adapt changes on the device (regardless of targetSdkVersion, as long asAndroid11 equipment
Any application running on it is affected.
Why say targetSdkVersion>=30 first? Generally speaking, in order to make us adapt to the new content in a longer time and ensure the stability of the application on the line, Google will put the content with big changes that need time to adapt into the corresponding application of the new targetSdkVersion. If you do not have the requirement of adapting targetSdkVersion30 for the time being, Also look at module 2 to see if it covers your application. GOGOGO!!!
Tips: this adaptation will be constantly updated, according to the progress of the release of Android11 adjustment, welcome to like attention. (Call ⭐ for extra attention)
Adapter targetSdkVersion30
Changes to this module only take effect for targetSdkVersion 30 or above.
Forcibly perform ⭐ for partition storage
Access to external storage directories is limited to application-specific directories and specific types of media that have been created by the application.
As for partitioned storage, it has been implemented in Android10. Simply speaking, the application can only read and write files in the sandbox environment, that is, the directory of its own application. Other media files can be accessed through MediaStore.
But with android10, Google still has one hand reserved for developers. In targetSdkVersion = 29 applications, set the android: requestLegacyExternalStorage = “true”, can not boot partition storage, file read before normal use. But targetSdkVersion = 30 is not available, forcibly enable partition storage. Android, of course, as a human, or left a small hand for developers, if it is cover installation, can increase the android: preserveLegacyExternalStorage = “true”, the temporary closure partition storage, good let developers to complete data migration work. Why temporary? Because as soon as you unload and reinstall it, it won’t work. The following is about partition storage will encounter all the situation, listed for you, first on the code:
fun saveFile(a) {
if (checkPermission()) {
/ / getExternalStoragePublicDirectory is deprecated, partition storage after opening is not allowed to visit
val filePath = Environment.getExternalStoragePublicDirectory("").toString() + "/test3.txt"
val fw = FileWriter(filePath)
fw.write("hello world")
fw.close()
showToast("File write succeeded")}}Copy the code
1) targetSdkVersion = 28, normal read and write after running. 2) targetSdkVersion = 29, do not delete the application, targetSdkVersion is changed from 28 to 29, overwrite the installation, normal read and write after running. 3) targetSdkVersion = 29, delete application, re-run, read and write error, program crash (open failed: EACCES (Permission denied)) 4) targetSdkVersion = 29, add the android: requestLegacyExternalStorage = “true” (not the partition storage), 5) targetSdkVersion = 30, do not delete the application, targetSdkVersion changed from 29 to 30, read and write error, program crash (open failed: EACCES (Permission denied)) 6) targetSdkVersion = 30 Increase the android: preserveLegacyExternalStorage = “true”, normal, speaking, reading and writing is not an error 7) targetSdkVersion = 30, delete the application, rerun, read/write error, the program crashes (open failed: EACCES (Permission denied))
Ok, so what should I change? There are three ways to access files:
1) App specific directories
// Partition storage space
val file = File(context.filesDir, filename)
// Application dedicated external storage space
val appSpecificExternalDir = File(context.getExternalFilesDir(), filename)
Copy the code
2) Access public media directory files
val cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null.null.null."${MediaStore.MediaColumns.DATE_ADDED} desc")
if(cursor ! =null) {
while (cursor.moveToNext()) {
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
val uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
println("image uri is $uri")
}
cursor.close()
}
Copy the code
- SAF(Storage Access Framework)
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "image/*"
startActivityForResult(intent, 100)
@RequiresApi(Build.VERSION_CODES.KITKAT)
override fun onActivityResult(requestCode: Int, resultCode: Int.data: Intent?). {
super.onActivityResult(requestCode, resultCode, data)
if (data= =null|| resultCode ! = Activity.RESULT_OK)return
if (requestCode == 100) {
val uri = data.data
println("image uri is $uri")}}Copy the code
AndroidQ(10) partition storage is a perfect fit for Android q (10) partition storage
Speaking of which, some people may ask, then my app is a mobile phone manager, I have to clear the cache of other apps, there is a way! Android provides two intEnts:
- call
ACTION_MANAGE_STORAGE intent
Operation checks available space. - call
ACTION_CLEAR_APP_CACHE intent
Action clears all caches.
Anyway, the trend is to privatize application data, and it’s better to adapt to partitioned storage sooner rather than later when mobile phones only have sandbox mechanism.
Media file access permission ⭐
To make it easier to access media while maintaining user privacy, Android 11 has added the following features. Perform batch operations and access files using direct file paths and native libraries.
1) Perform batch operations
The bulk operation here refers to the various methods that Android 11 has added to the MediaStore API to simplify the process of changing specific media files (for example, editing photos in situ) :
createWriteRequest()
A request by a user to grant an application write access to a specified media file group.createFavoriteRequest()
A request by the user to mark a specified media file on the device as favorites. Any application that has read access to the file can see that the user has marked the file as favorites.createTrashRequest()
A request by the user to place a specified media file into the device garbage bin. The contents of the trash can are permanently deleted after a system-defined period of time.createDeleteRequest()
A request by the user to delete the specified media file immediately and permanently, rather than putting it in the trash first.
Let’s look at an example:
val urisToModify = listOf(uri,uri,...)
val editPendingIntent = MediaStore.createWriteRequest(contentResolver,
urisToModify)
// Launch a system prompt requesting user permission for the operation.
startIntentSenderForResult(editPendingIntent.intentSender, EDIT_REQUEST_CODE,
null.0.0.0)
override fun onActivityResult(requestCode: Int, resultCode: Int.data: Intent?). {
when (requestCode) {
EDIT_REQUEST_CODE ->
if (resultCode == Activity.RESULT_OK) {
/* Edit request granted; proceed. */
} else {
/* Edit request not granted; explain to the user. */}}}Copy the code
After passing in a collection of URIs and obtaining the user’s approval, you can proceed.
2) Direct file paths and native library access files
That’s right! Android11 has restored access to media files using direct file path access! Haha, this is much more convenient. There are two ways to access media files in addition to the MediaStore API:
- The File API.
- Native libraries, such as fopen().
What about Android10? Maybe use MediaStore, otherwise the partition directly to turn off the storage (requestLegacyExternalStorage = true)
All file access permissions ⭐
Having said that, there are some applications that require access to all files, such as antivirus software and file managers. Don’t worry, there is a way! MANAGE_EXTERNAL_STORAGE. This permission is used to obtain administrative permission for all files. 🌰 :
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
val intent = Intent()
intent.action= Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
startActivity(intent)
// Check whether the MANAGE_EXTERNAL_STORAGE permission has been obtained:
val isHasStoragePermission= Environment.isExternalStorageManager()
Copy the code
Here’s a screenshot for the fun:
Phone number rights ⭐
Android 11 changes the phone-related permissions that your app uses to read phone numbers.
What exactly has changed? There are actually two apis:
- TelecomManager in the class
getLine1Number()
methods - TelecomManager in the class
getMsisdn()
methods
The READ_PHONE_STATE permission is no longer available when using both apis. READ_PHONE_NUMBERS is required.
To be specific, change targetSdkVersion to 30 and run a program to get the phone number:
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.READ_PHONE_STATE), 100)
btn2.setOnClickListener {
val tm = this.applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val phoneNumber = tm.line1Number
showToast(phoneNumber)
}
Copy the code
Collapse:
java.lang.SecurityException: getLine1NumberForDisplay: Neither user 10151 nor current process has android.permission.READ_PHONE_STATE, android.permission.READ_SMS, or android.permission.READ_PHONE_NUMBERS
Copy the code
As expected, the permission is registered in andmanifest.xml and the dynamic permission request is added:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.READ_PHONE_STATE,Manifest.permission.READ_PHONE_NUMBERS), 100)
Copy the code
There you go. If you only need to get phone numbers, you can also apply for READ_PHONE_NUMBERS only:
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
Copy the code
Custom message box view is shielded ⭐
As of Android 11, the custom message box view has been deprecated. If your app is targeting Android 11, message boxes containing custom views will be masked when published from the background
You might wonder, what is a custom message box view? If I say “custom toast views” in English, it means a custom toast. Write a simple code:
Toast toast = new Toast(context);
toast.setDuration(show_length);
toast.setView(view);
toast.show();
Copy the code
Oops oops, custom toast is out? This is what we use in our project! Don’t worry, custom toasts are no longer allowed to display in the background. Let’s say I write a toast 3 seconds later and then go into the background as soon as the app opens to see what happens:
Handler().postDelayed({
IToast.show("Hello, I'm a custom toast.")},3000)
W/NotificationService: Blocking custom toast from package com.example.studynote due to package not in the foreground
Copy the code
Nothing, just a warning. So don’t worry too much. If you really need a background display, just use a toast.
Now you need the APK signature scheme v2 ⭐
For applications that use Android 11 (API level 30) as the target platform and only use APK signature scheme V1, you must use APK signature scheme v2 or later to sign applications. Users cannot install or update applications signed only by APK signature scheme V1 on Android 11 devices.
If you change your targetSdkVersion to 30, you must add the v2 signature. Otherwise, it cannot be installed and updated.
Media Intent operations require the system’s default camera ⭐
Starting with Android 11, only pre-installed system camera apps can respond to the following intEnts:
android.media.action.VIDEO_CAPTURE
android.media.action.IMAGE_CAPTURE
android.media.action.IMAGE_CAPTURE_SECURE
That is, if I call the intent to invoke the camera and use the VIDEO_CAPTURE action, only the system camera will respond, and the third-party camera application will not.
val intent=Intent()
intent.action=android.provider.MediaStore.ACTION_IMAGE_CAPTURE
startActivity(intent)
// No third-party cameras can be invoked, only system cameras can be invoked
Copy the code
This is a bit of a blow to normal camera apps. The official advice is that if you want to use a particular third-party camera app to capture images or videos on its behalf, you can make the intent explicit by setting the package name or component for the intent.
5 g ⭐
Android 11 adds support for 5G in your apps
The new Android11 also supports 5g-related features, including:
- Check if you’re connected to a 5G network
- Check per-traffic billing
The first is to detect the 5G network through TelephonyManager’s listening method:
private fun getNetworkType(a){
val tManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
tManager.listen(object : PhoneStateListener() {
@RequiresApi(Build.VERSION_CODES.R)
override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
if (ActivityCompat.checkSelfPermission(this@Android11Test2Activity, android.Manifest.permission.READ_PHONE_STATE) ! = android.content.pm.PackageManager.PERMISSION_GRANTED) {return
}
super.onDisplayInfoChanged(telephonyDisplayInfo)
when(telephonyDisplayInfo.networkType) {
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> showToast("Advanced Professional LTE (5Ge)")
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> showToast("NR (5G) - 5G sub-6 Network")
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> showToast("5G+/5G UW-5G mmWave network")
else -> showToast("other")
}
}
}, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
}
Copy the code
If it’s 5G, you’re going to have to figure out if it’s pay-as-you-go, or 5g data is no joke.
Detecting the traffic billing method is also very simple, listening to the network, in the callback to determine:
val manager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
manager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities)
//true indicates that the connection is not charged by traffic
val isNotFlowPay=networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) ||
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)
}
})
Copy the code
Determine the value, if true, then the connection is treated as not billed by traffic.
Background location information access permission ⭐
On Android 11 devices, when a function in an application requests background location information, the system dialog box no longer contains a button to enable background location information access. To enable the permission to access background location information, you must set the permission option for all applications on the Settings page.
What does that mean? It mainly involves two points:
- Starting with devices running Android10, you need to request background location permissions
(ACCESS_BACKGROUND_LOCATION)
And selectAllow all the time
To obtain background location permissions. Again on Android11 devicesTo strengthen
Background permission management, mainly in theSystem dialog box
On, the dialog box no longer prompts “always allow”, but provides a setting entry for location permissions, which needs to be selected on the setting pageAlways allow
To obtain background location permissions. - In carrying
Android11 system
On the device, when targetVersion is less than 30, the foreground and background location permission can be applied together, and the dialog box provides a text description, indicating that the user location information needs to be obtained at any time, enter the setting selectionAlways allow
Can. But with targetVersion 30, you have toTo apply for alone
Background location permissions, and after obtaining foreground permissions,Don't mess with the order
. And there is no hint, the developer needs to design their own hint style.
It may be a bit convoluted, but here are a few examples:
1) Android10 device, apply foreground and background location permissions (any targetSdkVersion) :
requestPermissions(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_BACKGROUND_LOCATION), 100)
Copy the code
Execution effect:
2) Android11 device, targetSdkVersion<=29(Android 10),
requestPermissions(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_BACKGROUND_LOCATION), 100)
Copy the code
Execution effect:
3) Android11 device, targetSdkVersion=30(Android 11)
requestPermissions(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_BACKGROUND_LOCATION), 100)
Copy the code
Executive nonresponse
4) Android11 device, targetSdkVersion=30(Android 11), apply foreground location permission first, then apply background location permission:
requestPermissions(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), 100)
Copy the code
Execution effect:
requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), 100)
Copy the code
Execution effect (directly jump to the Settings page, without any explanation) :
So how do you fit in?
targetSdkVersion<30
In this case, if you already have access to the foreground and background locations, don’t worry, there is nothing to adapt.targetSdkVersion>30
In this case, it is necessary to apply for the front and back location permissions separately, and explain and guide the application for background location permissions, of course, in order to better serve users.
Permission application demo code:
val permissionAccessCoarseLocationApproved = ActivityCompat
.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION) ==
PackageManager.PERMISSION_GRANTED
if (permissionAccessCoarseLocationApproved) {
val backgroundLocationPermissionApproved = ActivityCompat
.checkSelfPermission(this, permission.ACCESS_BACKGROUND_LOCATION) ==
PackageManager.PERMISSION_GRANTED
if (backgroundLocationPermissionApproved) {
// Have access to both front and back locations
} else {
// Apply for background permission
if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.R){
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
200)}else{
AlertDialog.Builder(this).setMessage("Background location permission is required, please select Always Allow on the Settings page")
.setPositiveButton("Sure", DialogInterface.OnClickListener { dialog, which ->
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
200)
}).create().show()
}
}
} else {
if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.R){
// Apply for foreground and background location permissions
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_BACKGROUND_LOCATION),
100)}else{
// Apply for foreground location permission
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
100)}}Copy the code
Package visibility ⭐
Android 11 changes how apps query and interact with other apps that users have installed on the device. With the new element, an application can define a set of other applications that are themselves accessible. This element helps encourage the minimum permission principle by telling the system what other applications to show your application. In addition, this element can help app stores such as Google Play evaluate the privacy and security that an app provides to users.
In Android11, if you want to get the information of other applications, such as package name, name, etc., you can not directly get the information. You must add the
element in the list file to tell the system which application information you want to get or which kind of application.
For example, I have this code to query application information:
val pm = this.packageManager
val listAppcations: List<ApplicationInfo> = pm
.getInstalledApplications(PackageManager.GET_META_DATA)
for (app in listAppcations) {
Log.e("lz",app.packageName)
}
Copy the code
In Android11 version, you can only query the information of your application and system application, and can not check the information of other applications. How do? Add the
element in two ways:
1) Add package names to the element
<manifest package="com.example.game">
<queries>
<package android:name="com.example.store" />
<package android:name="com.example.services" />
</queries>
...
</manifest>
Copy the code
1) Add a fixed filter intent to the element
<manifest package="com.example.game">
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/jpeg" />
</intent>
</queries>
</manifest>
Copy the code
Some people may still wonder, what if my app is a browser or device manager? I’m gonna get all the package names, right? Rest assured, Android11 also introduces QUERY_ALL_PACKAGES permissions, which can be added to the manifest file. Google Play doesn’t have to be abusive, though. It has guidelines for applications that require QUERY_ALL_PACKAGES permissions, but they’re not available yet.
As for the domestic market… (Let’s hope there’s an app market that rules the world and manages this mess!)
Document access restrictions
To give developers time to test, the following changes related to the Storage Access Framework (SAF) will only take effect if the app is targeted at Android 11.
SAF(Storage Access Framework) can be used to Access public directories, but Android11 has updated some directories and files again. Details are as below:
The following directories can no longer be requested using ACTION_OPEN_DOCUMENT_TREE Intent:
- Root directory of the internal storage volume.
- The root directory of each SD card volume that the device manufacturer considers reliable, whether the card is an analog or removable card. A reliable volume is one that an application can access successfully in most cases.
- The Download directory.
You can no longer use ACTION_OPEN_DOCUMENT_TREE or ACTION_OPEN_DOCUMENT Intent actions to request the user to select a separate file from the following directory:
- The Android/data/ directory and all its subdirectories.
- The Android/obb/ directory and all its subdirectories.
Restrict read access to the APN database
11 for the application of the target platform for Android now. Must be able to Manifest the permission. WRITE_APN_SETTINGS privileges, to read or access phone provider APN database. If you try to access the APN database without this permission, a security exception is generated.
So the question is, what is APN?
- APN refers to a network access technology that must be configured to access the Internet through mobile phones. APN parameters include name, carrier ID, and APN access point.
That is to say if there is no Manifest. Permission. WRITE_APN_SETTINGS permissions will not be able to read the APN database, but! This privilege has long been restricted to only system applications, now this privilege does not understand what it means, does the system applications can not apply for it? You can leave a message in the comments section.
Declare accessibility button usage in the metadata file
Starting with Android 11, your accessibility service cannot declare an association with the system’s accessibility button at runtime. If you will AccessibilityServiceInfo FLAG_REQUEST_ACCESSIBILITY_BUTTON attached to AccessibilityServiceInfo flags attribute of the object, The framework will not pass the “accessibility” button callback event to your service.
If you’ve done accessibility accessibility, you’ll know that AccessibilityServiceInfo is FLAG_REQUEST_ACCESSIBILITY_BUTTON, GetAccessibilityButtonController method for auxiliary function button controller, and can be used to query the state of the auxiliary function button and register the listener to interact and auxiliary function button state changes.
However, starting with Android 11, you can no longer get the auxiliary button callback event by writing it this way, so you have to write it differently. In the metadata file (usually a res/raw/accessibilityservice. XML) used in flagRequestAccessibilityButton tag statement your barrier-free service connection with “barrier-free” button.
Firebase JobDispatcher and GCMNetworkManager
If your application targets platforms with API level 30 or higher, Firebase JobDispatcher and GcmNetworkManager API calls will be disabled on devices running Android 6.0 (API level 23) or higher.
These two apis are not used domestically and are mainly used for background tasks. The official alternative is WorkManager, which is available in China and belongs to the Jetpack component, which is mainly used for scheduling and performing deferred background work.
Device to device file transfer
If your application is targeting Android 11, you will no longer be able to disable device-to-device migration of application files using the allowBackup property. The system automatically enables this function. However, even if your application is targeting Android 11, you can disable cloud backup and recovery of application files by setting the allowBackup property to false.
Android: allowBackup properties
- Indicates whether applications are allowed to participate in backup and recovery of the infrastructure. If this property is set to false, it will never be executed for the application
Backup or Restore
This is true even for system-wide backups, which typically save all application data through ADB. The default value for this property is true.
So you can’t disable device-to-device migration of files, but you can disable cloud backup and recovery
Automatic reset permission
If the app is targeted at Android 11 and has not been used for several months, the system protects the user’s data by automatically resetting the run-time sensitive permissions that the user has granted to the app. This action is the same as if the user views the permissions in the system Settings and changes the application’s access level to deny. If the application has followed best practices for requesting permissions at run time, you do not need to make any changes to the application. This is because when users interact with features in your application, you should verify that the relevant features have the required permissions.
The official instructions are clear, and as long as the application follows best practices for requesting permissions at run time, which is to determine every time a permission needs to be invoked, then there should be no problem.
What if you need to turn this feature off? With the user to Settings page closed, you can call an Intent containing settings. ACTION_APPLICATION_DETAILS_SETTINGS action to direct the user to the page applied in system Settings.
How do I check if auto reset is disabled? Call the PackageManager’s isAutoRevokeWhitelisted() method. If this method returns true, the system does not automatically reset application permissions.
Front Desk Service Type
Starting with Android 9, apps are limited to foreground access to the camera and microphone. To further protect users, Android 11 changes the way foreground services access data related to cameras and microphones. If your application targets The Android 11 platform and accesses these types of data in a foreground service, you need to add the new Camera and MICROPHONE types to the foregroundServiceType property declared by the foreground service.
When Android10 for front desk location services must be combined with android: foregroundServiceType = “location”, now Android11 added two permissions, a camera is a microphone.
So to sum up, if applying a foreground service requires access to location information, camera, and microphone, add this to the manifest file:
<manifest>
<service ...
android:foregroundServiceType="location|camera|microphone" />
</manifest>
Copy the code
Some friends may test found that, without the premise of foregroundServiceType, let the Activity start a foreground service, and in the service to get location, unexpectedly can get location information, did the official say wrong?
This is because you don’t have the foreground Service running on its own. You can try to enter the Home screen after the Activity starts the Service and ask for the location a few seconds later. It will not crash because the permission category is MODE_IGNORED, which is silent failure mode.
So to be on the safe side, as long as the front desk service involves the three functions, in the manifest file with android: foregroundServiceType
For Android11 phones
The changes in this module are for all projects that exist on Android11 phones and are not related to targetSdkVersion.
Data access audit ⭐
To make the process by which apps and their dependencies access users’ private data more transparent, Android 11 has introduced data access auditing. With insights from this process, you can better identify and correct potential for unexpected data access.
What are the categories of user private data? This function provides a listener that can listen for dangerous permission calls. Mainly involves is AppOpsManager OnOpNotedCallback. Any access to private data (dangerous permissions) will be called back to us, either from the app itself or from code in the dependent libraries or SDK.
This function is suitable for large projects or projects that use more SDKS to make the private data management of their applications more transparent and standardized, otherwise the use and management of private data is not comprehensive and convenient. And you can also use add attribution for permissions, which is a tag, to indicate where the permissions are being used. It’s easy to know where private data is being used during callbacks.
🌰 to:
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test1)
// Create an attribute
attributionContext = createAttributionContext("shareLocation")
// Listen on events
val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
private fun logPrivateDataAccess(
opCode: String, attributionTag: String, trace: String) {
Log.i(TAG, "Private data accessed. " +
"Operation: $opCode\n " +
"Attribution Tag:$attributionTag\nStack Trace:\n$trace")}override fun onNoted(syncNotedAppOp: SyncNotedAppOp){ syncNotedAppOp.attributionTag? .let { logPrivateDataAccess(syncNotedAppOp.op, it, Throwable().stackTrace.toString()) } }override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp){ syncNotedAppOp.attributionTag? .let { logPrivateDataAccess(syncNotedAppOp.op, it, Throwable().stackTrace.toString()) } }override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp){ asyncNotedAppOp.attributionTag? .let { logPrivateDataAccess(asyncNotedAppOp.op, it, asyncNotedAppOp.message) } } }// Enable private data listening
val appOpsManager =
getSystemService(AppOpsManager::class.java) as AppOpsManager
appOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback)
btn1.setOnClickListener {
getLocation()
}
}
fun getLocation(a) {
val locationManager = attributionContext.getSystemService(
LocationManager::class.java) as LocationManager
if(! checkPermission()) {return
}
val location: Location? = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
if(location ! =null) {
showToast("${location.latitude}")}}Copy the code
This example mainly shows a function to getLocation information. If the getLocation method is called, the onNoted callback will be triggered. The callback includes danger permission code and attribution.
OnOpNotedCallback has three callback methods:
onNoted
This method is normally called back toonAsyncNoted
OnAsyncNoted () is called if the data access is not happening during an application call to the API, such as some listener callbacks.onSelfNoted
In rare cases, onSelfNoted() is called if an application passes its UID to noteOp().
Finally click the button to see the result log of the next callback:
Private data accessed. Operation: android:coarse_location
Attribution Tag:shareLocation
Stack Trace:
[Ljava.lang.StackTraceElement;@14f5a16
Copy the code
You can see the permission code: Android :coarse_location and attribution shareLocation
A single license
In Android 11, every time an app requests permission related to location information, microphone, or camera, the user-facing permission dialog box contains a once-only option. If the user selects this option in the dialog box, the system grants temporary single authorization to the application.
In simple terms, when applying for permission related to location information, microphone or camera, the system will automatically provide a single authorization option, which can be obtained only once. Then the next time the user opens the app, the system will prompt the user to grant permission again. This effect should not be big, as long as we use every time to judge the authority, not to apply for. Put a new version of the permission get style:
Visibility of the Permissions dialog box
Android 11 recommends not asking for permissions that the user has chosen to deny. After the application is installed on the device, if the user repeatedly clicks Reject for a specific permission, this operation indicates that the user wants to “ask no more”.
This is not even a change, just a good suggestion from the authorities. It is recommended that you do not display permission requests after the user rejects them for several times.
Scudo Hardened Allocator
Android 11 internally uses Scudo Hardened Locator to provide services for heap allocation. Scudo is able to detect and mitigate certain types of memory security violations. If you find scudo-related crashes (such as Scudo ERROR 🙂 in native code crash reports, refer to the Scudo troubleshooting documentation.
Scudo is a dynamic user-mode memory allocator designed to withstand heap-related vulnerabilities while maintaining good performance. It is an open source project. In Android 11, the new Heap allocator will be used for better performance and more security.
File descriptor debugger
Android 10 introduces FDSAN (file descriptor debugger). Fdsan detects error handling of file descriptor ownership errors, such as use-after-close and double-close. In Android 11, the default mode for FDSAN has changed. Fdsan now aborts when an error is detected, whereas the previous behavior was to log a warning and continue.
The question is, what is FDSAN? First, understand what fd is
FileDescriptor is a concept related to file operations in Unix/Linux systems. It is a non-negative integer in form. When a program opens an existing file or creates a new file, the kernel returns a file descriptor to the process. The process of the system is to use the FD to mark the open file, it can do a variety of operations on the file, obtain a variety of relevant information of the file.
So FDSAN is just a way of detecting errors in file processing.
Application usage statistics
To better protect users, Android 11 stores app usage statistics for each user in a credential encrypted storage space.
This involves UsageStatsManager, the Android service that provides statistics on app usage. This service allows you to obtain application usage statistics, component state change event statistics, and hardware configuration information statistics for a specified time interval.
QueryAndAggregateUsageStats method, for example, you can get use statistical data within the specified time interval, in packages called merge keys for data.
But on Android 11 devices, sorry, you can’t use this information freely. The data is accessible only if the isUserUnlocked() method returns true. That is, the following two situations:
- The user unlocks the device for the first time after the system starts
- Users switch to their own accounts on the device
The JobScheduler API calls restrict debugging
JobScheduler Is a task scheduler that can perform tasks when the device is idle. On Android11 if you set it to Debug mode (the debuggable list property is set to true), JobScheduler API calls that exceed the rate limit will return RESULT_FAILURE. What’s the use of this? This should help us find some performance issues, so if you’re interested, try it out for yourself.
By the way, Jetpack component WorkManager also uses JobScheduler. If you are not familiar with it, JobScheduler is a system service started by the SystemServer process, so it has such a large authority.
Barrier-free operation
In previous versions of Android, the framework dispatched touch events to widgets that did not properly handle click-based accessibility. Typically, these views handle touch events directly, rather than registering click listeners.
In order to create more consistent behavior in applications that properly define accessibility, Android 11 will never dispatch touch events. Instead, the system relies entirely on click-based accessibility: ACTION_CLICK and ACTION_LONG_CLICK. This change affects the behavior of screen readers.
There’s a pre-installed screen reading service on Android phones called TalkBack for visually impaired or elderly people with poor vision. So in order for this reader to be able to read your custom view action, we have to give the custom control a custom handler, including click, long press and so on. The original version may also support barrier-free touch events for OnTouchListener, whereas in Android11 you have to specify click or hold events. Give a 🌰 :
class TriSwitch(context: Context) : Switch(context) {
// 0, 1, or 2.
var currentState: Int = 0
private set
init {
updateAccessibilityActions()
}
private fun updateAccessibilityActions(a) {
ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,
action-label) {
view, args -> moveToNextState()
})
}
private fun moveToNextState(a) {
currentState = (currentState + 1) % 3}}Copy the code
A custom controls TriSwitch, inherited from the Switch, because and click on the effect of the Switch is different, so you must by replacing ViewCompat. ReplaceAccessibilityAction () to redefine the corresponding barrier-free operation.
Non-sdk interface restrictions
Android 11 includes an updated list of restricted non-SDK interfaces (based on collaboration with Android developers and recent internal testing). Before we restrict the use of non-SDK interfaces, we try to ensure that we provide exposed alternatives as much as possible.
As usual, Android11 will also restrict some interfaces, including the gray list and white list, to see the list of non-sdk interfaces
conclusion
It can also be seen that important changes, especially those involving crashes, are placed in the targetSdkVersion=30 content. This is also an unwritten rule of every Android release, in order to minimize the impact of the online app. But that doesn’t mean we can’t change. Because the app can’t afford to drag, users can’t afford to drag, after all, upgrade to give users the best experience. TargetSdkVersion is also recommended or mandatory for every major app market to be updated for the latest phones.
So go for it.
The attachment
Introduction to changes on official website
My public number: code on building blocks, every day three interview questions, detailed analysis, help you become offer harvester.
Thank you for reading, and if you think it’s ok, just give it a thumbs up! Thank you! One of your 👍 is my motivation to share ❤️.