客户给了一套应用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;
}