在 Android 5.0 以上 Service 調(diào)用出現(xiàn)了一個比較有影響力的特性:Service Intent must be explicit
。也就是說,Service 必須顯式啟動。否則會報錯。
在官方網(wǎng)站和網(wǎng)上都查了一下,解決的辦法有兩種:
-
設(shè)置
packageName
和Action
Intent mIntent = new Intent(); mIntent.setAction("XXX.XXX.XXX"); //定義的 Service 的 Action mIntent.setPackage(getPackageName()); //設(shè)置為應(yīng)用的包名 context.startService(mIntent);
-
將隱式啟動轉(zhuǎn)換為顯式啟動,方法如下:
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,無法對代碼進(jìn)行修改莫瞬,在進(jìn)行一番探索之后儡蔓,發(fā)現(xiàn)修改 AndroidManifest.xml
的 targetSdkVersion
在 21 以下就可以了!雖然問題解決了乏悄,但是原理沒有搞懂浙值,在查了一系列資料以后,大概得出這樣一個結(jié)論(也許不是準(zhǔn)確的檩小,歡迎指正):
targetSdkVersion
的作用只是告訴你這個項目在這個目標(biāo)版本下運(yùn)行是經(jīng)過測試的开呐,沒有問題,不用再開啟兼容性檢查了规求,這樣做的效果是能夠一定程度上提高運(yùn)行效率筐付。這樣在運(yùn)行的時候,就會直接使用該版本的處理方式調(diào)用 Service阻肿,但是由于在該版本下不允許隱式調(diào)用瓦戚,所以程序會崩潰。但是修改了targetSdkVersion
以后丛塌,程序不能保證你在 5.0 以上還是能正常運(yùn)行较解,所以在我的觀點(diǎn)看來,這里應(yīng)該是強(qiáng)制使用了 5.0 以下的 Service 調(diào)用方式赴邻,所以程序能夠正常運(yùn)行印衔。
目前經(jīng)過測試只發(fā)現(xiàn)了這一種解決方法,在后期我會持續(xù)跟進(jìn)這個問題姥敛,以求能夠更深入地了解 Android 在處理這個問題時的內(nèi)部機(jī)制奸焙。
資料鏈接 :