Android App兼容8.0和9.0

Android在8.0限制了後臺服務這些,啓動後臺服務需要設置通知欄,使服務變成前臺服務。但是在9.0上,就會出現Permission Denial: startForeground requires android.permission.FOREGROUND_SERVICE。
解決辦法是在AndroidManifest中添加

    <!--android 9.0上使用前臺服務,需要添加權限-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
1
2
之後啓動service的時候也需要做處理,否則會拋異常java.lang.IllegalStateException: Not allowed to start service Intent。stackoverflow的回答

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent);
        } else {
            context.startService(intent);
        }
1
2
3
4
5
之後service的onCreate還需要設置通知欄

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     
                NotificationChannel channel = new NotificationChannel("xxx", "xxx", NotificationManager.IMPORTANCE_LOW);

                NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                if (manager == null)
                    return;
                manager.createNotificationChannel(channel);

                Notification notification = new NotificationCompat.Builder(this, "xxx")
                        .setAutoCancel(true)
                        .setCategory(Notification.CATEGORY_SERVICE)
                        .setOngoing(true)
                        .setPriority(NotificationManager.IMPORTANCE_LOW)
                        .build();

                startForeground(101, notification);
         
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
服務這塊就沒了。stackoverflow的回答

項目中如果使用Volley的話,在android 9.0會出現異常,提示ProtocolVersion的異常,之後,就在AndroidManifest的application節點下添加

  <!--解決android9.0上使用ProtocolVersion拋異常的bug-->
        <uses-library android:name="org.apache.http.legacy" android:required="false" />
1
2
之後編譯運行,請求網絡正常了,不報錯了。
stackoverflow的相似問題

Android 9.0強制使用https,會阻塞http請求,如果app使用的第三方sdk有http,將全部被阻塞。
出現UnknownServiceException: CLEARTEXT communication to localhost not permitted by network security policy或者IOException java.io.IOException: Cleartext HTTP traffic to * not permitted
就說明,你需要去兼容了。最簡單的兼容方式是在AndroidManifest文件的application設置android:usesCleartextTraffic="true"。這是第一種方式。
可以參考stackoverflow的回答
以及Android P - CLEARTEXT communication not permitted by network security policy
第二種方式:網絡安全性配置
在AndroidManifest文件的application節點配置android:networkSecurityConfig="@xml/network_security_config"
xml中的配置具體的配置。
可以參考我的配置

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!--默認配置,明文通信,使用系統證書-->
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <!--trust system while release only-->
            <certificates src="system" />
        </trust-anchors>
    </base-config>
       <!--自己服務器,使用https,將所有域名添加到此-->
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">xxx.xxx.com</domain>
        <!--<trust-anchors>-->
        <!--<certificates src="@raw/my_proxy_ssl_proxying_certificate" />-->
        <!--</trust-anchors>-->
    </domain-config>
    <!--debug模式,可以使用用戶自己安裝的正式,比如charles抓包安裝的證書,這個配置只在 android:debuggable 爲 "true" 時將應用的重寫,IDE 和構建工具生成的非發佈版本通常屬於此情況-->
    <debug-overrides>
        <!-- Trust user added CAs while debuggable only -->
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
第二種方式纔是最好的方式,具體參考官方文檔security-config

還有就是如果在請求https的時候拋出javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 請檢查手機是不是設置了代理。android7.0之後不特殊處理,是無法抓取https。
把android官方文檔放這裏,可以自己查閱通過https和SSL確保安全

補充記錄一個android 8.0的無法安裝apk,即 未知來源 的問題

8.0如果應用內有升級,而且應用沒有上google play ,安裝apk還需要申請 未知來源 的權限

 <!-- 8.0安裝apk權限,需要允許安裝未知應用 -->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
1
2
安裝包下載完成之後,屏幕閃了一下並沒有跳轉到安裝界面,使用8.0以下的手機並沒有這個問題。
原因:Android 8.0 Oreo 中,Google 移除掉了容易被濫用的“允許位置來源”應用的開關,在安裝 Play Store 之外的第三方來源的 Android 應用的時候,竟然沒有了“允許未知來源”的檢查框,如果你還是想要安裝某個被自己所信任的開發者的 app,則需要在每一次都手動授予“安裝未知應用”的許可。
適配Android 8.0:
1.清單文件添加安裝未知來源應用的權限 android.permission.REQUEST_INSTALL_PACKAGES

2.下載好安裝包後,安裝程序之前驗證是否有安裝未知來源應用的權限

public class MyActivity extends Activity {

private static final int REQUEST_INSTALL = 124;
private final UpdateBuilder builder = UpdateBuilder.create();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /**
     * 請在Application中進行UpdateConfig的全局配置
     */
    builder.setInstallStrategy((context, s, update) -> {
        if (Build.VERSION.SDK_INT < 26) {
                //直接安裝
                new DefaultInstallStrategy().install(context, s, update);
            } else if (getPackageManager().canRequestPackageInstalls()) {//26 版本纔有此方法
                //可以安裝未知來源應用
                new DefaultInstallStrategy().install(context, s, update);
            } else {
                //申請權限
                if (ActivityCompat.shouldShowRequestPermissionRationale(MyActivity.this, Manifest.permission.REQUEST_INSTALL_PACKAGES)) {
                    //自定義的Dialog,可以用Android系統自帶Dialog代替
                    new MessageDialog.Builder(UMainActivity.this)
                            .title("提示")
                            .content("爲了正常升級“預逍”APP,請允許“預逍”安裝未知來源應用,本功能只限用於版本升級")
                            .positiveText("確定")
                            .negativeText("取消")
                            .canceledOnTouchOutside(false)
                            .cancelable(false)
                            .onPositive((dialog, which) -> ActivityCompat.requestPermissions(MyActivity.this,
                                    new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},
                                    REQUEST_INSTALL))
                            .onNegative(((dialog, which) -> ActivityCompat.requestPermissions(MyActivity.this,
                                    new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},
                                    REQUEST_INSTALL)))
                            .show();
                } else {
                    ActivityCompat.requestPermissions(MyActivity.this,
                            new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},
                            REQUEST_INSTALL);
                }
            }
    });
     builder.check();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_INSTALL) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            builder.check();
        } else {
            //啓動授權頁面
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, REQUEST_INSTALL);
        }
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_INSTALL) {
        builder.check();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
這個借鑑於github
8.0安裝閃退

慢慢踩坑

致敬前輩,砥礪前行!
--------------------- 
作者:賢澤 
來源:CSDN 
原文:https://blog.csdn.net/wxz1179503422/article/details/83031724 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章