Android R (Android 11 API 30) was officially released on September 9, 2020. With the update and upgrade of Android devices sold by various domestic terminal manufacturers, the compatibility and adaptation of Android R version of application software is imminent.

The new features of Android R are summarized in the following aspects: partitioned storage, permissions, privacy, performance, and security.

Official document description: developer. The android. Google. Cn/about/versi…

1. Partition storage

Starting from Android 10 (API) 29, open the Android default partition storage function, but should be increased through Android 10 Android: requestLegacyExternalStorage = “true” disable partition storage configuration; Starting from Android 11 (API) 30, enforce partition storage, 11 and above for Android devices, Android: requestLegacyExternalStorage = “true” configuration will no longer valid.

11 partition storage official description: Android developer. The Android, Google. Cn/training/da… 10 the default Android open partition storage: xiaxl.blog.csdn.net/article/det…

1.1. Access directories

After partitioned storage is enabled, an application can access only application-specific directories (internal and external application-specific directories) and specific types of media files created by the application by default.

  • Application Specific Directory

Directories for internal and external storage (for example, the application package name com.xiaxl.demo) : / data/data/com. Xiaxl. Demo/files, / sdcard/Android/data/com xiaxl. The demo/files respectively using the following API to access: File appFile = new File(context.getFilesDir(), filename); File appExternalFile = new File(context.getExternalFilesDir(), filename);

  • Shared Storage Directory

This includes media, documents, and other files. Directories such as DCIM, Pictures, Movies, Download, etc. Note: Shared storage directories in Android 10(Android Q) are accessed using the MediaStore API. Android 11(Android R) supports the MediaStore API and File API for accessing shared storage directories. To ensure that applications running on Android 10 and Android 11 have the same File access permissions on shared storage directories, use the File API. Suggestions in AndroidManifest application configuration file, add requestLegacyExternalStorage = “true” logo, in order to close the Android devices 10 partition storage function, make the partition storage for Android only 11 more effective equipment:

1.2. Access required permissions

  • Application Specific Directory

Read and write the application exclusive directory (internal storage, external storage exclusive directory), Android 4.4 or higher devices do not need any permission;

  • Shared Storage Directory

The READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions are required for reading and writing shared storage paths.

On devices later than Android 11, if your application requests the READ_EXTERNAL_STORAGE permission again, the dynamic permission request window changes to your application is requesting access to photos and media.

File access media official description: developer. The android. Google. Cn/training/da…

1.3. Sharing Files

If you need to share a single file or application data with other applications, you can use the API:

  • FileProvider(Share one or more of your own files)

If an application needs to make one or more of its files available to other applications, it is safe to send the content URI of the file to the receiving application and grant temporary access to that URI. The Android FileProvider component provides the getUriForFile() method, which is used to generate the file’s content URI.

  • ContentProvider(Obtain data provided for other applications)

If you need to provide data to other applications, use a ContentProvider. ContentProvider is a standard interface for connecting data in one process to code running in another process.

11 Shared file official description: Android developer. The Android, Google. Cn/training/da…

1.4. Access to all files

Some applications require access to all files, such as file manager software. To obtain the permission for all files, apply for the MANAGE_EXTERNAL_STORAGE permission.

// Permission configuration
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

// Check whether the MANAGE_EXTERNAL_STORAGE permission is available
Environment.isExternalStorageManager();

// Jump to the Settings page and request user authorization
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);

Copy the code

MANAGE_EXTERNAL_STORAGE related official description: developer. The android. Google. Cn/training/da…

Second, the permissions

The following changes have been made to permissions in Android 11:

  • newREAD_PHONE_NUMBERSPermission to obtain mobile phone numbers;
  • Background access locationPermission adjustment;
  • The userMultiple requests for a specific permissionpointRefused toRepresents the user’s wishesNo longer ask;
  • applicationNot used for a long time, the system willAutomatically resets sensitive permissions granted to users;
  • forLocation, microphone, cameraAdded authorization pop-upsJust this onceAuthorization button;
  • SYSTEM_ALERT_WINDOWThe permission authorization mode is changed to automatic authorization.

