Android8.1 Launcher3中应用icon的替换

客户给了一套应用icon图片,要求替换当前应用的icon,实现如下.

将要替换的应用包名存放在字符串数组中:


            
	    com.android.camera2
	    
	    com.android.chrome,com.android.browser
	    
	    com.android.contacts
	    
	    com.android.dialer
	    
	    com.android.gallery3d
	    
	    com.android.music
	    
	    com.android.settings
	    
	    com.android.vending
 

将客户提供的应用icon的名称也存放在字符串数组中,注意应用icon图片名称在数组中位置要与包名数组中应用包名的位置

相对应,如下:


	    
	    theme_camera.png
	    
	    theme_browser.png
	    
	    theme_contacts.png
	    
	    theme_phone.png
	    
	    theme_gallery.png
	    
	    theme_music.png
	    
	    theme_settings.png
	    
	    theme_appstore.png
 
Launcher3获取应用图标时都会经过一个类,IconCache.java

代码路径:packages/apps/Launcher3/src/com/android/launcher3/IconCache.java

在IconCache.java中找到函数:cacheLocked

函数中有下面几行代码:

entry.icon = LauncherIcons.createBadgedIconBitmap(
                   getFullResIcon(info), info.getUser(), mContext,
                   infoProvider.get().getApplicationInfo().targetSdkVersion);

没错这里就是设置应用icon的地方了,下面就需要我们在这里替换客户提供的应用icon了。

首先获取存放包名的字符串数组:

private String getIconPackage(int i){
	String[] arr = mContext.getResources().getStringArray(R.array.icon_package);

	return arr[i];
}

再通过存放icon图片名称的数组得到对应图片的资源ID:

private int getIconId(int i){

        String[] imageNameArr = mContext.getResources().getStringArray(R.array.icon_image);
	String imageName = null;
	if(!TextUtils.isEmpty(imageNameArr[i])){
             //获取图片的名称,去掉后缀
             imageName = imageNameArr[i].substring(0, imageNameArr[i].indexOf("."));
	}
        //通过图片名称获取图片的资源ID
        int resId = mContext.getResources().getIdentifier(imageName, "drawable" , mContext.getPackageName()); 
	return resId;
}

然后再实现替换应用icon的功能:

private void setAppIconTheme(ComponentName componentName, 
				Provider infoProvider, 
				LauncherActivityInfo info, 
				CacheEntry entry){
	String[] arr = mContext.getResources().getStringArray(R.array.icon_package);							
	//通过for循环取数组中的包名和系统应用的包名对比,匹配上则替换该应用的icon,替换成功就结束函数					
	for (int i = 0; i < arr.length; i++) {
		Log.d("lp","componentName.getPackageName()="+componentName.getPackageName());
                //这里判断字符串包含而不是相等,这样的好处我们可以在包名数组中的单个item中存放同类功能的不同应用,
                //比如邮箱存放如下:
                //
                //com.google.android.gm.lite,com.android.email
                if(getIconPackage(i).contains(componentName.getPackageName())){
			Log.d("lp","packageName("+ i +")="+getIconPackage(i));
			entry.icon = BitmapFactory.decodeResource(mContext.getResources(),getIconId(i));
			return;
		}
	}
        //for循环没匹配到,则执行默认代码
	entry.icon = LauncherIcons.createBadgedIconBitmap(
                   getFullResIcon(info), info.getUser(), mContext,
                   infoProvider.get().getApplicationInfo().targetSdkVersion);
}

接下来就用函数setAppIconTheme替换系统默认的代码:

protected CacheEntry cacheLocked(
            @NonNull ComponentName componentName,
            @NonNull Provider infoProvider,
            UserHandle user, boolean usePackageIcon, boolean useLowResIcon) {

        ........... 
        ........... 
        //此处省略 
        ........... 
        ........... 
        //用函数setAppIconTheme替换系统默认的代码: 
        if (mContext.getResources().getBoolean(R.bool.config_app_icon_theme)) { 
        	setAppIconTheme(componentName, infoProvider, info, entry);
        }else { 
        	entry.icon = LauncherIcons.createBadgedIconBitmap( getFullResIcon(info), 
        								info.getUser(), mContext, 
        								infoProvider.get().getApplicationInfo().targetSdkVersion);
        } 
        ...........
        ...........
        //此处省略
        ...........
        ...........
        return entry;
}

能力有限,不当之处请多多指正!!

你可能感兴趣的:(Android学习)