Note: This article covers the major updates and compatibility issues for Android 10 from three perspectives
-
Privacy features
Introduce new protections to protect user privacy that you will need to support in your application
-
Behavior change
System changes that may affect your applications running on Android 10
-
New features and apis
Apis for foldable devices, dark themes, gesture navigation, connectivity, media, NNAPI, biometrics, and more
1. Privacy change
Android 10 introduces a number of changes, such as an improved interface, stricter permissions and restrictions on what data apps can use, to protect privacy and give users control. Here are the major changes:
Privacy change | Affected applications | Mitigation strategy |
---|---|---|
Partition storage | Applications that access and share files in external storage | Use application-specific directories and media collection directories |
Enhanced user control over location permissions | An application that requests access to user location information while in the background | Make sure to gracefully degrade to get location information in the background using the permissions introduced in Android 10 without background location updates |
Restrictions on launching activities from the background | An application that starts an Activity without user interaction | Activity triggered by notification |
The unique identifier of the device changed | Access device serial numbers or IMEI applications | Use an identifier that the user can reset |
# # # #Partition storage | ||
Android Q provides an “isolated storage sandbox” (e.g. /sdcard) for each application on the external storage device. No other application can directly access your application’s sandbox files. Because files are private to your application, you no longer need any permissions to access and save your own files on the external storage device. For applications targeting Android 10 or later, the access permission is limited to external storage, that is, partitioned storage. | ||
This type of application can view the following types of files in the external storage device without requiring any storage-related user permissions: |
- Files in application-specific directories (accessed using getExternalFilesDir(), which is application-specific)
public File getPrivateAlbumStorageDir(Context context, String albumName) { // Get the directory for the app's private pictures directory. File file = new File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName); if (! file.mkdirs()) { Log.e(LOG_TAG, "Directory not created"); } return file; }Copy the code
- Photos, videos, and audio clips created by an application (accessed through a media library, which is a shareable media file) MediaStore includes all media files that belong to the user and are visible to other applications. All applications can provide content to MediaStore without any permission. To access content provided by other applications, you must obtain READ_EXTERNAL_STORAGE. [](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b29524bf83c24bc18351a72b372dd8f3~tplv-k3u1fbpfcp-zoom-1.image) The MediaStore API provides access to the following types of media files: Photos: Video stored in mediastore.images: Audio files stored in mediastore.video: Stored in mediastore.audio, MediaStore also contains a collection called mediastore.files, which provides an interface to access all types of media Files. If you want to access system media files: Android Q introduces a new set of defined media files to be shared. If you want to access media files outside the sandbox, such as photos, music, videos, etc., you need to apply for new media permissions: READ_MEDIA_IMAGES,READ_MEDIA_VIDEO,READ_MEDIA_AUDIO, apply for the same storage permission. Here's an example of saving images: This is how we saved images before Android 10Copy the code
Public static void saveImg (File originalFile, String fileName) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { return null; } / / create the project images public cache directory File File = new File (Environment) external.getexternalstoragedirectory () + File. The separator + Environment.DIRECTORY_PICTURES + File.separator + “yourAppName” + File.separator + “images”;) ; if (! file.exists()) { file.mkdirs(); } // Create a cache path for the corresponding image File newFile = newFile (File + file.separator + fileName); FileOutputStream outStream = new FileOutputStream(newFile,true) // Pseudocode // Write originalFile to the output stream to complete the image save}
On Android 10 or later we can no longer use the File API, otherwise we will report an access exception.Copy the code
Private static void saveImg (File originalFile, String imageName, String imageType) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { return null; } if (TextUtils.isEmpty(relativePath)) { return null; } Uri insertUri = null; ContentResolver resolver = context.getContentResolver(); // Set file parameters to ContentValues ContentValues = new ContentValues(); / / set the file name values. The put (MediaStore. Images. Media. DISPLAY_NAME, imageName); / / set the file and replace the values with the file name here. The put (MediaStore. Images. Media. The DESCRIPTION, imageName); / / set the file type of image / * values in the put (MediaStore. Images. Media. MIME_TYPE, “image/” + imageType); / / note: MediaStore. Images. Media. RELATIVE_PATH need targetSdkVersion = 29, / / it is only the method can be performed on the mobile phone Android10 values. The put (MediaStore. Images. Media. RELATIVE_PATH, Environment. DIRECTORY_DCIM); / / insertUri said file uri path insertUri = resolver. Insert (MediaStore. Images. Media. EXTERNAL_CONTENT_URI, values). / / get the output stream ContentResolver resolver = context. GetContentResolver (); OutputStream OS = resolver. OpenOutputStream (insertUri) / / / / pseudo code will complete the picture save originalFile files written to the output stream}
** Until your application is fully compatible with partitioned storage, you can use the following to temporarily disable partitioned storage: ** - Target Android 9 (API level 28) or lower. - if you with Android 10 (29) API level or higher as the target platform, in the application list, please file requestLegacyExternalStorage value is set to true: < manifest... > <! -- This attribute is "false" by default on apps targeting Android 10 or higher. --> <application android:requestLegacyExternalStorage="true" ... >... </application> </manifest> #### <span id="jump2"> Permission required to access device location information when running in the background To better control the application's permission to access location information, Android 10 introduces ACCESS_BACKGROUND_LOCATION, which is different from ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION, The ACCESS_BACKGROUND_LOCATION permission affects the access to location information only when an application is running in the background. An application will be treated as accessing location information in the background unless one of the following conditions is met: - The Activity belonging to the application is visible - The application runs on a foreground device that declares the foreground service type as Location. To declare the foreground service type of a service in your application, set the application's targetSdkVersion or compileSdkVersion If your app is running on Android 10 or higher, but your target version is lower than Android 10, if your app has ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions, The system automatically adds ACCESS_BACKGROUND_LOCATION to an application during installation. If an application requests ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION, The ACCESS_BACKGROUND_LOCATION permission is automatically added to the request. #### <span id="jump3"> Restrictions on launching activities from the background Starting with Android 10, the system adds restrictions on launching activities from the background. This behavior change helps minimize disruption to users and gives them more control over what is displayed on their screens. As long as your application starts the Activity as a direct result of user interaction, the application will most likely not be affected by these restrictions. In certain cases, if your application needs to attract users' attention immediately, you can use the following solutions: - Creating a high-priority notification When creating a notification, be sure to add a descriptive title and message. You can also choose to use full-screen IntEnts (the USE_FULL_SCREEN_INTENT permission must be requested in the application manifest file. This is normal permission) - Display notifications to the user associated with the foreground service, startForeground(notificationId, notification); #### <span id="jump4"> Device unique identifier changes from Android 10, Applications must have the READ_PRIVILEGED_PHONE_STATE privilege to access the device's non-reset identifier (including the IMEI and serial number) ** Note: Third-party apps installed from the Google Play Store cannot claim privilege ** The methods affected include: Build getSerial() TelephonyManager getImei() getDeviceId() getMeid() getSimSerialNumber() getSubscriberId() If your app does not have this permission and you still try to query for information about the non-resettable identifier, the platform response will vary depending on the target SDK version: a SecurityException will occur if the app is targeting Android 10 or higher. If the application is targeting Android 9 (API level 28) or lower, the method returns NULL or placeholder data (if the application has READ_PHONE_STATE permission). Otherwise, a SecurityException occurs. <span id="jumpBehavior"> behavior change #### restriction non-SDK interface Restriction non-SDK interface restriction is some SDK private methods, such as private methods, that you get and call through Java reflection etc. These calls will be restricted on target>=P or target>=Q devices, and an error will be reported when you use these methods. If you want to check whether your app uses a non-SDK interface, you can use the following methods: - You can test whether your app uses a non-SDK interface by building and running a debuggable application on a device or emulator running Android 9 (API level 28) or higher. Make sure that the device or emulator you use matches the application's target API level. When you run tests on your application, the system prints a log message if the application accesses some non-SDK interface. You can examine the application's log messages for the following details: - Declared class, name, and type (in the format used by the Android runtime). - Access mode: link, reflection, or JNI - Which list the non-SDK interface accessed belongs to. You can use ADB Logcat to view these log messages, which are displayed under the PID of the running application. For example, the log may contain the following entry: Accessing hidden field Landroid/ OS /Message; ->flags:I (light greylist, JNI) - Testing with veridex tools You can run static analysis tools on APK [veridex] (https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat). Open the command line to switch to the Veridex directory and run the command: / appCompat. sh --dex-file=your-app.apk Veridex will scan the entire APK code base (including all third-party libraries), and the scanning result is divided into two parts. One part is the location of the non-SDK interface that is called. The other part is the number statistics of non-SDK interfaces. - Reflection solution written by the developer: at this point we need to talk about using the non-SDK interface to migrate to the SDK interface - third party SDK uses the non-SDK interface solution: If the application is targeting Android 10 or higher and uses notifications involving full-screen intEnts, You must request the USE_FULL_SCREEN_INTENT permission in the application manifest file. If an app targeting Android 10 or higher tries to create a full-screen intent notification without requesting the required permissions, the system will automatically grant the permission to the application that requests it. <span id="jumpNew"> #### Dark theme the dark theme background of the application will be associated with the system-controlled night mode flag. There are two ways to implement dark theme: <style name="AppTheme" parent="Theme.AppCompat.DayNight"> You can also use MaterialComponent Dark thematic background: < style name = "AppTheme" parent "=" Theme. MaterialComponents. DayNight "> if you want to switch topics background, call AppCompatDelegate. SetDefaultNightMode (), Force Dark allows developers to quickly implement Dark theme backgrounds. Without explicitly setting the DayNight theme background, if you want to enable Force Dark, set it in the theme background: Android :forceDarkAllowed="true" If you want to disable Force Dark on separate views, Add 'Android :forceDarkAllowed' or code call 'setForceDarkAllowed()' ** Note that if you are using a dark theme or a Daynight-themed background, The system will not apply Force Dark ** #### foregroundServiceType Android 10 introduces the foregroundServiceType XML list attribute, which you can include in the definition of multiple specific services. Although rarely applicable, you can assign more than one foreground service type to a particular service. The following table shows the different foreground service types and the appropriate ones to declare specific types of services in: | | at the front desk service type should be a statement USES service situation of the appropriate type | -- -- -- -- -- - | -- -- -- -- -- - | -- -- -- -- -- - | | connectedDevice | wearable monitoring equipment fitness tracker | | dataSync | | download file from the network | the location | continuation of the operation of the user initiated | | mediaPlayback | audiobooks and podcasts or music | | mediaProjection briefly record screen | | | phoneCall | processing | ongoing callsCopy the code