Reference 11 permissions to update the official document: Android developer. The Android, Google. Cn/about/versi…

2.1. Add READ_PHONE_NUMBERS permission

When the application targetSdkVersion>=30 is used to obtain mobile phone numbers using the following API, you need to apply for READ_PHONE_NUMBERS instead of READ_PHONE_STATE permission.

  • TelephonyManagerClasses andTelecomManagerIn the classgetLine1Number()Methods.
  • TelephonyManagerClass that is not supportedgetMsisdn()Methods.

On Android 10 and older devices, you can continue to use READ_PHONE_STATE to get the phone number; For Android11 and later devices, you need to obtain the READ_PHONE_NUMBERS permission to obtain the phone number.

<manifest>
    <! -- Get the READ_PHONE_STATE permission on Android 10 and below devices only to get the terminal phone number -->
    <uses-permission android:name="READ_PHONE_STATE"
                     android:maxSdkVersion="29" />
	<! -- Android 11 or later get READ_PHONE_NUMBERS permission to get terminal phone numbers -->
    <uses-permission android:name="READ_PHONE_NUMBERS" />
</manifest>
Copy the code

forREAD_PHONE_STATEpermissions

  • Android 10 startCommon applicationCan no longerRead the hardware ID of the deviceInformation;

The information reference xiaxl.blog.csdn.net/article/det… ;

  • Android 11 beganObtaining mobile phone NumberRelated apis are replaced withREAD_PHONE_NUMBERSPermissions;

READ_PHONE_NUMBERS authority official API description: developer. The android. Google. Cn/reference/a…

2.2 Background access position permission adjustment

  • On Android10 devices, meanwhileApply for foreground and background location permissionWhen the user selectsAlways allowAfter, can obtain background location permission.
  • On Android11 devices, fortargetSdkVersion<=29(Android 10)At the same timeApply for foreground and background location permissionThe dialog box no longer prompts always allow, but instead provides a location permission setting entry, as requiredThe user chooses always allow on the Settings pageTo obtain background location permissions.
  • On Android11 devices, fortargetSdkVersion=30(Android 11)At the same timeApply for foreground and background location permission, the system ignores the request and has no response (You must first obtain the foreground location permission and then apply for the background location permission).
  • On Android11 devices, fortargetSdkVersion=30(Android 11)The application of theApply for foreground location permission first, and then apply for background location permission.

Position the background access Description: the official developer. The android. Google. Cn/training/lo…

A. Android10 devices

On Android10 devices, when applying for foreground and background location permission at the same time, the user can obtain background location permission only after selecting always allow.

// On Android10 devices, . At the same time, application foreground and the background location permissions ActivityCompat requestPermissions (this, new String [] {the Manifest. Permission. ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 101);Copy the code

B, Android11 device targetSdkVersion<=29

On Android11 devices, for targetSdkVersion<=29(Android 10) applications, when applying for foreground and background location permission at the same time, the dialog box no longer prompts “always allow”, but provides the setting entrance of location permission. The user must select always Allow on the Settings page to obtain background location permission.

