Android 7.1 Settings對應的TileUtils.java

TileUtils.javajava

/* 在Android7.1中,Settings中全部category下的條目都是直接經過讀取AndroidManifest.xml對應條目構成的數據,獲取的方法就是TileUtils.getCategories() */
public class TileUtils {
    private static final boolean DEBUG = false;
    private static final boolean DEBUG_TIMING = false;

    private static final String LOG_TAG = "TileUtils";
    
    private static final String SETTINGS_ACTION =
            "com.android.settings.action.SETTINGS";

    private static final String OPERATOR_SETTINGS =
            "com.android.settings.OPERATOR_APPLICATION_SETTING";

    private static final String OPERATOR_DEFAULT_CATEGORY =
            "com.android.settings.category.wireless";

    private static final String MANUFACTURER_SETTINGS =
            "com.android.settings.MANUFACTURER_APPLICATION_SETTING";

    private static final String MANUFACTURER_DEFAULT_CATEGORY =
            "com.android.settings.category.device";

    private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category";

    public static final String META_DATA_PREFERENCE_ICON = "com.android.settings.icon";

    public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";

    public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";

    private static final String SETTING_PKG = "com.android.settings";

    /* 獲取Categories */
    public static List<DashboardCategory> getCategories(Context context, HashMap<Pair<String, String>, Tile> cache) {
        final long startTime = System.currentTimeMillis();
        boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) != 0;
        ArrayList<Tile> tiles = new ArrayList<>();
        UserManager userManager = UserManager.get(context);
		
