Third party apk icons are customized in android Launcher3 to achieve similar theme functions

Recently, I met the need to use the specified icon for the specified app in the Launcher to implement theme like functions. To implement such a function, it is necessary to find out how the Launcher loads the app icon.

First, navigate to the cacheLocked () method of the class com.android.launcher3.IconCache.java

private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
            HashMap<Object, CharSequence> labelCache, UserHandleCompat user, boolean usePackageIcon) {
        CacheKey cacheKey = new CacheKey(componentName, user);
        CacheEntry entry = mCache.get(cacheKey);
        if (entry == null) {
            entry = new CacheEntry();
        .......
                entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
                //Used to initialize the app Icon
                entry.icon = Utilities.createIconBitmap(
                        info.getBadgedIcon(mIconDpi), mContext);
            } else {
        ......
        return entry;
    }

First, obtain the Drawable application of the original launcher icon through info.getBadgedIcon(mIconDpi), which is the graph resource id, and then use Utilities.createIconBitmap (Drawable icon, Context context context) method to process the icon simply (to modify the background of all launcher icons, you can modify it in this method).

Among them, info.getBadgedIcon(mIconDpi) is the method to determine the application icon. This method will eventually enter getBadgedIcon() - > geticon(), of the com.android.launcher3.compat.LauncherActivityInfoCompatV16.java class, and get the icon through Resources.  
The method I used is to first customize a class, LauncherIconTheme.java. The content of this class is as follows

package com.android.launcher3;

import com.android.launcher3.R;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;

public final  class LauncherIconTheme {
    //google mailbox
    private static int GMAIL = R.drawable.ic_launcher_gmail;
    //google Map
    private static int GOOGLE_MAPS = R.drawable.ic_launcher_googlemaps;
    //Custom application resource id
    ...................

    private static String TAG = "LauncherIconTheme";

        //Get Bitmap according to package name and class name
    public static Bitmap  getIconBitmap(Context context , String packageName , String className) {
        Resources resources = context.getResources();
        int iconId = getIconId(packageName, className);
        if (iconId != -1){
            return BitmapFactory.decodeResource(resources, iconId);
        }
        return null;
    }
        //This is the method used to get Drawable according to package name and class name
    public static Drawable getIconDrawable(Context context , String packageName , String className) {
        Resources resources = context.getResources();
        int iconId = getIconId(packageName, className);
        if ( iconId != -1) {
            return resources.getDrawable(iconId);
        }
        return null;
    }
        //Get icon resource id of resource definition according to package name and class name
    private static int getIconId(String packageName , String className){
        if ( "com.google.android.gm".equals(packageName)
                && "com.google.android.gm.ConversationListActivityGmail".equals(className)) {
            return GMAIL;

        }else if ("com.google.android.apps.maps".equals(packageName)
                && "com.google.android.maps.MapsActivity".equals(className)) {
            return GOOGLE_MAPS;

        }else if ....................
            .................................
        }else{
            return -1;          
        }
    }   
}

Then in the cacheLocked method of IconCache

    /**
     * Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
     * This method is not thread safe, it must be called from a synchronized method.
     */
    private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
            HashMap<Object, CharSequence> labelCache, UserHandleCompat user, boolean usePackageIcon) {
        CacheKey cacheKey = new CacheKey(componentName, user);
        CacheEntry entry = mCache.get(cacheKey);
        if (entry == null) {
           .................................

                entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
                //Implement the logic of modifying Icon
                Drawable themeDrawable = LauncherIconTheme
                        .getIconDrawable(mContext,
                                componentName.getPackageName(), componentName.getClassName());
                if ( themeDrawable != null ) {
                    entry.icon = Utilities.createIconBitmap(
                            themeDrawable, mContext);
                }else{
                    entry.icon = Utilities.createIconBitmap(
                            info.getBadgedIcon(mIconDpi), mContext);                    
                }
            } else {
             ...........................................
        return entry;
    }

End. In this method, you can simply implement the function of custom application icon in Launcher. If you have any shortcomings, please point out and make progress together.


Tags: Android Google Java

Posted on Wed, 01 Apr 2020 21:49:49 -0700 by bluwe