之前一直以为是应用本身在对图标进行修改,看了源码之后发现其实主要的工作并不是应用自己完成的,主要的工作在是launcher里面完成的.
关于系统里面类似未读短信的具体处理流程如下:
原理
一个应用要实现这个效果,就要在自己有未读的消息的时候发送一个广播告诉系统我有未处理的事件了(例如:短信,电话和邮件等),同时将相关的信息进行保存,比如应用的名称(这里指的是ComponentName)和未处理事件的数量.系统将提升用户有待处理的事件交给Launcher去处理,launcher会接收到对应的广播,不是随便一个应用都有这个待遇的,launcher接到广播之后会先解析数据,看当前的应用有没有这个待遇也就是是否支持显示这个待处理事件的通知.如果通过launcher就会调用相关方法去重绘应用的icon.
效果图:
实现过程分析
Intent.java(系统增加3个常量)
frameworks/base/core/java/android/content/Intent.java
//状态
public static final String MTK_ACTION_UNREAD_CHANGED = "com.mediatek.action.UNREAD_CHANGED";
//应用名称
public static final String MTK_EXTRA_UNREAD_COMPONENT = "com.mediatek.intent.extra.UNREAD_COMPONENT";
//数量
public static final String MTK_EXTRA_UNREAD_NUMBER = "com.mediatek.intent.extra.UNREAD_NUMBER";
系统里面有这个功能几个应用相关的代码路径
日历packages/apps/Calendar/src/com/mediatek/calendar/MTKUtils.java
邮件:packages/apps/Email/src/com/android/email/NotificationController.java
电话:packages/providers/ContactsProvider/src/com/android/providers/contacts/CallLogProvider.java
短信:packages/providers/TelephonyProvider/src/com/android/providers/telephony/MmsSmsProvider.java
这里以电话为例:
假设当前有人打电话进来,系统会保存改记录到数据库,根据事件是否已经处理来判断是否发送广播
CallLogProvider.java(发送有待处理事件的广播)
packages/providers/ContactsProvider/src/com/android/providers/contacts/CallLogProvider.java
/** M: send new Calls broadcast to luancher to update unread icon @{ */
public static final void notifyNewCallsCount(SQLiteDatabase db, Context context) {
Cursor c = null;
…..
//send count=0 to clear the unread icon
if (newCallsCount >= 0) { //有新的来电数量
Intent newIntent = new Intent(Intent.MTK_ACTION_UNREAD_CHANGED);
newIntent.putExtra(Intent.MTK_EXTRA_UNREAD_NUMBER, newCallsCount);
newIntent.putExtra(Intent.MTK_EXTRA_UNREAD_COMPONENT, new ComponentName(Constants.CONTACTS_PACKAGE,
Constants.CONTACTS_DIALTACTS_ACTIVITY));
context.sendBroadcast(newIntent); //发送对应的广播
android.provider.Settings.System.putInt(context.getContentResolver(), Constants.CONTACTS_UNREAD_KEY, Integer
.valueOf(newCallsCount));
}
}
LauncherApplication.java(Launcher注册对应的广播接收器)
packages/apps/Launcher2/src/com/android/launcher2/LauncherApplication.java
public void onCreate() {
........
/// M: register unread broadcast.
if (FeatureOption.MTK_LAUNCHER_UNREAD_SUPPORT) {
mUnreadLoader = new MTKUnreadLoader(getApplicationContext());
// Register unread change broadcast.
filter = new IntentFilter();
filter.addAction(Intent.MTK_ACTION_UNREAD_CHANGED);
registerReceiver(mUnreadLoader, filter); //注册对应的广播接收器
}
..............
}
MTKUnreadLoader.java(处理应用的图标显示未处理事件的数字)
packages/apps/Launcher2/src/com/android/launcher2/MTKUnreadLoader.java
static void drawUnreadEventIfNeed(Canvas canvas, View icon) {
ItemInfo info = (ItemInfo)icon.getTag();
if (info != null && info.unreadNum > 0) { //判断未处理事件数量
Resources res = icon.getContext().getResources();
..........
if (info.unreadNum > Launcher.MAX_UNREAD_COUNT) {
unreadTextNumber = String.valueOf(Launcher.MAX_UNREAD_COUNT);
unreadTextPlusPaint.getTextBounds(unreadTextPlus, 0, unreadTextPlus.length(), unreadTextPlusBounds);
} else {
unreadTextNumber = String.valueOf(info.unreadNum);
}
unreadTextNumberPaint.getTextBounds(unreadTextNumber, 0, unreadTextNumber.length(), unreadTextNumberBounds);
int textHeight = unreadTextNumberBounds.height();
int textWidth = unreadTextNumberBounds.width() + unreadTextPlusBounds.width();
// 数字的背景图
NinePatchDrawable unreadBgNinePatchDrawable = (NinePatchDrawable)res.getDrawable(R.drawable.ic_newevents_numberindication);
.........
Rect unreadBgBounds = new Rect(0, 0, unreadBgWidth, unreadBgHeight);
unreadBgNinePatchDrawable.setBounds(unreadBgBounds);
int unreadMarginTop = 0;
int unreadMarginRight = 0;
if (info instanceof ShortcutInfo) { //workspace 里面的快捷方式
if (info.container == (long)LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
unreadMarginTop = (int)res.getDimension(R.dimen.hotseat_unread_margin_top);
unreadMarginRight = (int)res.getDimension(R.dimen.hotseat_unread_margin_right);
} else if (info.container == (long)LauncherSettings.Favorites.CONTAINER_DESKTOP) {
unreadMarginTop = (int)res.getDimension(R.dimen.workspace_unread_margin_top);
unreadMarginRight = (int)res.getDimension(R.dimen.workspace_unread_margin_right);
} else {
unreadMarginTop = (int)res.getDimension(R.dimen.folder_unread_margin_top);
unreadMarginRight = (int)res.getDimension(R.dimen.folder_unread_margin_right);
}
} else if (info instanceof FolderInfo) { //文件夹
if (info.container == (long)LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
unreadMarginTop = (int)res.getDimension(R.dimen.hotseat_unread_margin_top);
unreadMarginRight = (int)res.getDimension(R.dimen.hotseat_unread_margin_right);
} else if (info.container == (long)LauncherSettings.Favorites.CONTAINER_DESKTOP) {
unreadMarginTop = (int)res.getDimension(R.dimen.workspace_unread_margin_top);
unreadMarginRight = (int)res.getDimension(R.dimen.workspace_unread_margin_right);
}
}
else if (info instanceof ApplicationInfo) { //all app 里面的应用icon
unreadMarginTop = (int)res.getDimension(R.dimen.app_list_unread_margin_top);
unreadMarginRight = (int)res.getDimension(R.dimen.app_list_unread_margin_right);
}
int unreadBgPosX = icon.getScrollX() + icon.getWidth() - unreadBgWidth - unreadMarginRight;
int unreadBgPosY = icon.getScrollY() + unreadMarginTop;
canvas.save();
canvas.translate(unreadBgPosX, unreadBgPosY);
unreadBgNinePatchDrawable.draw(canvas);
/// M: Draw unread text.
Paint.FontMetrics fontMetrics = unreadTextNumberPaint.getFontMetrics();
if (info.unreadNum > Launcher.MAX_UNREAD_COUNT) {
canvas.drawText(unreadTextNumber,
(unreadBgWidth - unreadTextPlusBounds.width()) / 2,
(unreadBgHeight + textHeight) / 2,
unreadTextNumberPaint);
canvas.drawText(unreadTextPlus,
(unreadBgWidth + unreadTextNumberBounds.width()) / 2,
(unreadBgHeight + textHeight) / 2 + fontMetrics.ascent / 2,
unreadTextPlusPaint);
} else {
.....
}
}
unread_support_shortcuts.xml(配置哪些应用可以显示待处理的事件)
packages/apps/Launcher2/res/xml/unread_support_shortcuts.xml
<unreadshortcuts xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
<!--电话-->
<shortcut
launcher:unreadPackageName="com.android.contacts"
launcher:unreadClassName="com.android.contacts.activities.DialtactsActivity"
launcher:unreadType="0"
launcher:unreadKey="com_android_contacts_mtk_unread"
/>
<!--短信-->
<shortcut
launcher:unreadPackageName="com.android.mms"
launcher:unreadClassName="com.android.mms.ui.BootActivity"
launcher:unreadType="0"
launcher:unreadKey="com_android_mms_mtk_unread"
/>
<!--邮件-->
<shortcut
launcher:unreadPackageName="com.android.email"
launcher:unreadClassName="com.android.email.activity.Welcome"
launcher:unreadType="0"
launcher:unreadKey="com_android_email_mtk_unread"
/>
................
</unreadshortcuts>
原文:http://862123204-qq-com.iteye.com/blog/2000310
分享到:
相关推荐
andriod2.3修改Launcher让图标不显示在桌面或者主菜单中,4.0只有很少的区别
Android实现图标拖拽.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
9.0 10.0Launcher3修改默认的app图标和hotseat图标为圆角图标
android 系统桌面logo增加消息角标功能,解决目前android系统只有小米等几类手机有消息角标,华为、三星等手机。。
Launcher3升级变化:小部件变化 、...UI客制化 :桌面布局 、布局配置 、预置图标 、图标客制化 、待机界面客制化、应用抽屉客制化 功能客制化 :桌面样式 、图标角标、动态图标 、Hotseat图标自适应 、最近任务扩展功能
android桌面拖拽效果.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
在Android原生系统中,众所周知不支持桌面图标显示未读消息提醒的数字,虽然第三方控件BadgeView可以实现应用内的数字提醒。但对于系统的图标,特别是app的logo图标很难实现数字标志,即使是绘图的方式不断修改,但...
我写了几篇博客来讲解Launcher3桌面什么的,有兴趣的可以看看这里: 概述 Android的触摸控制流程 Launcher3界面的布局和结构 Launcher3中的常用类 Launcher3的启动流程(一) 细说ItemInfo Launcher3的启动流程(二...
Android 轻松打造一个APP动态切换桌面图标Launcher
Android上类似桌面应用的一个GridView,可以拖动位置,支持多页,可以拖动子项到另一页。
主要介绍了Android实现系统的桌面图标文字的双行显示效果,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
每当双 11、12 来临之际,Android 手机 Launcher 中的淘宝、天猫图标就会变成双 11、12 主题的图标。该 Demo 就实现了动态切换图标、名称
一个页与页里面的元素都能被拖动的view,类似于ViewPager。这个可以做出launcher中桌面图标在不同页之间切换的效果.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
android Launcher 源码 native 实现桌面添加应用图标 管理屏幕 多屏幕管理 添加widget 动画桌面 等
选择快捷方式后,会弹出一个对话框,显示出了可添加快捷方式的Activity所属的应用程序的图标和名称的列表。当我们想把添加快捷方式的Activity添加到这一列表时,只需要在这个Activity注册时添加一个Action为android....
类似桌面应用图标效果 android触摸事件机制 随意拖拽效果 消息提醒标志 长按事件,触摸事件,点击事件并存
Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT"); // 快捷名称 shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, tName); // 快捷图标是允许重复 shortcut.putExtra(...
基于4.0源码,实现Launcher循环滚动,待机桌面快捷方式的循环翻页,循环滚动时桌面图标跟随手指移动等功能。有兴趣的朋友可以下载了看看。
7.另外,如果你重新运行之后图标没有变化,不用着急,现在智能手机基本上都是桌面和应用同时控制着图标的显示,两者一起改,桌面图标才会变化,而桌面图标是有缓存的,应用改了之后,桌面依然控制着显示原来的图标,...