Android 9.0 簡單適配


轉載請聲明,本文來自:


本文僅描述當前項目apk遇到的適配9.0問題,所以不是全面的,請自行參考;

適配一:
純後臺服務,需要在AndroidManifest.xml添加權限

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

適配二:

java.lang.SecurityException: Permission Denial: reading provider-name uri content://provider-CONTENT_URI from pid=5114, uid=10065 requires 權限, or grantUriPermission()
at android.os.Parcel.createException(Parcel.java:1949)
at android.os.Parcel.readException(Parcel.java:1917)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:418)
at android.content.ContentResolver.query(ContentResolver.java:804)
at android.content.ContentResolver.query(ContentResolver.java:753)
at android.content.ContentResolver.query(ContentResolver.java:711)
at com.privateclass.ssl.ContentResolverUtils.quertData(ContentResolverUtils.java:30)
修改部分:
我是在MainActivity.class裏重寫方法的

 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        Log.d(TAG, "requestCode=" + requestCode + "; --->" + Arrays.toString(permissions)
                + "; grantResult=" + Arrays.toString(grantResults));
        switch (requestCode) {
            case 0: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted
                    // request successfully, handle you transactions

                } else {
                    // permission denied
                    // request failed
                }
                return;
            }
            default:
                break;
        }
    }

參考:Android: requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()

適配三:(這個是7.0的權限適配)

Sending non-protected broadcast action from system 1616:packagename/u0a64 pkg packagename
java.lang.Throwable
at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:21275)
at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:21879)
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:22021)
at android.app.IActivityManagerStub.onTransactStub.onTransactbroadcastIntent(IActivityManager.java:10171)atandroid.app.IActivityManager(IActivityManager.java:10171) at android.app.IActivityManagerStub.onTransact(IActivityManager.java:167)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3311)

修改部分:
這是因爲“靜態廣播的exported爲true的時候必須同時加上permission限制

8.0的只要求intent加上package就可, 現在還需要加上權限
參考:protected-broadcast 規範使用(ERROR: Sending non-protected broadcast)

在加權限的時候,還需要對權限進行聲明,不然會報錯

/system_process W/BroadcastQueue: Permission Denial: broadcasting Intent { XXXX (has extras) } from XXXX (pid=1628, uid=10038) requires XXXX due to receiver XXXX

參考:Android發送權限受限的廣播,指定接受方!

<manifest
    <!--  此處聲明權限,可以在任意需要發送該廣播的app中聲明 -->
    <uses-permission android:name="自定義的權限" />
	<application
        <receiver
            android:name=".MsgReceiver"
            android:enabled="true"
            android:exported="true"
            android:permission="自定義的權限">
        </receiver>
    </application>

    <permission
        android:name="自定義的權限"
        android:protectionLevel="normal" />
</manifest>

適配四:(這個是8.0的Service適配)

ActivityManager: ANR in cn.digirun.update.smart
PID: 5212
Reason: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{45a21a7 u0 package/service}
Load: 2.36 / 2.21 / 2.24
CPU usage from 0ms to 9159ms later (2019-04-02 18:31:47.260 to 2019-04-02 18:31:56.419):
27% 922/system_server: 16% user + 11% kernel / faults: 5609 minor

修改部分:
在AndroidManifest中添加權限

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

在Service.class 中添加代碼

 @Override
    public void onCreate() {
        super.onCreate();
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            String Notifi_Channel = BaseApplication.context.getPackageName() + ".MDMConObsService";
            NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), Notifi_Channel);
            notificationVersion(this, Notifi_Channel, "BackGround Service", false);
            Notification notification = builder.build();
            startForeground(1, notification);
        }
        mdmContentObserver = new MDMContentObserver(new Handler());
    }

    public static void notificationVersion(Context context, String channelId, String channelName, boolean voiceVibration) {
//        String channelID = "cn.digirun.update.smart.Notification";
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
            if (!voiceVibration) {
                channel.enableLights(false);
                channel.enableVibration(false);
                channel.setImportance(NotificationManager.IMPORTANCE_LOW);//設置爲low, 通知欄不會有聲音
            }
            NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            manager.createNotificationChannel(channel);
        }
    }

適配五:

System.err: java.net.UnknownServiceException: CLEARTEXT communication to .oss-cn-beijing.aliyuncs.com not permitted by network security policy
2019-04-04 10:47:58.126 429-429/? I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0
2019-04-04 10:47:58.129 429-429/? I/chatty: uid=1000(system) /system/bin/surfaceflinger identical 2 lines
2019-04-04 10:47:58.129 429-429/? I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0
2019-04-04 10:47:58.131 1580-1580 W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:139)
2019-04-04 10:47:58.131 1580-1580/ W/System.err: at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:195)
2019-04-04 10:47:58.131 1580-1580/ W/System.err: at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
2019-04-04 10:47:58.131 1580-1580/ W/System.err: at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
2019-04-04 10:47:58.131 1580-1580/ W/System.err: at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
2019-04-04 10:47:58.131 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
2019-04-04 10:47:58.131 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
2019-04-04 10:47:58.131 1580-1580/W/System.err: at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at com.lzy.okgo.interceptor.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:93)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at okhttp3.RealCall.execute(RealCall.java:69)
2019-04-04 10:47:58.132 1580-1580/ W/System.err: at com.lzy.okgo.request.base.Request.execute(Request.java:383)

這個還是9.0默認取消了http的通訊,要使用https 導致的。

修改部分:
方法一:(臨時過渡)
在AndroidManifest.xml裏添加

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

在res/xml 目錄下新建文件夾 network_security_config.xml

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

方法二:
後期請將後臺和設備接口都替換成https協議

適配六:
找不到Activity

componentName = null
MyClass: Unexpected remote exception
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.qualcomm.update.REBOOT flg=0x10000000 (has extras) }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2014)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1675)
at android.app.ContextImpl.startActivity(ContextImpl.java:917)
at android.app.ContextImpl.startActivity(ContextImpl.java:888)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:379)

下面是我在8.0的時候代碼,在9.0 的時候componentName爲null了

 //兼容8.0  修改成以下
     if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
         ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
         ComponentName componentName = intent.resolveActivity(getPackageManager());
          Log.e(TAG, ": componentName = " + (componentName == null ? "null" : (componentName.getPackageName() + "|" + componentName.getClassName())));
           if (componentName != null) {
               intent.setComponent(componentName);
               }
     }

適配修改:
莫名其妙的好了, 問題就出現了一次,後面就沒有復現了,待後續觀察

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