之前一直以为是应用本身在对图标进行修改,看了源码之后发现其实主要的工作并不是应用自己完成的,主要的工作在是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)); } }MTKUnreadLoader.java(Launcher接收到应用发送的广播,进行判断改应用是否可以显示有未处理事件的图标)
packages/apps/Launcher2/src/com/android/launcher2/MTKUnreadLoader.java
public void onReceive(final Context context, final Intent intent) { final String action = intent.getAction(); //过滤广播 if (Intent.MTK_ACTION_UNREAD_CHANGED.equals(action)) { final ComponentName componentName = (ComponentName) intent.getExtra(Intent.MTK_EXTRA_UNREAD_COMPONENT); final int unreadNum = intent.getIntExtra(Intent.MTK_EXTRA_UNREAD_NUMBER, -1); if (mCallbacks != null && componentName != null && unreadNum != -1) { //判断是否支持该功能 final int index = supportUnreadFeature(componentName); if (index >= 0) { //支持 boolean ret = setUnreadNumberAt(index, unreadNum); if (ret) { final UnreadCallbacks callbacks = mCallbacks.get(); if (callbacks != null) { callbacks.bindComponentUnreadChanged(componentName, unreadNum); } ......... }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>
相关推荐
android实现类似在短信图标右上角显示短信个数的效果,比较全面和实用,该代码在ADT中调试通过,在android4.2版本手机上可正常运行。
Android中为图标加上数字--用于未读短信数提醒,待更新应用数提醒等 对应博客 http://blog.csdn.net/michael__li/article/details/6941756
本文主要介绍了Android 桌面图标右上角显示未读消息数字的方法。具有很好的参考价值。下面跟着小编一起来看下吧
Android仿微信未读消息数提示显示数字BadgeView大于99条显示99+
锁屏界面未接来电未读信息图标显示
Android-NavMenu-master一个底部导航栏, 实现了显示未读消息数, 显示红点等效果的封装
现在的很多Android手机软件都是使用的类似于微信的架构,即左右滑动底部图标颜色和文字颜色随之改变。本资源通过一个例子来实现这个效果。
图标爆炸效果(类似小米卸载应用图标散开效果)
android app图标未读消息数(BadgeNumber). 仅仅支持三星/小米/索尼
android spinner的前面设置图标android spinner的前面设置图标android spinner的前面设置图标android spinner的前面设置图标android spinner的前面设置图标
最近在做一个可以查看未读消息的功能,需要在界面中的Tab页的标签icon的右上角添加一个未读消息提示的功能。 先上个效果图出来,比较直观明白需求: 思路上似乎有两种: ... * 绘制图标右上角的未读消息数
android 桌面图标数字提醒 ,一款高仿QQ桌面快捷方式显示未读数量的源代码.zip,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
仿造微信等,设置图标右上角未读消息显示,动感十足
Android应用图标右上角显示数字/图标数字角标,支持小米手机系统、三星手机系统、索尼手机系统(未验证)、Android原生系统(4.3的系统通过验证,其他未验证)
本项目是一款很简单的就是一个MainActivity显示一个静态页面,主要是页面布局很重要,就是类似显示未读短信的条数上面的那个红圈里面带未读数字的形状,如果以后在自己的代码中会遇到显示数字脚标的可以拿这个项目中...
Android中为图标加上数字--用于未读短信数提醒,待更新应用数提醒等
Android 模仿QQ_微信 未读消息显示.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
Android,悬浮窗口,状态栏显示应用图标
android多个图标显示在桌面上,可以用于进入不同的activity,达到不同的安装效果.zip,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。