android: targetSdkVersion 引起的問題

在 Android 5.0 以上 Service 調用出現了一個比較有影響力的特性:Service Intent must be explicit。也就是說,Service 必須顯式啟動。否則會報錯。

在官方網站和網上都查了一下,解決的辦法有兩種:

  • 設置 packageNameAction

      Intent mIntent = new Intent();
      mIntent.setAction("XXX.XXX.XXX");   //定義的 Service 的 Action
      mIntent.setPackage(getPackageName());   //設置為應用的包名
      context.startService(mIntent);
    
  • 將隱式啟動轉換為顯式啟動,方法如下:

      public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
        // Retrieve all services that can match the given intent
        PackageManager pm = context.getPackageManager();
        List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
        // Make sure only one match was found
        if (resolveInfo == null || resolveInfo.size() != 1) {
          return null;
        }
        // Get component info and create ComponentName
        ResolveInfo serviceInfo = resolveInfo.get(0);
        String packageName = serviceInfo.serviceInfo.packageName;
        String className = serviceInfo.serviceInfo.name;
        ComponentName component = new ComponentName(packageName, className);
        // Create a new intent. Use the old one for extras and such reuse
        Intent explicitIntent = new Intent(implicitIntent);
        // Set the component to be explicit
        explicitIntent.setComponent(component);
        return explicitIntent;
      }
    

這兩種方法都是通過改變代碼的方式解決的,不過由于我引用的是一個外部的framework,無法對代碼進行修改,在進行一番探索之后,發現修改 AndroidManifest.xmltargetSdkVersion 在 21 以下就可以了!雖然問題解決了,但是原理沒有搞懂,在查了一系列資料以后,大概得出這樣一個結論(也許不是準確的,歡迎指正):

targetSdkVersion 的作用只是告訴你這個項目在這個目標版本下運行是經過測試的,沒有問題,不用再開啟兼容性檢查了,這樣做的效果是能夠一定程度上提高運行效率。這樣在運行的時候,就會直接使用該版本的處理方式調用 Service,但是由于在該版本下不允許隱式調用,所以程序會崩潰。但是修改了 targetSdkVersion 以后,程序不能保證你在 5.0 以上還是能正常運行,所以在我的觀點看來,這里應該是強制使用了 5.0 以下的 Service 調用方式,所以程序能夠正常運行。

目前經過測試只發現了這一種解決方法,在后期我會持續跟進這個問題,以求能夠更深入地了解 Android 在處理這個問題時的內部機制。

資料鏈接 :

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容