1. 程式人生 > >20 展訊Sprd設定-電池-識別沒有啟動入口的程式

20 展訊Sprd設定-電池-識別沒有啟動入口的程式

1. 目的

關聯喚醒管理中,不對無啟動入口介面程式進行攔截,但是目前的實際情況是進行攔截

2. 獲取無啟動入口的應用程式

原始碼中改函式可能獲取的資料為空,因為其中的getInstalledAppList獲取的安裝列表一直為空

函式的主要原理是mContext.getPackageManager().getLaunchIntentForPackage(key) == null,null則表示是該包沒有入口介面

    // the install third-party service that is app with out launcher entry
    private ArrayList<String> mInstalledServiceList = new ArrayList<>();
    private SparseArray<ArrayMap<String, PackageInfo>> mInstalledAppListForUsers = new SparseArray<>();
    
    private void loadInstalledServiceList() {
        try {
            // 多使用者
            final List<UserInfo> users = mUserManager.getUsers();
            // 獲取每個使用者的應用安裝資訊
            for (int ui = users.size() - 1; ui >= 0; ui--) {
                UserInfo user = users.get(ui);
                if (DEBUG) Slog.d(TAG, "- loadInstalledServiceList() for user: " + user.id);
                // ArrayMap<包名, 應用包資訊>
                ArrayMap<String, PackageInfo> mInstalledAppList = getInstalledAppList(user.id);
                if (DEBUG) Slog.d(TAG, "get launcher intent for installed app : size: " + mInstalledAppList.size());

                for (String key : mInstalledAppList.keySet()) {
                    // 滿足下面條件,則進行新增一條無啟動入口app的條目
                    // 1. 如果包名沒有問題,得到的是null,則表示是該包沒有入口Main activity
                    // 2. 現有的列表不包含當前
                    // 3. 當前應用程式為可用
                    if (mContext.getPackageManager().getLaunchIntentForPackage(key) == null
                        && !mInstalledServiceList.contains(key)
                        && getApplicationLauncherEnabledSetting(key, mCurrentUserId) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT ) {
                        // 新增到列表,新增包名
                        mInstalledServiceList.add(key);
                    }
                }
            }
        } catch (Exception e) {

        }

        if (DEBUG) {
            Slog.d(TAG, "mInstalledServiceList: " + mInstalledServiceList.size());
            // 列印無入口程式列表
            for (int i=0;i<mInstalledServiceList.size();i++) {
                Slog.d(TAG, "App:" + mInstalledServiceList.get(i));
            }
        }

    }
    

2.1 判斷當前應用程式是否可用

    private int getApplicationLauncherEnabledSetting(String packageName, int userId) {

        if (USE_COMPONENT) {
            ComponentName launcherComp = null;
            int launcherState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;

            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.setPackage(packageName);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);

            ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(intent, PackageManager.MATCH_DISABLED_COMPONENTS, mCurrentUserId);

            if (DEBUG) Slog.d(TAG, "getApplicationLauncherEnabledSetting: "
                + " appPackageName:" + packageName
                + " launcher info:" + info);
            if (info != null && info.activityInfo != null) {
                launcherComp = new ComponentName(packageName, info.activityInfo.name);
                try {
                    launcherState = AppGlobals.getPackageManager().getComponentEnabledSetting(launcherComp, userId);
                } catch (Exception e) {
                    Slog.d(TAG, "getApplicationLauncherEnabledSetting Exception:" + e);
                }
            }
            return launcherState;
        } else {
            int enabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;

            try {
                enabled = AppGlobals.getPackageManager().getApplicationEnabledSetting(packageName, userId);
            } catch (Exception e) {
                Slog.d(TAG, "getApplicationLauncherEnabledSetting Exception:" + e);
            }
            return enabled;
        }
    }

2.2 獲取多使用者下對應的應用安裝列表

    private SparseArray<ArrayMap<String, PackageInfo>> mInstalledAppListForUsers = new SparseArray<>();


    // 通過多使用者id獲取,應用安裝列表
    private ArrayMap<String, PackageInfo> getInstalledAppList(int userId) {
        ArrayMap<String, PackageInfo> mInstalledAppList = mInstalledAppListForUsers.get(userId);
        // 如果該使用者獲取到的應用列表為空
        if (mInstalledAppList == null) {
            // 正常邏輯是獲取下該應用id對應的應用安裝列表
            // 原始碼居然是這樣,簡直是奇怪,不明白作者用意
            // 或者寫成 List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackagesAsUser(0, user.id);
            mInstalledAppList = new ArrayMap<>();
            // 儲存鍵值對<多使用者id, 應用安裝列表>
            mInstalledAppListForUsers.put(userId, mInstalledAppList);
        }
        return mInstalledAppList;
    }

3. 另一種無介面應用程式的函式方法判斷


    public static boolean hasLauncherEntry(Context mContext, String pkgName) {
        Intent launchIntent = new Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER);
        List<ResolveInfo> intents = mContext.getPackageManager().queryIntentActivities(launchIntent, PackageManager.GET_DISABLED_COMPONENTS);

        for (int j = 0; j < intents.size(); j++) {
            String intentPackageName = intents.get(j).activityInfo.packageName;
            if (pkgName.equals(intentPackageName)) {
                return true;
            }
        }
        return false;
    }