Android 类似未读短信图标显示数字效果的分析

来源:互联网 发布:做淘宝云客服工资多少 编辑:程序博客网 时间:2024/06/02 05:26
 之前一直以为是应用本身在对图标进行修改,看了源码之后发现其实主要的工作并不是应用自己完成的,主要的工作在是launcher里面完成的.
关于系统里面类似未读短信的具体处理流程如下,

 
原理
一个应用要实现这个效果,就要在自己有未读的消息的时候发送一个广播告诉系统我有未处理的事件了(例如:短信,电话和邮件等),同时将相关的信息进行保存,比如应用的名称(这里指的是ComponentName)和未处理事件的数量.系统将提升用户有待处理的事件交给Launcher去处理,launcher会接收到对应的广播,不是随便一个应用都有这个待遇的,launcher接到广播之后会先解析数据,看当前的应用有没有这个待遇也就是是否支持显示这个待处理事件的通知.如果通过launcher就会调用相关方法去重绘应用的icon.
效果图:

 实现过程分析
Intent.java(系统增加3个常量)
frameworks/base/core/java/android/content/Intent.java
Java代码  收藏代码
  1. //状态     
  2. public static final String MTK_ACTION_UNREAD_CHANGED = "com.mediatek.action.UNREAD_CHANGED";  
  3. //应用名称      
  4. public static final String MTK_EXTRA_UNREAD_COMPONENT = "com.mediatek.intent.extra.UNREAD_COMPONENT";  
  5. //数量  
  6. public static final String MTK_EXTRA_UNREAD_NUMBER = "com.mediatek.intent.extra.UNREAD_NUMBER";  
  7.    
 
系统里面有这个功能几个应用相关的代码路径
日历 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
Java代码  收藏代码
  1. /** M: send new Calls broadcast to luancher to update unread icon @{ */  
  2.     public static final void notifyNewCallsCount(SQLiteDatabase db, Context context) {  
  3.         Cursor c = null;  
  4.        …..  
  5.         //send count=0 to clear the unread icon  
  6.         if (newCallsCount >= 0) { //有新的来电数量  
  7.             Intent newIntent = new Intent(Intent.MTK_ACTION_UNREAD_CHANGED);  
  8.             newIntent.putExtra(Intent.MTK_EXTRA_UNREAD_NUMBER, newCallsCount);  
  9.             newIntent.putExtra(Intent.MTK_EXTRA_UNREAD_COMPONENT, new ComponentName(Constants.CONTACTS_PACKAGE,  
  10.                     Constants.CONTACTS_DIALTACTS_ACTIVITY));  
  11.             context.sendBroadcast(newIntent); //发送对应的广播  
  12.             android.provider.Settings.System.putInt(context.getContentResolver(), Constants.CONTACTS_UNREAD_KEY, Integer  
  13.                     .valueOf(newCallsCount));  
  14.         }  
  15.     }  
 MTKUnreadLoader.java(Launcher接收到应用发送的广播,进行判断改应用是否可以显示有未处理事件的图标)
