Android7.0 高通平台原生Launcher3未读角标更新流程
--唐旋凯 2017.11.2
做2代项目的时候,图标的未读提示功能是自己写的,所以流程都很清楚,做3代的时候发现7.0的原生launcher已经支持了未读提示的功能,也没去看过它的原理,前几天研究未读提示动画的时候,看了下原生launcher未读图标的更新流程,写个文档记录下。
7.0高通原生的Launcher3分了两个情况来处理未读提示。
第一个情况是在Launcher3刚启动的时候,在Launcher.java的onCreate函数里直接绑定了高通用于处理未读提示的launcherunreadservice(其实进入这个servervice的源码里可以看到高通也只是支持了电话、短信、邮件3个应用的未读提示,而且也是通过查询监听这3个应用的数据库来获取数据的),
private Map mUnreadAppMap = new HashMap();
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IGetUnreadNumber iGetUnreadNumber = IGetUnreadNumber.Stub.asInterface(service);
try {
if(iGetUnreadNumber != null){
mUnreadAppMap = iGetUnreadNumber.GetUnreadNumber();
}
} catch (RemoteException ex) {
}
mIconCache.setUnreadMap(mUnreadAppMap);
unbindService(mConnection);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
可以看到通过这个service的接口函数,我们可以直接取得包含了应用包名和未读条数的map,然后再设置mIconCahe.setUnreadMap(……)来让launcher显示有未读提示的图标。为什么通过mIconCahe.setUnreadMap就能显示有未读提示的图标,因为在生成桌面图标的时候会通过未读提示count的数量来判断是否生成带有提示的图标。IconCaha.java –> cacheLocked(…)-> entry.icon =Utilities.createBadgedIconBitmap(…)
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static Bitmap createBadgedIconBitmap(
Drawable icon, UserHandleCompat user, Context context, int count ) {
float scale = FeatureFlags.LAUNCHER3_DISABLE_ICON_NORMALIZATION ?
1 : IconNormalizer.getInstance().getScale(icon, null);
Bitmap bitmap = createIconBitmap(icon, context, scale);
// create the unread icon's info here
if (isUnreadCountEnabled(context) && count > 0) {
bitmap = createIconBitmapUnreadInfo(context, bitmap, count);
}
return badgeIconForUser(bitmap, user, context);
}
进入函数我们可以看到,通过判断count是否大于0来分别生成是否带有提示的图标。这是Launcher刚启动时就能显示未读提示图标的的流程。
第二种情况是在Launcher启动之后,如果数据变化了如何实时更新相应的图标。在第一种情况的时候已经说了,launcherunreadservice这个服务其实就是用于查询和监听电话、短信、邮件这几个应用的数据库的,当这几个数据库的未读字段发生变化的时候,他就会发送一个带相应参数的广播出来,Launcher只要负责监听这个广播,
"com.android.launcher.action.UNREAD_CHANGED"
然后做出相应的处理就可以了。在LauncherModel.java-> onReceive(…)对这个广播进行了监听:
} else if (ACTION_UNREAD_CHANGED.equals(action)) {
ComponentName componentName = intent.getParcelableExtra(EXTRA_COMPONENT_NAME);
int unreadNum = intent.getIntExtra(EXTRA_UNREAD_NUMBER, 0);
if (componentName == null) return;
synchronized (mUnreadChangedMap) {
mUnreadChangedMap.put(componentName, new UnreadInfo(componentName, unreadNum));
}
sWorker.removeCallbacks(mUnreadUpdateTask);
sWorker.post(mUnreadUpdateTask);
}
可以看到接收到更新的广播后,主要图标更新工作都是UnreadUpateTask这个进程完成,这个函数得代码有点多,就不贴了,主要流程就是会走到AllAppList.java的unreadNumbersChanged(..)函数里,这个函数得作用就是把旧的图标移除,然后获取到一个重新画好角标的图标换上去。代码接着走下去就是调用callback函数通知workspace更新下桌面图标。这样新的数据就更新成功了.
7.0高通未读角标的更新流程基本就是这样。也没有对第三方应用做出支持。