        //Part One
        for (UserHandle user : userManager.getUserProfiles()) {
            /* private static final String EXTRA_SETTINGS_ACTION = "com.android.settings.action.EXTRA_SETTINGS"; private static final String SETTINGS_ACTION = "com.android.settings.action.SETTINGS"; private static final String OPERATOR_SETTINGS = "com.android.settings.OPERATOR_APPLICATION_SETTING"; private static final String OPERATOR_DEFAULT_CATEGORY = "com.android.settings.category.wireless"; private static final String MANUFACTURER_SETTINGS = "com.android.settings.MANUFACTURER_APPLICATION_SETTING"; private static final String MANUFACTURER_DEFAULT_CATEGORY = "com.android.settings.category.device"; */
            if (user.getIdentifier() == ActivityManager.getCurrentUser()) {
                //只有這一個起到做用,下面三個getTilesForAction沒有用,轉到getTilesForAction看看
                getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
                getTilesForAction(context, user, OPERATOR_SETTINGS, cache, OPERATOR_DEFAULT_CATEGORY, tiles, false);
                getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache, MANUFACTURER_DEFAULT_CATEGORY, tiles, false);
            }
            if (setup) {
                getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
            }
        }
		
        //Part Two
        HashMap<String, DashboardCategory> categoryMap = new HashMap<>();
        for (Tile tile : tiles) {
            DashboardCategory category = categoryMap.get(tile.category);
            if (category == null) {
                category = createCategory(context, tile.category);
                if (category == null) {
                    Log.w(LOG_TAG, "Couldn't find category " + tile.category);
                    continue;
                }
                categoryMap.put(category.key, category);
            }
            category.addTile(tile);
        }
        ArrayList<DashboardCategory> categories = new ArrayList<>(categoryMap.values());
        for (DashboardCategory category : categories) {
            Collections.sort(category.tiles, TILE_COMPARATOR);
        }
        Collections.sort(categories, CATEGORY_COMPARATOR);
        if (DEBUG_TIMING) Log.d(LOG_TAG, "getCategories took "
                + (System.currentTimeMillis() - startTime) + " ms");
        return categories;
    }

    private static DashboardCategory createCategory(Context context, String categoryKey) {
        DashboardCategory category = new DashboardCategory();
        category.key = categoryKey;
        PackageManager pm = context.getPackageManager();
        List<ResolveInfo> results = pm.queryIntentActivities(new Intent(categoryKey), 0);
        if (results.size() == 0) {
            return null;
        }
        for (ResolveInfo resolved : results) {
            if (!resolved.system) {
                // Do not allow any app to add to settings, only system ones.
                continue;
            }
            category.title = resolved.activityInfo.loadLabel(pm);
            category.priority = SETTING_PKG.equals(
                    resolved.activityInfo.applicationInfo.packageName) ? resolved.priority : 0;
            if (DEBUG) Log.d(LOG_TAG, "Adding category " + category.title);
        }

        return category;
    }

    /* 主要是調用了getTilesForIntent,到getTilesForIntent裏 */
    private static void getTilesForAction(Context context, UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache, String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings) {
        Intent intent = new Intent(action);
        if (requireSettings) {
            intent.setPackage(SETTING_PKG);
        }
        getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles, requireSettings, true);
    }

    /* 這裏纔是真正解析AndroidManifets.xml的地方 */
    public static void getTilesForIntent( Context context, UserHandle user, Intent intent, Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles, boolean usePriority, boolean checkCategory) {
        PackageManager pm = context.getPackageManager();
        /* 在這裏解析AndroidManifest.xml並獲取結果results */
        List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
                PackageManager.GET_META_DATA, user.getIdentifier());
        /* 遍歷results的每一條數據並解析保存到對應的Tile數據中 */
        for (ResolveInfo resolved : results) {
            if (!resolved.system) {
                // Do not allow any app to add to settings, only system ones.
                continue;
            }
			
            ActivityInfo activityInfo = resolved.activityInfo;
            Bundle metaData = activityInfo.metaData;
            String categoryKey = defaultCategory;
            /* metaData裏必須包含key com.android.settings.category, 而它的value只能是 com.android.settings.category.wireless com.android.settings.category.device com.android.settings.category.personal com.android.settings.category.system */
            if (checkCategory && ((metaData == null) || !metaData.containsKey(EXTRA_CATEGORY_KEY))
                    && categoryKey == null) {
                Log.e(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent "
                        + intent + " missing metadata "
                        + (metaData == null ? "" : EXTRA_CATEGORY_KEY));
                continue;
            } else {
                categoryKey = metaData.getString(EXTRA_CATEGORY_KEY);
            }
			
            Pair<String, String> key = new Pair<String, String>(activityInfo.packageName,
                    activityInfo.name);
            Tile tile = addedCache.get(key);
            if (tile == null) {
                tile = new Tile();
                tile.intent = new Intent().setClassName(
                        activityInfo.packageName, activityInfo.name);
                tile.category = categoryKey;
                tile.priority = usePriority ? resolved.priority : 0;
                tile.metaData = activityInfo.metaData;
                updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
                        pm);
                Log.e(LOG_TAG, "Adding tile " + tile.title);

                addedCache.put(key, tile);
            }
            if (!tile.userHandle.contains(user)) {
                tile.userHandle.add(user);
            }
            if (!outTiles.contains(tile)) {
                outTiles.add(tile);
            }
        }
    }

    private static DashboardCategory getCategory(List<DashboardCategory> target, String categoryKey) {
        for (DashboardCategory category : target) {
            if (categoryKey.equals(category.key)) {
                return category;
            }
        }
        return null;
    }

    private static boolean updateTileData(Context context, Tile tile, ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) {
        if (applicationInfo.isSystemApp()) {
            int icon = 0;
            CharSequence title = null;
            String summary = null;

            try {
                Resources res = pm.getResourcesForApplication(
                        applicationInfo.packageName);
                Bundle metaData = activityInfo.metaData;

                if (res != null && metaData != null) {
                    if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
                        icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
                    }
                    if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
                        if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
                            title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
                        } else {
                            title = metaData.getString(META_DATA_PREFERENCE_TITLE);
                        }
                    }
                    if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
                        if (metaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) {
                            summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
                        } else {
                            summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
                        }
                    }
                }
            } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
                if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
            }


            if (TextUtils.isEmpty(title)) {
                title = activityInfo.loadLabel(pm).toString();
            }
            if (icon == 0) {
                icon = activityInfo.icon;
            }

            // Set icon, title and summary for the preference
            tile.icon = Icon.createWithResource(activityInfo.packageName, icon);
            tile.title = title;
            tile.summary = summary;
            // Replace the intent with this specific activity
            tile.intent = new Intent().setClassName(activityInfo.packageName,
                    activityInfo.name);

            return true;
        }

        return false;
    }

    public static final Comparator<Tile> TILE_COMPARATOR =
            new Comparator<Tile>() {
        @Override
        public int compare(Tile lhs, Tile rhs) {
            return rhs.priority - lhs.priority;
        }
    };

    private static final Comparator<DashboardCategory> CATEGORY_COMPARATOR =
            new Comparator<DashboardCategory>() {
        @Override
        public int compare(DashboardCategory lhs, DashboardCategory rhs) {
            return rhs.priority - lhs.priority;
        }
    };
}
複製代碼
相關文章
相關標籤/搜索