getApplicationInfo的坑
一般情況下我們通過PackageManager.GET_UNINSTALLED_PACKAGES來檢查應用是否安裝,且不論其本身存在的不正確性,自Android 4.2(API 17)以后,多賬戶的出現,其又新出現一些坑。現在Android 7.0(API 24)使用MATCH_UNINSTALLED_PACKAGES 將其替換。
問題描述
在做微信分享操作之前,應用內先對微信App進行一次判斷是否安裝,使用的方法:
public boolean checkApkExist(Context context, String packageName) {
try {
ApplicationInfo info = context.getPackageManager().getApplicationInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if (info != null)
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
return false;
}
在我的設備上存在兩個賬戶,一個管理員賬戶用于日常使用,另一個普通賬戶用于開發,在我的管理員賬戶中安裝了微信,而普通賬戶里面沒有安裝微信,但是在普通賬戶里運行這段代碼,其會告訴你安裝了微信。
問題分析
從API 24的源碼可以看到,其實GET_UNINSTALLED_PACKAGES標志僅僅用于查詢在手機系統分區存在數據目錄的應用:
/**
* @deprecated replaced with {@link #MATCH_UNINSTALLED_PACKAGES}
*/
@Deprecated
public static final int GET_UNINSTALLED_PACKAGES = 0x00002000;
/**
* Flag parameter to retrieve some information about all applications (even
* uninstalled ones) which have data directories. This state could have
* resulted if applications have been deleted with flag
* {@code DONT_DELETE_DATA} with a possibility of being replaced or
* reinstalled in future.
* <p>
* Note: this flag may cause less information about currently installed
* applications to be returned.
*/
public static final int MATCH_UNINSTALLED_PACKAGES = 0x00002000;
其實這個標簽都不一定能保證應用就一定安裝著,只能說應用是否安裝過,而多賬戶下就更不能保證這個賬戶下就一定安裝過了,因為可以是另一個賬戶下安裝過。
問題解決
- 盡量不要使用GET_UNINSTALLED_PACKAGES或者MATCH_UNINSTALLED_PACKAGES去判斷應用是否已安裝或者安裝過。
- 微信的API自有判斷是否安裝的方法。