All stages of this adaptation for Android

Keywords: Java Android

Android 4.4

  • Publish ART virtual machine and provide options to enable it.
  • The underlying implementation of HttpURLConnection is changed to OkHttp.

Android 5.0

  • ART becomes the default virtual machine and completely replaces Dalvik virtual machine.
  • The Context.bindService() method requires an explicit intent. If an implicit intent is provided, an exception will be thrown.

Android 6.0

  • Increase runtime permission restrictions

If your application uses dangerous permissions, such as checking and requesting permissions at runtime. The checkSelfPermission() method is used to check permissions, and the requestPermissions() method is used to request permissions.

  • Unsupported Apache HTTP

Android version 6.0 removes support for Apache HTTP related class libraries. To continue using the Apache HTTP API, you must first declare the following compile time dependencies in the build.gradle file:

android {useLibrary 'org.apache.http.legacy'}

Apache HttpClient is an open source project provided by Apache open source organization. It is a simple HTTP client (not a browser) that can send HTTP requests and receive HTTP responses.

Android 7.0

  • Android 7.0 introduces a new application signature scheme APK Signature Scheme v2
  • BadTokenException caused by Toast
  • On the Android 7.0 system, the Android framework enforces the StrictMode API policy, which prohibits the disclosure of file:// URI to your application. If an Intent containing the file file:// URI type leaves your application, the application fails and a FileUriExposedException exception occurs, such as calling the system camera to take photos, record videos, or cut photos.

In fact, it restricts the sharing of files between applications. If you need to share files between applications, you need to grant temporary access to the URI to be accessed. What we need to do is to register the FileProvider:

1) Declare FileProvider.

    android:authorities="app Package name.fileProvider"
        android:resource="@xml/file_paths" />
<!--androidx The version class path is: androidx.core.content.FileProvider-->

2) Write an xml file to determine the accessible directory

<paths xmlns:android="">
    //Represents the root directory of the device, new File("/");
    <root-path name="root" path="." /> 
    <files-path name="files" path="." /> 
    <cache-path name="cache" path="." /> 
    <external-path name="external" path="." />
    <external-files-path name="name" path="path" />
     <external-cache-path name="name" path="path" />

