android獲取應用四大組件列表以及詳細信息

我們可以通過PackageManager獲取PackageInfo,既而獲得應用包相關的各種信息,除了之前說過的可以獲取包名、版本號、圖標、入口Activity、Application、文件md5/sha1/sha256等等,我們還可以獲取應用的四大組件列表,以及組件具體詳情。

PackageInfo info = pm.getPackageInfo(mPackageName, PackageManager.GET_ACTIVITIES
        | PackageManager.GET_RECEIVERS
        | PackageManager.GET_SERVICES
        | PackageManager.GET_PROVIDERS
        | PackageManager.GET_INTENT_FILTERS
        | PackageManager.GET_META_DATA
        | PackageManager.GET_DISABLED_COMPONENTS);

獲取PackageInfo要注意flags參數,否則獲取不到相應信息。

info.activities; //activity列表, ActivityInfo[]類型
info.receivers; //broadcast receiver列表 ActivityInfo[]類型
info.services; //service列表, ServiceInfo[]類型
info.activities; //provider列表, ProviderInfo[]類型

其中,對於組件來說,有兩個字段我最關心:

info.exported;
info.enabled;

自此,我們做一個顯示應用的四大組件列表功能所需的一切就都齊了。

截圖來自 android開發工具箱, 點我下載 android開發工具箱


組件詳情就比較麻煩了,因爲四大組件的屬性都不一樣,而且由於android版本不同,字段也有所區別。下面只拿Activity舉例。

有一些字段我們是可以直接從ActivityInfo獲取的,比如

info.enabled;
info.exported;
info.processName;
info.permission;
info.parentActivityName;

有一些字段,我們需要做一下映射,比如launchMode。info.launchMode是int類型

public class ActivityInfo extends ComponentInfo implements Parcelable {
    public static final int LAUNCH_MULTIPLE = 0;
    public static final int LAUNCH_SINGLE_TOP = 1;
    public static final int LAUNCH_SINGLE_TASK = 2;
    public static final int LAUNCH_SINGLE_INSTANCE = 3;
}

除了launchMode之外,colorMode、screenOrientation、uiOptions等等也是需要進行類似的轉換的。

如果不想寫很多的switch-case之類的代碼,也可以使用反射。比如launchMode,我們可以將`ActivityInfo`類中,所有靜態且以LAUNCH_開頭的常量一一遍歷,與info.launchMode值相同的話,我們顯示field.getName()即可。

還有一種情況,比如flags等字段,是多種類型的組合,我們也一樣可以使用反射。以flags爲例:

public static final int FLAG_MULTIPROCESS = 0x0001;
public static final int FLAG_FINISH_ON_TASK_LAUNCH = 0x0002;
public static final int FLAG_CLEAR_TASK_ON_LAUNCH = 0x0004;
...

只是我們不能使用相等來作爲判斷條件了,需要做個位運算:

if ((flags & fieldValue) == fieldValue) {
    //滿足條件,field.getName()
}

除此之外,還有兩個特殊的,一個是theme一個是softInputMode。

先說theme,通過PackageInfo,我們只能拿到themeId,我們知道,想要獲取theme名字,可以通過如下方式:

resources.getResourceName(themeId);
//或者
resources.getResourceEntryName(themeId);

需要注意的是,我們不能使用自己的Resources對象來獲取其他應用的主題信息,我們需要拿到對應應用的Resources

context.getPackageManager().getResourcesForApplication(packageName);

 

再看softInputMode,我們也是沒有辦法直接拿到softInputMode對應的可讀的描述,但是InputMethodClient提供了相應的方法,不過也是hide方法,複製出來即可。

public static String softInputModeToString(final int softInputMode) {
    final StringBuilder sb = new StringBuilder();
    final int state = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
    final int adjust = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
    final boolean isForwardNav =
            (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0;

    switch (state) {
        case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
            sb.append("stateUnspecified");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
            sb.append("stateUnchanged");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
            sb.append("stateHidden");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
            sb.append("stateAlwaysHidden");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
            sb.append("stateVisible");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
            sb.append("stateAlwaysVisible");
            break;
        default:
            sb.append("stateUnknown(");
            sb.append(state);
            sb.append(")");
            break;
    }

    switch (adjust) {
        case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED:
            sb.append("|adjustUnspecified");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE:
            sb.append("|adjustResize");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN:
            sb.append("|adjustPan");
            break;
        case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING:
            sb.append("|adjustNothing");
            break;
        default:
            sb.append("|adjustUnknown(");
            sb.append(adjust);
            sb.append(")");
            break;
    }

    if (isForwardNav) {
        // This is a special bit that is set by the system only during the window navigation.
        sb.append("|isForwardNavigation");
    }

    return sb.toString();
}

這樣,我們就拿到Activity相關的所有信息。另外三個組件也類似,不再一一演示。

截圖來自 android開發工具箱, 點我下載 android開發工具箱

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