// On Android11 devices, apply for foreground and background location permissions with targetSdkVersion<=29
ActivityCompat.requestPermissions(this.new String[]{
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 101);
Copy the code

C. Android11 device targetSdkVersion=30 Apply for foreground and background location permissions at the same time

  • On Android11 devices, fortargetSdkVersion=30(Android 11)At the same timeApply for foreground and background location permission, the system ignores the request and has no response (You must first obtain the foreground location permission and then apply for the background location permission).
// On Android11 devices, apply for foreground and background location permissions with targetSdkVersion=30
// There is no response to the request
ActivityCompat.requestPermissions(this.new String[]{
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 101);
Copy the code

D. Android11 device targetSdkVersion=30 Apply for foreground and background location permissions in sequence

On Android11 devices, for applications targetSdkVersion=30(Android 11), apply for foreground location permission first, and then apply for background location permission.

// On Android11 devices, with targetSdkVersion=30, apply for foreground location permission
ActivityCompat.requestPermissions(this.new String[]{
        Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
Copy the code

Android11 device, targetSdkVersion=30 application, apply background location permission, jump directly to the Settings page.

// On Android11 devices, apply for background location permission with targetSdkVersion=30
ActivityCompat.requestPermissions(this.new String[]{
        Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 101);
Copy the code

2.3, the userMultiple requests for a specific permissionpointRefused to

In Android 11, if a user clicks “reject” several times for a particular permission request, the user will not see a system permission popup when the application requests that permission again.

2.4. If it is not used for a long time, it automatically resets the sensitive permissions granted

In Android 11, when targetSdkVersion>=30 is not used for a period of time, the system protects user data by automatically resetting the run-time sensitive permissions that the user has granted to the application.

2.5. Added the “Only this once” authorization button

Starting with Android 11 (API level 30), the user-facing authorization dialog box includes a once-only option when an application requests permission related to location, microphone, or camera. If the user selects this time only in the dialog box, the system grants temporary single authorization to the application.

The permission application API is used in the same way:

private void showCameraPreview(a) {
    // Check whether you have Camera permission
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
            == PackageManager.PERMISSION_GRANTED) {
        // Go to the Camera page
        // startCamera();
    } else {
        // Request Camera permissionrequestCameraPermission(); }}private void requestCameraPermission(a) {
    // Check whether Camera permission has been "denied" by the user.
    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            Manifest.permission.CAMERA)) {
        // The popup window tells the user, why do I need Camera permission
        Snackbar.make(mLayout, R.string.camera_access_required,
                Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok, new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Request Camera permission
                ActivityCompat.requestPermissions(MainActivity.this.new String[]{Manifest.permission.CAMERA},
                        PERMISSION_REQUEST_CAMERA);
            }
        }).show();

    } else {
        // Request Camera permission
        ActivityCompat.requestPermissions(this.newString[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA); }}@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    if (requestCode == PERMISSION_REQUEST_CAMERA) {
        // User authorization Camera (user select "use when allowed", "only this time allowed")
        if (grantResults.length == 1
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permission has been granted. Start camera preview Activity.
            Snackbar.make(mLayout, R.string.camera_permission_granted,
                    Snackbar.LENGTH_SHORT)
                    .show();
            startCamera();
        }
        // The user selects "reject"
        else {
            // Permission request was denied.Snackbar.make(mLayout, R.string.camera_permission_denied, Snackbar.LENGTH_SHORT) .show(); }}}Copy the code

Source code reference: github.com/android/per… ;

2.6 SYSTEM_ALERT_WINDOW permission authorization mode

On Android 11, the SYSTEM_ALERT_WINDOW permission mode is changed to automatically grant the SYSTEM_ALERT_WINDOW permission to certain applications upon request.

  • The system automatically identifies aROLE_CALL_SCREENINGAnd requestSYSTEM_ALERT_WINDOWGrant this permission to all applications of. If the application losesROLE_CALL_SCREENING, the permission will be lost.

ROLE_CALL_SCREENING is a constant class in RoleManager. It is mainly used to inform users to replace our application with the pre-loaded application (SMS, phone dialing) of mobile phones.

  • The system will automatically pass throughMediaProjectionCapture the screen and requestSYSTEM_ALERT_WINDOWGrant the permission to all applications unless the user has explicitly refused to grant the permission to the application. This permission is lost when the application stops capturing the screen. This use case is primarily used for live game applications.

SYSTEM_ALERT_WINDOW authority official description: developer. The android. Google. Cn/about/versi…

Third, privacy protection

The major changes involve the following aspects:

  • Software package visibility: Obtain other application information from theAndroidManifestadd<queries>The label;
  • Front desk services: access to location information, cameras, microphone restrictions;
  • Obtaining the permanent SIM card identifier ICCID is restricted.
  • newAppOpsManager.OnOpNotedCallbackListen for calls of dangerous permissions to protect users’ private data;

This allows you to monitor access requests for third-party libraries

3.1 Software package visibility

  • On Android 11 and later devices, when the apptargetSdkVersion>=30If an application wants to obtain information about other applications, such as the package name and software name, the application cannot obtain the information in the original mode.
  • To obtain other application information, visit theAndroidManifestadd<queries>Element tag that tells the system which application or type of application information it wants to obtain.
  • If you need to get information about all applications (e.g., Launcher application, device manager application) : In this case, you only need to use theAndroidManifestaddQUERY_ALL_PACKAGESPermission can.

QUERY_ALL_PACKAGES permissions are common permissions and do not require dynamic application. However, after submission to the app market, the app market may review

Package visibility official description: developer. The android. Google. Cn/about/versi…

 <manifest package="com.xiaxl.myapp">// 1, if you know the package name of the specific application<queries>
        <package android:name="com.xiaxl.otherapp01" />
        <package android:name="com.xiaxl.otherapp01" />
    </queries>// do not know the package name, but want to know the application information of a certain type of App<queries>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="image/jpeg" />
        </intent>
    </queries>	
</manifest>
Copy the code

3.2 Reception services: access to location information, cameras and microphones is limited

When targetSdkVersion>=30 is applied, foregroundServiceType must be added when the foreground service accesses the location information, camera, and microphone.

<manifest>// Foreground service access: location information, camera, microphone<service
        android:foregroundServiceType="location|camera|microphone" />
</manifest>
Copy the code

The front desk service Description: the official developer. The android. Google. Cn/about/versi…

3.3 Obtaining the permanent SIM card identifier ICCID is restricted

11 and higher in the Android version, using SubscriptionInfo. GetIccId () method to access cannot be reset ICCID is restricted.

SubscriptionInfo. GetIccId () method returns a non-null empty string.

To uniquely identify the SIM card installed on the device, use the getSubscriptionId() method instead. The SubscriptionId provides an index value that uniquely identifies installed SIM cards (both physical and electronic), and the value of this identifier remains constant for a given SIM card until the device is restored to factory Settings.

3.4. Listen for the invocation of dangerous permissions

11 new Android AppOpsManager. OnOpNotedCallback for developers using listening for application of dangerous permissions, so as to protect the user’s private data. When the application and the application of rely on the package, when applying for a dangerous permissions, AppOpsManager. OnOpNotedCallback corresponding callback method will be invoked, and print the application permissions with the corresponding API call stack.

Example: when using access to location information, the callback will be AppOpsManager. OnOpNotedCallback onNoted method, and printing permission to use with the corresponding API call stack.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //
    AppOpsManager.OnOpNotedCallback appOpsCallback =
            new AppOpsManager.OnOpNotedCallback() {
                private void logPrivateDataAccess(String opCode, String trace) {
                    Log.i("xiaxl: "."opCode: " + opCode + "\n trace: " + trace);
                }

                @Override
                public void onNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
                    Log.i("xiaxl: "."---onNoted---");
                    logPrivateDataAccess(syncNotedAppOp.getOp(),
                            Arrays.toString(new Throwable().getStackTrace()));
                }

                @Override
                public void onSelfNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
                    Log.i("xiaxl: "."---onSelfNoted---");
                    logPrivateDataAccess(syncNotedAppOp.getOp(),
                            Arrays.toString(new Throwable().getStackTrace()));
                }

                @Override
                public void onAsyncNoted(@NonNull AsyncNotedAppOp asyncNotedAppOp) {
                    Log.i("xiaxl: "."---onAsyncNoted---"); logPrivateDataAccess(asyncNotedAppOp.getOp(), asyncNotedAppOp.getMessage()); }}; AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);if(appOpsManager ! =null) { appOpsManager.setOnOpNotedCallback(getMainExecutor(), appOpsCallback); }}public void getLocation(a) {
    // Create attributions
    Context attributionContext = createAttributionContext("shareLocation");
    // Get location information
    LocationManager locationManager =
            attributionContext.getSystemService(LocationManager.class);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ! = PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) ! = PackageManager.PERMISSION_GRANTED) {return;
    }
    Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