packages/apps/Launcher2/src/com/android/launcher2/MTKUnreadLoader.java
Java代码  收藏代码
  1. public void onReceive(final Context context, final Intent intent) {  
  2.         final String action = intent.getAction();  
  3.             //过滤广播  
  4.         if (Intent.MTK_ACTION_UNREAD_CHANGED.equals(action)) {  
  5.             final ComponentName componentName = (ComponentName) intent.getExtra(Intent.MTK_EXTRA_UNREAD_COMPONENT);  
  6.             final int unreadNum = intent.getIntExtra(Intent.MTK_EXTRA_UNREAD_NUMBER, -1);  
  7.   
  8.             if (mCallbacks != null && componentName != null && unreadNum != -1) {  
  9.                 //判断是否支持该功能  
  10.                 final int index = supportUnreadFeature(componentName);  
  11.                 if (index >= 0) { //支持  
  12.                     boolean ret = setUnreadNumberAt(index, unreadNum);  
  13.                     if (ret) {  
  14.                         final UnreadCallbacks callbacks = mCallbacks.get();  
  15.                         if (callbacks != null) {  
  16.                             callbacks.bindComponentUnreadChanged(componentName, unreadNum);  
  17.                         }  
  18.                     .........  
  19.     }  
 LauncherApplication.java(Launcher注册对应的广播接收器)
packages/apps/Launcher2/src/com/android/launcher2/LauncherApplication.java
Java代码  收藏代码
  1. public void onCreate() {  
  2.        ........  
  3.         /// M: register unread broadcast.  
  4.         if (FeatureOption.MTK_LAUNCHER_UNREAD_SUPPORT) {  
  5.             mUnreadLoader = new MTKUnreadLoader(getApplicationContext());  
  6.             // Register unread change broadcast.  
  7.             filter = new IntentFilter();  
  8.             filter.addAction(Intent.MTK_ACTION_UNREAD_CHANGED);  
  9.             registerReceiver(mUnreadLoader, filter); //注册对应的广播接收器  
  10.         }  
  11.        ..............  
  12.     }  
 MTKUnreadLoader.java(处理应用的图标显示未处理事件的数字)
packages/apps/Launcher2/src/com/android/launcher2/MTKUnreadLoader.java
Java代码  收藏代码
  1. static void drawUnreadEventIfNeed(Canvas canvas, View icon) {  
  2.         ItemInfo info = (ItemInfo)icon.getTag();  
  3.         if (info != null && info.unreadNum > 0) { //判断未处理事件数量  
  4.             Resources res = icon.getContext().getResources();  
  5.            ..........  
  6.             if (info.unreadNum > Launcher.MAX_UNREAD_COUNT) {  
  7.                 unreadTextNumber = String.valueOf(Launcher.MAX_UNREAD_COUNT);  
  8.                 unreadTextPlusPaint.getTextBounds(unreadTextPlus, 0, unreadTextPlus.length(), unreadTextPlusBounds);  
  9.             } else {  
  10.                 unreadTextNumber = String.valueOf(info.unreadNum);  
  11.             }  
  12.             unreadTextNumberPaint.getTextBounds(unreadTextNumber, 0, unreadTextNumber.length(), unreadTextNumberBounds);  
  13.             int textHeight = unreadTextNumberBounds.height();  
  14.             int textWidth = unreadTextNumberBounds.width() + unreadTextPlusBounds.width();  
  15.   
  16.             // 数字的背景图  
  17.             NinePatchDrawable unreadBgNinePatchDrawable = (NinePatchDrawable)res.getDrawable(R.drawable.ic_newevents_numberindication);  
  18.            .........  
  19.             Rect unreadBgBounds = new Rect(00, unreadBgWidth, unreadBgHeight);  
  20.             unreadBgNinePatchDrawable.setBounds(unreadBgBounds);  
  21.   
  22.             int unreadMarginTop = 0;  
  23.             int unreadMarginRight = 0;  
  24.             if (info instanceof ShortcutInfo) { //workspace 里面的快捷方式  
  25.                 if (info.container == (long)LauncherSettings.Favorites.CONTAINER_HOTSEAT) {  
  26.                     unreadMarginTop = (int)res.getDimension(R.dimen.hotseat_unread_margin_top);  
  27.                     unreadMarginRight = (int)res.getDimension(R.dimen.hotseat_unread_margin_right);  
  28.                 } else if (info.container == (long)LauncherSettings.Favorites.CONTAINER_DESKTOP) {  
  29.                     unreadMarginTop = (int)res.getDimension(R.dimen.workspace_unread_margin_top);  
  30.                     unreadMarginRight = (int)res.getDimension(R.dimen.workspace_unread_margin_right);  
  31.                 } else {  
  32.                     unreadMarginTop = (int)res.getDimension(R.dimen.folder_unread_margin_top);  
  33.                     unreadMarginRight = (int)res.getDimension(R.dimen.folder_unread_margin_right);  
  34.                 }  
  35.             } else if (info instanceof FolderInfo) { //文件夹  
  36.                 if (info.container == (long)LauncherSettings.Favorites.CONTAINER_HOTSEAT) {  
  37.                     unreadMarginTop = (int)res.getDimension(R.dimen.hotseat_unread_margin_top);  
  38.                     unreadMarginRight = (int)res.getDimension(R.dimen.hotseat_unread_margin_right);  
  39.                 } else if (info.container == (long)LauncherSettings.Favorites.CONTAINER_DESKTOP) {  
  40.                     unreadMarginTop = (int)res.getDimension(R.dimen.workspace_unread_margin_top);  
  41.                     unreadMarginRight = (int)res.getDimension(R.dimen.workspace_unread_margin_right);  
  42.                 }  
  43.             }  
  44.             else if (info instanceof ApplicationInfo) { //all app 里面的应用icon  
  45.                 unreadMarginTop = (int)res.getDimension(R.dimen.app_list_unread_margin_top);  
  46.                 unreadMarginRight = (int)res.getDimension(R.dimen.app_list_unread_margin_right);  
  47.             }  
  48.   
  49.             int unreadBgPosX = icon.getScrollX() + icon.getWidth() - unreadBgWidth - unreadMarginRight;  
  50.             int unreadBgPosY = icon.getScrollY() + unreadMarginTop;  
  51.   
  52.             canvas.save();  
  53.             canvas.translate(unreadBgPosX, unreadBgPosY);  
  54.   
  55.             unreadBgNinePatchDrawable.draw(canvas);  
  56.   
  57.             /// M: Draw unread text.  
  58.             Paint.FontMetrics fontMetrics = unreadTextNumberPaint.getFontMetrics();  
  59.             if (info.unreadNum > Launcher.MAX_UNREAD_COUNT) {  
  60.                 canvas.drawText(unreadTextNumber,  
  61.                                 (unreadBgWidth - unreadTextPlusBounds.width()) / 2,  
  62.                                 (unreadBgHeight + textHeight) / 2,  
  63.                                 unreadTextNumberPaint);  
  64.                 canvas.drawText(unreadTextPlus,  
  65.                                 (unreadBgWidth + unreadTextNumberBounds.width()) / 2,  
  66.                                 (unreadBgHeight + textHeight) / 2 + fontMetrics.ascent / 2,  
  67.                                 unreadTextPlusPaint);  
  68.             } else {  
  69.                .....  
  70.         }  
  71.     }  
 unread_support_shortcuts.xml(配置哪些应用可以显示待处理的事件)
packages/apps/Launcher2/res/xml/unread_support_shortcuts.xml
Xml代码  收藏代码
  1. <unreadshortcuts xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">  
  2. <!--电话-->  
  3.     <shortcut  
  4.         launcher:unreadPackageName="com.android.contacts"  
  5.         launcher:unreadClassName="com.android.contacts.activities.DialtactsActivity"  
  6.         launcher:unreadType="0"  
  7.         launcher:unreadKey="com_android_contacts_mtk_unread"  
  8.      />  
  9. <!--短信-->  
  10.      <shortcut  
  11.         launcher:unreadPackageName="com.android.mms"  
  12.         launcher:unreadClassName="com.android.mms.ui.BootActivity"  
  13.         launcher:unreadType="0"  
  14.         launcher:unreadKey="com_android_mms_mtk_unread"  
  15.      />  
  16. <!--邮件-->  
  17.      <shortcut  
  18.         launcher:unreadPackageName="com.android.email"  
  19.         launcher:unreadClassName="com.android.email.activity.Welcome"  
  20.         launcher:unreadType="0"  
  21.         launcher:unreadKey="com_android_email_mtk_unread"  
  22.      />  
  23.     ................  
  24. </unreadshortcuts>  



原文:http://862123204-qq-com.iteye.com/blog/2000310
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 衣服上粘胶水了怎么办 衣服钻掉了有胶怎么办 衣服上贴纸掉了怎么办 裤子沾上502胶水怎么办 衣服上沾泡沫胶怎么办 衣服上面滴上502怎么办 502胶水弄衣服上怎么办 裤子上粘了胶怎么办 胶水滴在衣服上怎么办 衣服上有502胶水怎么办 衣服上面粘了胶怎么办 衣服上的胶干了怎么办 凌晨4点到火车站怎么办 运管罚款没钱交怎么办 郑州地铁票没买怎么办 遇到吸毒者拦路威胁要钱怎么办 开车遇见拦路要钱的怎么办 高速上有人拦车怎么办 马路上有人拦车怎么办 苹果手机下截软件要钱怎么办 孩子在学校问同学要钱怎么办 在学校被同学要钱怎么办 把人家店砸了要怎么办 外汇出金不到账怎么办 把罚款单弄丢了怎么办 在12306买不到下铺怎么办有 地铁票买反了怎么办 香港买错特惠票怎么办 到达迪拜t3 后怎么办 海藻面膜调多了怎么办 被鸡爪子抓伤了怎么办 被鸡抓伤肿了怎么办 护士电子化没有激活码怎么办 窗帘盒螺丝掉了怎么办 窗帘的环扣掉了怎么办 门式起重吊装行车脱轨怎么办 在日本丢了东西怎么办 在日本钱包丢了怎么办 被起诉后没钱还怎么办 分期付款卖车打不起车款怎么办 地铁票买多了怎么办