3) Using FileProvider

    Uri uri = FileProvider.getUriForFile(CameraActivity.this, "app Package name.fileProvider", photoFile);
} else {
    Uri uri = Uri.fromFile(photoFile);

Android 8.0

  • Error modifying runtime permissions

Before Android 8.0, if an application requests permission at runtime and is granted this permission, the system will mistakenly grant other permissions that belong to the same permission group and registered in the list to the application. For applications for Android 8.0, the system will only grant the permission explicitly requested by the application. However, once a user grants a permission to an application, all subsequent requests for permission in the permission group will be automatically approved.

In other words, you applied for read before_ EXTERNAL_ With the storage permission, the application will grant you write of the same permission group at the same time_ EXTERNAL_ Storage permissions. If Android 8.0 or above, it will only grant you the read you requested_ EXTERNAL_ Storage permissions. Write if required_ EXTERNAL_ Storage permission should be applied separately, but the system will grant it immediately without prompting.

  • Modification notice

Android 8.0 has modified a lot for notification, such as notification channel, notification flag, notification timeout and background color. The more important one is the notification channel, which allows you to create user-defined channels for each notification type to be displayed.

The advantage of this is that for an application, permissions can be divided into many categories, and users can control whether to display notifications of which categories. What developers need to do is to set this channel id, otherwise the notification may become invalid.

     private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            NotificationManager notificationManager = (NotificationManager)

            //Grouping (optional)
            //groupId must be unique
            String groupId = "group_001";
            NotificationChannelGroup group = new NotificationChannelGroup(groupId, "advertisement");

            //Create group

            //channelId must be unique
            String channelId = "channel_001";

            NotificationChannel adChannel = new NotificationChannel(channelId,
                    "Promotion information", NotificationManager.IMPORTANCE_DEFAULT);
            //Supplement the meaning of channel (optional)
            adChannel.setDescription("Promotion information");
            //Add channel to group (create group before adding)
            //Create channel

            //Mark your channel id when creating notifications
            Notification notification = new Notification.Builder(MainActivity.this, channelId)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                    .setContentTitle("A new notice")
                    .setContentText("This is a test message")
            notificationManager.notify(1, notification);

  • Suspension window
    Android 8.0 and above must use a new window type (TYPE_APPLICATION_OVERLAY) to display the reminder hover window:

    mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
}else {
    mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
  • Apps from unknown sources are not allowed to be installed
    Android 8.0 removes the "allow unknown sources" option, so if our App has the function of installing App (checking for updates, etc.), it will not be installed normally.

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

    private void installAPK(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            boolean hasInstallPermission = getPackageManager().canRequestPackageInstalls();
            if (hasInstallPermission) {
                //Install application
            } else {
                //Jump to the "install unknown application" permission interface and guide the user to open the permission
                Uri selfPackageUri = Uri.parse("package:" + this.getPackageName());
                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, selfPackageUri);
                startActivityForResult(intent, 100);
        }else {
            //Install application


    //Receive the opening result of "install unknown app" permission
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 100) {
  • Only fullscreen opaque activities can request orientation
    Only full screen opaque activities can set the direction. This should be a bug, which appeared in Android 8.0 and was fixed in 8.1.

Our approach is to either remove the code that sets the direction or abandon the transparency effect.

Android 9.0

  • In 9.0, network transport layer security protocol (TLS) is enabled by default, and plaintext support is disabled by default. That is, http requests are not allowed and https is required. The solution is to add a network security configuration:

<application android:networkSecurityConfig="@xml/network_security_config">

 <base-config cleartextTrafficPermitted="true" />

<!--Or in AndroidManifest.xml Configuration in:
  • Remove Apache HTTP client

The support for Apache HTTP client is cancelled in 6.0, and the library is directly removed in Android 9.0. If you want to use it, you need to add a configuration:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>
  • Foreground service call

Android 9.0 requires that a foreground service be created and foreround is required_ Service permission, otherwise the system will raise SecurityException.

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
} else {
  • An Activity cannot be started in a non Activity environment

In 9.0, you cannot directly start an Activity in a non Activity environment (such as Service and Application), otherwise it will crash and report an error. The solution is to add FLAG_ACTIVITY_NEW_TASK

Intent intent = new Intent(this, TestActivity.class);

Android 10

  • Partitioned storage

Partition storage is enabled by default in Android 10, that is, sandbox mode. The application can only see the application specific directories (accessed through Context.getExternalFilesDir()) and specific types of media.

If you need to turn off this function, you can configure:


Methods of accessing files under partitioned storage:

1) Application specific directory

//Partitioned storage space
val file = File(context.filesDir, filename)

//Application specific external storage space
val appSpecificExternalDir = File(context.getExternalFilesDir(), filename)

2) Access public media catalog 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")

3) Saf (storage access framework -- Storage Access Framework)

    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
    intent.type = "image/*"
    startActivityForResult(intent, 100)

    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 =
            println("image uri is $uri")
  • Upgrade permissions again

Starting from Android 10, ordinary applications are no longer allowed to request permission android.permission.READ_PHONE_STATE. Moreover, no matter whether your App has been adapted to Android Q (i.e. whether targetSdkVersion is greater than or equal to 29), you can no longer obtain device information such as device IMEI.

The maximum sdk version can be configured if the Android 10 obtains information such as device IMEI from the following devices:

<uses-permission android:name="android.permission.READ_PHONE_STATE"

Android 11

  • Partitioned storage enforcement

Android 11 enforces partitioned storage, that is, sandbox mode. It's really not turned off this time. It's been a while since Android 11 came out. Let's hurry up with the adaptation.

  • Modify phone permissions

Two API s have been changed: getLine1Number() and getMsisdn(), and read needs to be added_ PHONE_ Numbers permissions

  • Custom toast is not allowed to be displayed from the background
  • The v2 signature must be added
  • Add 5g related API
  • Background location access is restricted again

Author: WuChao 226
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Posted by Ceril on Fri, 26 Nov 2021 07:04:04 -0800