Copy the code

The following logs are displayed:

---onNoted---
opCode: android:coarse_location
trace: 
[com.xiaxl.android_test.MainActivity$1.onNoted(MainActivity.java:42), 
 android.app.AppOpsManager.readAndLogNotedAppops(AppOpsManager.java:8204), 
 android.os.Parcel.readExceptionCode(Parcel.java:2304), 
 android.os.Parcel.readException(Parcel.java:2279), 
 android.location.ILocationManager$Stub$Proxy.getLastLocation(ILocationManager.java:1225),
 android.location.LocationManager.getLastKnownLocation(LocationManager.java:648),
 com.xiaxl.android_test.MainActivity.getLocation(MainActivity.java:87),
 com.xiaxl.android_test.MainActivity$2.onClick(MainActivity.java:70),
 android.view.View.performClick(View.java:7448),
 com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967),
 android.view.View.performClickInternal(View.java:7425),
 android.view.View.access$3600(View.java:810),
 android.view.View$PerformClick.run(View.java:28305),
 android.os.Handler.handleCallback(Handler.java:938),
 android.os.Handler.dispatchMessage(Handler.java:99),
 android.os.Looper.loop(Looper.java:223),
 android.app.ActivityThread.main(ActivityThread.java:7656),
 java.lang.reflect.Method.invoke(Native Method),
 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592),
 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)]
 
