Android6.0-9.0 Version Adaptation Guide

As we all know, the Android version is updated rapidly, and each version has some new features added, which has caused many pitfalls, which has caused developers to continue to adapt. Let me talk about the mainstream features from Android6.0 to Android9.0 the adaptation process.

Anrdoid 6.0

1. Dynamic permissions

The biggest change in Android 6.0 is the dynamic permission application. For detailed instructions, please refer to my other blog: Android6.0 permission management for Android development

2. Deprecate HttpClient

After Android 6.0, AndroidSDK no longer uses Apache Http-related APIs. If your project needs to use HttpClient, you need to add the following configuration to the app's build.gradle file:

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

Note: After Android 9.0, the support for Apache HTTP client has been completely removed. Even if you configure the above, it will not work. For details, please refer to the adaptation of Android 9.0 below.

Android 7.0

On the basis of Android 6.0, Android 7.0 has stricter control over permissions, mainly reflected in:

1. Share files between apps

If your application wants to access local files (folders) through Intent, then this error android.os.FileUriExposedException may be reported in Android7.0.

This is because 7.0 prohibits direct access to files between applications. For specific solutions, please see: Android 7.0 reports android.os.FileUriExposedException

2. App new signature scheme V2

Android 7.0 introduces a new application signature scheme, APK Signature Scheme v2, which provides faster application installation times and more protection against unauthorized changes to APK files. By default, Android Studio 2.2+ and Gradle 2.2+ use APK Signature Scheme v2 and legacy signature schemes to sign your app.

When packaging the application, the last two must be checked

1) Only check the v1 signature is the traditional scheme signature, but the V2 security verification method will not be used on 7.0.
2) Only check the V2 signature below 7.0, it will be displayed as not installed, and the V2 security verification method will be used on 7.0.
3) Check V1 and V2 at the same time, all versions are fine.

3. Shared Preferences problem

//Context.MODE_WORLD_READABLE:7.0以后不推荐使用这个,已经过时,这个也属于应用间共享文件的范畴,修改成MODE_PRIVATE
SharedPreferences sp = context.getSharedPreferences("key", Context.MODE_WORLD_READABLE);

MODE_WORLD_READABLE is no longer recommended for APIs after Android 7.0. If you need to share configuration between applications, it is recommended to use ContentProvider or Broadcast.

Android 8.0

1. Add permissions

Two new permissions are added to the PHONE permission group:

android.permission.ANSWER_PHONE_CALLS: Allows your app to programmatically answer incoming calls. To handle incoming calls in your application, you can use the acceptRingingCall() method.

android.permission.READ_PHONE_NUMBERS: Allows your app to read phone numbers stored on the device.

Permission to install apps from unknown sources:

android.permission.REQUEST_INSTALL_PACKAGES: Allows installation of applications from unknown sources

In this way, the system will automatically ask the user to complete the authorization. Of course, you can also use canRequestPackageInstalls() to check whether you have this permission first. If not, use the Action Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES to guide the user to the interface for installing unknown application permissions to authorize.

 private void installAPK(String apkPath){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            boolean hasPermission = getPackageManager().canRequestPackageInstalls();
            if (hasPermission) {
                //安装应用
                install(apkPath);
            } else {
                //跳转至“允许安装未知应用”权限界面,引导用户开启权限
                Uri packageUri = Uri.parse("package:" + this.getPackageName());
                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri);
                startActivityForResult(intent, 101);
            }
        }else {
            //安装应用
            install(apkPath);
        }
    }
    
    private void install(String apkPath){
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        Uri uri = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            uri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", new File(apkPath));
        } else {
            uri = Uri.fromFile(new File(apkPath));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
    }

2. Change of Notification

Notification is the thing that I think changes the most frequently. One API per version is very cheating.

Android 8.0 adds NotificationChannel to distinguish notifications from different channels.

Here is a code example:

   /**
     * 使用一个ID来标识不同渠道,在手机中可以禁止接收来自某个渠道的通知
     */
    public static final String CHANNEL_ID = "test";

    private void showNotify(int progress) {
         NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //先创建一个新渠道:渠道ID,渠道名称,渠道重要性
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_LOW);
            channel.enableVibration(false); //对于持续性的通知,有些手机会不断地震动和发出提示音,建议禁用
            channel.enableLights(false); //禁止灯光闪烁提示
            channel.setSound(null, null);
            manager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder notifyBuilder = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0之后,使用渠道,必须使用已经存在的渠道ID
            notifyBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
        } else {
            notifyBuilder = new NotificationCompat.Builder(this);
        }
        notifyBuilder.setSound(null); //禁用提示音,对于持续性的通知,有些手机会不断地震动和发出提示音,建议禁用
        notifyBuilder.setSmallIcon(getResources().getIdentifier("ic_launcher", "mipmap", getPackageName()));
        notifyBuilder.setPriority(NotificationCompat.PRIORITY_HIGH); //优先级
        notifyBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
        notifyBuilder.setShowWhen(true);
        notifyBuilder.setOnlyAlertOnce(true);//只提示一次
        notifyBuilder.setContentTitle("下载中...");
        notifyBuilder.setAutoCancel(false);
        notifyBuilder.setOngoing(true);
        notifyBuilder.setProgress(100, progress, false);

        Intent intent =new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        notifyBuilder.setContentIntent(pendingIntent);

        Notification notification = notifyBuilder.build();
        notification.priority = Notification.PRIORITY_HIGH;
        manager.notify(100, notification);
    }

3. Static broadcasts cannot be received normally

Android 8.0 introduces new broadcast receiver restrictions, resulting in the need to remove all broadcast receivers registered for implicit broadcast Intents, and use dynamic broadcasts instead of static broadcasts.

4.Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

 Android 8.0 non-full-screen transparent pages do not allow setting orientation (Google will remove this restriction later in the 8.1 system)

solution:

(1) android:windowIsTranslucent is set to false

(2) If you still want to use it, remove the configuration item android:screenOrientation in Activity in the manifest file,

Android 9.0

1.CLEARTEXT communication to life.115.com not permitted by network security policy

Android P restricts network requests for plaintext traffic (ordinary http requests), and non-encrypted traffic requests will be banned by the system.

Solution: Create a new xml directory in the resource file, and create a new file network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

AndroidManifest configuration:

<application
        android:networkSecurityConfig="@xml/network_security_config">
        <uses-library
            android:name="org.apache.http.legacy"
            android:required="false" /><!-- Android P添加对ApacheHttp的支持 -->
</application>

However, it is still recommended that the background interface use https to transfer data, which will be more secure.

For more adaptations after Android9.0, see: AndroidP Adaptation Guide (must-see)

Well, the above are the Android adaptation problems I have encountered, plus the experience of some great gods, it is definitely not complete, and I will add it when I encounter it later.

Guess you like

Origin blog.csdn.net/gs12software/article/details/84936019