Copy the code

According to the above logs, when an application applies for ACCESS_COARSE_LOCATION permission and obtains location information, the application permission and the corresponding API call stack are printed.

AppOpsManager related official description: developer. The android. Google. Cn/guide/topic…

Four, performance,

  • The JobScheduler uses frequency limits

4.1. The use frequency of JobScheduler is limited

Android 11 limits the frequency of using JobScheduler. For applications with the debuggable list attribute set to True, excessive calls to the JobScheduler API will return RESULT_FAILURE.

JobScheduler is mainly used to trigger the execution of a task when certain conditions are met at a certain time in the future. For example, when the device is idle and wifi is used, Apk is automatically downloaded. A typical example of JobScheduler is as follows:

 JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);  
ComponentName jobService = new ComponentName(this, MyJobService.class);

// The task Id is 123
JobInfo jobInfo = new JobInfo.Builder(123, jobService) 
	 // Minimum task latency
     .setMinimumLatency(5000)
	 // The deadline of the task will be executed if the specified condition is not met
     .setOverrideDeadline(60000)
	 // Network conditions, the network does not need to pay for the execution
     .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
	 // Whether to charge
     .setRequiresCharging(true)
	 // Whether to execute in idle time
     .setRequiresDeviceIdle(true)
	 // Whether to continue after the device is restarted
     .setPersisted(true) 
	 // Set the retreat/retry policy
     .setBackoffCriteria(3000, the JobInfo. BACKOFF_POLICY_LINEAR). The build (); scheduler.schedule(jobInfo);Copy the code

The official description reference: developer. The android. Google. Cn/about/versi…

Official Demo reference: github.com/googlearchi…

Fifth, security

  • Non-sdk interface restrictions

5.1 Non-SDK interface restrictions

Starting with Android 9 (API level 28), apps can use non-SDK interfaces. These restrictions come into play if your APP references a non-SDK interface or tries to use reflection or JNI to get handles. The official explanation is to improve the user experience and reduce the risk of app crashes.

A. Non-sdk interface detection tools

A test tool is available for download at Veridex

Veridex usage:

appcompat.sh --dex-file=apk.apk
Copy the code

B. Blacklist, greylist, greylist-max-o, and greylist-max-p

In the preceding screenshot, blacklist, greylist, greylist-max-o, and greylist-max-p are described as follows:

  • Blacklist: non-SDK interfaces that are forbidden to be used and Crash when running (therefore must be resolved)
  • Greylist: Non-SDK interfaces that are still available in the current version but may become restricted in the next version
  • Greylist-max-o: non-SDK interface that can be used in targetSDK<= o but is disabled in targetSDK>=P
  • Greylist-max -p: non-SDK interface that can be used in targetSDK<= p, but is disabled in targetSDK>=Q

The SDK is restricted Description: the official developer. The android. Google. Cn/about/versi…

========== THE END ==========