如何在android4.4上添加未读信息,未接来电或日历新事件提醒等功能,android4.2上

很多商家都已实现,其实将其移植过来就可以了,不过4.4有许多类变化了,要稍作修

改,下面将列出要修改哪些类?添加些什么方法?
详细修改如下:
1.首先准备各种大小的ic_newevents_numberindication.9.png图片,这个自己去找吧

,如果你是搞开发的,在以前的项目中都可以找到的。
2.定义个未读信息支持的app事件xml,我这个支持短信,日历,电话,邮件:
b/packages/apps/Launcher3/res/xml/unread_support_shortcuts.xml
内容如下:

+<?xml version="1.0" encoding="UTF-8"?>
 +<unreadshortcuts xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
 +
 +    <shortcut
 +        launcher:unreadPackageName="com.android.dialer"
 +        launcher:unreadClassName="com.android.dialer.DialtactsActivity"
 +        launcher:unreadType="0"
 +        launcher:unreadKey="com_android_contacts_unread"
 +     />
 +     <shortcut
 +        launcher:unreadPackageName="com.android.mms"
 +        launcher:unreadClassName="com.android.mms.ui.BootActivity"
 +        launcher:unreadType="0"
 +        launcher:unreadKey="com_android_mms_unread"
 +     />
 +     <shortcut
 +        launcher:unreadPackageName="com.android.email"
 +        launcher:unreadClassName="com.android.email.activity.Welcome"
 +        launcher:unreadType="0"
 +        launcher:unreadKey="com_android_email_unread"
 +     />
 +     <shortcut
 +        launcher:unreadPackageName="com.android.calendar"
 +        launcher:unreadClassName="com.android.calendar.AllInOneActivity"
 +        launcher:unreadType="0"
 +        launcher:unreadKey="com_android_calendar_unread"
 +     />
 +     <shortcut
 +        launcher:unreadPackageName="com.orangelabs.rcs"
 +        launcher:unreadClassName="com.mediatek.rcse.activities.ChatMainActivity"
 +        launcher:unreadType="0"
 +        launcher:unreadKey="com_android_rcse_unread"
 +    />
 +    <shortcut
 +        launcher:unreadPackageName="com.android.cellbroadcastreceiver"
 +        launcher:unreadClassName="com.android.cellbroadcastreceiver.CellBroadcastLis
tActivity"
 +        launcher:unreadType="0"
 +        launcher:unreadKey="com_android_calendar_unread"
 +    />
 +    <shortcut
 +        launcher:unreadPackageName="com.mediatek.cellbroadcastreceiver"
 +        launcher:unreadClassName="com.mediatek.cellbroadcastreceiver.CellBroadcastLi
stActivity"
 +        launcher:unreadType="0"
 +        launcher:unreadKey="com_mediatek_cellbroadcastreceiver_unread"
 +    />
 +</unreadshortcuts>3.添加几种需要用到而之前没有的权限:
b/packages/apps/Launcher3/AndroidManifest.xml
 <original-package android:name="com.android.launcher3" />
 <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
 +    <uses-permission android:name="android.permission.ADVANCED_WIDGET_API"/>
 +    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
 +    <uses-permission android:name="android.permission.INSTALL_PACKAGES"/>
 +    <uses-permission android:name="android.permission.DELETE_PACKAGES"/>4.定义要用的字符串:b/packages/apps/Launcher3/res/values/attrs.xml
 +     <!-- XML attributes used by unread_support_shortcuts.xml -->
 +    <declare-styleable name="UnreadShortcut">
 +         <attr name="unreadPackageName" format="string" />
 +        <attr name="unreadClassName" format="string" />
 +        <attr name="unreadKey" format="string" />
 +        <attr name="unreadType" format="integer" />
 +    </declare-styleable>5.定义显示的数字大小尺寸,这个可以自己修改到满意,这个是四行五列排列的
1080*1920屏幕大小的尺寸。
 b/packages/apps/Launcher3/res/values/dimens.xml
 +   <!-- Add for unread events feature. -->
 +    <dimen name="unread_minWidth">20dp</dimen>
 +    <dimen name="hotseat_unread_margin_top">16dp</dimen>
 +    <dimen name="hotseat_unread_margin_right">8dp</dimen>
 +    <dimen name="folder_unread_margin_top">16dp</dimen>
 +    <dimen name="folder_unread_margin_right">14dp</dimen>
 +    <dimen name="workspace_unread_margin_top">16dp</dimen>
 +    <dimen name="workspace_unread_margin_right">16dp</dimen>
 +    <dimen name="app_list_unread_margin_top">20dp</dimen>
 +    <dimen name="app_list_unread_margin_right">16dp</dimen>
 +    <dimen name="unread_text_margin">8dp</dimen>
 +    <dimen name="unread_text_number_size">14sp</dimen>
 +    <dimen name="unread_text_plus_size">10sp</dimen>
 6.接下来就是写一个类了,这里命名为UnreadLoader.java:
 b/packages/apps/Launcher3/src/com/android/launcher3/UnreadLoader.javapackage com.android.launcher3;
import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Canvas;
 import android.graphics.drawable.NinePatchDrawable;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.Typeface;
 import android.os.AsyncTask;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.SuperscriptSpan;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.View;import com.android.internal.util.XmlUtils;
 import com.android.launcher3.R;import com.mediatek.launcher3.ext.LauncherLog;
import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;class UnreadSupportShortcut {
     public UnreadSupportShortcut(String pkgName, String clsName, String keyString, int type) {
         mComponent = new ComponentName(pkgName, clsName);
         mKey = keyString;
         mShortcutType = type;
         mUnreadNum = 0;
     }    ComponentName mComponent;
     String mKey;
     int mShortcutType;
     int mUnreadNum;    @Override
     public String toString() {
         return "{UnreadSupportShortcut[" + mComponent + "], key = " + mKey + ",type = "
                 + mShortcutType + ",unreadNum = " + mUnreadNum + "}";
     }
 }/**
  * M: This class is a util class, implemented to do the following two things,:
  *
  * 1.Read config xml to get the shortcuts which support displaying unread number,
  * then get the initial value of the unread number of each component and update
  * shortcuts and folders through callbacks implemented in Launcher.
  *
  * 2. Receive unread broadcast sent by application, update shortcuts and folders in
  * workspace, hot seat and update application icons in app customize paged view.
  */
 public class UnreadLoader extends BroadcastReceiver {
     private static final String TAG = "UnreadLoader";
     private static final String TAG_UNREADSHORTCUTS = "unreadshortcuts";    private static final ArrayList<UnreadSupportShortcut> 
UNREAD_SUPPORT_SHORTCUTS = new ArrayList<UnreadSupportShortcut>();
    private static int sUnreadSupportShortcutsNum = 0;
     private static final Object LOG_LOCK = new Object();    private Context mContext;
    private WeakReference<UnreadCallbacks> mCallbacks;
    public UnreadLoader(Context context) {
         mContext = context;
     }    @Override
     public void onReceive(final Context context, final Intent intent) {
         final String action = intent.getAction();
         if (Intent.XXX_ACTION_UNREAD_CHANGED.equals(action)) {
             final ComponentName componentName = (ComponentName) intent
                     .getExtra(Intent.XXX_EXTRA_UNREAD_COMPONENT);
             final int unreadNum = intent.getIntExtra(Intent.XXX_EXTRA_UNREAD_NUMBER, -1);
             if (LauncherLog.DEBUG) {
                 LauncherLog.d(TAG, "Receive unread broadcast: componentName = " + componentName
                         + ", unreadNum = " + unreadNum + ", mCallbacks = " + mCallbacks
                         + getUnreadSupportShortcutInfo());
             }            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);
                         }
                     }
                 }
             }
         }
     }    /**
      * Set this as the current Launcher activity object for the loader.
      */
     public void initialize(UnreadCallbacks callbacks) {
         mCallbacks = new WeakReference<UnreadCallbacks>(callbacks);
         if (LauncherLog.DEBUG_UNREAD) {
             LauncherLog.d(TAG, "initialize: callbacks = " + callbacks + ", mCallbacks = " + mCallbacks);
         }
     }    /**
      * Load and initialize unread shortcuts.
      *
      * @param context
      */
     void loadAndInitUnreadShortcuts() {
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... unused) {
                 loadUnreadSupportShortcuts();
                 initUnreadNumberFromSystem();
                 return null;
             }            @Override
             protected void onPostExecute(final Void result) {
                 if (mCallbacks != null) {
                     UnreadCallbacks callbacks = mCallbacks.get();
                     if (callbacks != null) {
                         callbacks.bindUnreadInfoIfNeeded();
                     }
                 }
             }
         }.execute();
     }    /**
      * Initialize unread number by querying system settings provider.
      *
      * @param context
      */
     private void initUnreadNumberFromSystem() {
         final ContentResolver cr = mContext.getContentResolver();
         final int shortcutsNum = sUnreadSupportShortcutsNum;
         UnreadSupportShortcut shortcut = null;
         for (int i = 0; i < shortcutsNum; i++) {
             shortcut = UNREAD_SUPPORT_SHORTCUTS.get(i);
             try {
                 shortcut.mUnreadNum = android.provider.Settings.System.getInt(cr, shortcut.mKey);
                 if (LauncherLog.DEBUG_UNREAD) {
                     LauncherLog.d(TAG, "initUnreadNumberFromSystem: key = " + shortcut.mKey
                             + ", unreadNum = " + shortcut.mUnreadNum);
                 }
             } catch (android.provider.Settings.SettingNotFoundException e) {
                 LauncherLog.e(TAG, "initUnreadNumberFromSystem SettingNotFoundException key = "
                         + shortcut.mKey + ", e = " + e.getMessage());
             }
         }
         if (LauncherLog.DEBUG_UNREAD) {
             LauncherLog.d(TAG, "initUnreadNumberFromSystem end:" + getUnreadSupportShortcutInfo());
         }
     }    private void loadUnreadSupportShortcuts() {
         long start = System.currentTimeMillis();
         if (LauncherLog.DEBUG_PERFORMANCE) {
             LauncherLog.d(TAG, "loadUnreadSupportShortcuts begin: start = " + start);
         }        // Clear all previous parsed unread shortcuts.
         UNREAD_SUPPORT_SHORTCUTS.clear();        try {
             XmlResourceParser parser = mContext.getResources().getXml(
                     R.xml.unread_support_shortcuts);
             AttributeSet attrs = Xml.asAttributeSet(parser);
             XmlUtils.beginDocument(parser, TAG_UNREADSHORTCUTS);            final int depth = parser.getDepth();
            int type = -1;
             while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
                     && type != XmlPullParser.END_DOCUMENT) {                if (type != XmlPullParser.START_TAG) {
                     continue;
                 }                TypedArray a = mContext.obtainStyledAttributes(attrs, 
R.styleable.UnreadShortcut);
                 synchronized (LOG_LOCK) {
                     UNREAD_SUPPORT_SHORTCUTS.add(new UnreadSupportShortcut(a
                             .getString(R.styleable.UnreadShortcut_unreadPackageName), a
                             .getString(R.styleable.UnreadShortcut_unreadClassName), a
                             .getString(R.styleable.UnreadShortcut_unreadKey), a.getInt(
                             R.styleable.UnreadShortcut_unreadType, 0)));
                 }
                 a.recycle();            }
         } catch (XmlPullParserException e) {
             LauncherLog.w(TAG, "Got XmlPullParserException while parsing unread shortcuts.", e);
         } catch (IOException e) {
             LauncherLog.w(TAG, "Got IOException while parsing unread shortcuts.", e);
         }
         sUnreadSupportShortcutsNum = UNREAD_SUPPORT_SHORTCUTS.size();
         if (LauncherLog.DEBUG_PERFORMANCE) {
             LauncherLog.d(TAG, "loadUnreadSupportShortcuts end: time used = "
                     + (System.currentTimeMillis() - start) + ",sUnreadSupportShortcutsNum = "
                     + sUnreadSupportShortcutsNum + getUnreadSupportShortcutInfo());
         }
     }    /**
      * Get unread support shortcut information, since the information are stored
      * in an array list, we may query it and modify it at the same time, a lock
      * is needed.
      *
      * @return
      */
     private static String getUnreadSupportShortcutInfo() {
         String info = " Unread support shortcuts are ";
         synchronized (LOG_LOCK) {
             info += UNREAD_SUPPORT_SHORTCUTS.toString();
         }
         return info;
     }    /**
      * Whether the given component support unread feature.
      *
      * @param component
      * @return
      */
     static int supportUnreadFeature(ComponentName component) {
         if (LauncherLog.DEBUG_UNREAD) {
             LauncherLog.d(TAG, "supportUnreadFeature: component = " + component);
         }
         if (component == null) {
             return -1;
         }        final int size = UNREAD_SUPPORT_SHORTCUTS.size();
         for (int i = 0, sz = size; i < sz; i++) {
             if (UNREAD_SUPPORT_SHORTCUTS.get(i).mComponent.equals(component)) {
                 return i;
             }
         }        return -1;
     }    /**
      * Set the unread number of the item in the list with the given unread number.
      *
      * @param index
      * @param unreadNum
      * @return
      */
     static synchronized boolean setUnreadNumberAt(int index, int unreadNum) {
         if (index >= 0 || index < sUnreadSupportShortcutsNum) {
             if (LauncherLog.DEBUG_UNREAD) {
                 LauncherLog.d(TAG, "setUnreadNumberAt: index = " + index + ",unreadNum = " + unreadNum
                         + getUnreadSupportShortcutInfo());
             }
             if (UNREAD_SUPPORT_SHORTCUTS.get(index).mUnreadNum != unreadNum) {
                 UNREAD_SUPPORT_SHORTCUTS.get(index).mUnreadNum = unreadNum;
                 return true;
             }
         }
         return false;
     }    /**
      * Get unread number of application at the given position in the supported
      * shortcut list.
      *
      * @param index
      * @return
      */
     static synchronized int getUnreadNumberAt(int index) {
         if (index < 0 || index >= sUnreadSupportShortcutsNum) {
             return 0;
         }
         if (LauncherLog.DEBUG_UNREAD) {
             LauncherLog.d(TAG, "getUnreadNumberAt: index = " + index
                     + getUnreadSupportShortcutInfo());
         }
         return UNREAD_SUPPORT_SHORTCUTS.get(index).mUnreadNum;
     }    /**
      * Get unread number for the given component.
      *
      * @param component
      * @return
      */
     static int getUnreadNumberOfComponent(ComponentName component) {
         final int index = supportUnreadFeature(component);
         return getUnreadNumberAt(index);
     }    /**
      * Draw unread number for the given icon.
      *
      * @param canvas
      * @param icon
      * @return
      */
     static void drawUnreadEventIfNeed(Canvas canvas, View icon) {
         ItemInfo info = (ItemInfo)icon.getTag();
         if (info != null && info.unreadNum > 0) {
             Resources res = icon.getContext().getResources();            /// M: Meature sufficent width for unread text and background 
image
             Paint unreadTextNumberPaint = new Paint();
             unreadTextNumberPaint.setTextSize(res.getDimension(R.dimen.unread_text_number_size));
             unreadTextNumberPaint.setTypeface(Typeface.DEFAULT_BOLD);
             unreadTextNumberPaint.setColor(0xffffffff);
             unreadTextNumberPaint.setTextAlign(Paint.Align.CENTER);            Paint unreadTextPlusPaint = new Paint(unreadTextNumberPaint);
             unreadTextPlusPaint.setTextSize(res.getDimension(R.dimen.unread_text_plus_size));
            String unreadTextNumber;
             String unreadTextPlus = "+";
             Rect unreadTextNumberBounds = new Rect(0, 0, 0, 0);
             Rect unreadTextPlusBounds = new Rect(0, 0, 0, 0);
             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();
            /// M: Draw unread background image.
             NinePatchDrawable unreadBgNinePatchDrawable = (NinePatchDrawable) res.getDrawable
(R.drawable.ic_newevents_numberindication);
             int unreadBgWidth = unreadBgNinePatchDrawable.getIntrinsicWidth();
             int unreadBgHeight = unreadBgNinePatchDrawable.getIntrinsicHeight();
            int unreadMinWidth = (int) res.getDimension
(R.dimen.unread_minWidth);
             if (unreadBgWidth < unreadMinWidth) {
                 unreadBgWidth = unreadMinWidth;
             }
             int unreadTextMargin = (int) res.getDimension(R.dimen.unread_text_margin);
             if (unreadBgWidth < textWidth + unreadTextMargin) {
                 unreadBgWidth = textWidth + unreadTextMargin;
             }
             if (unreadBgHeight < textHeight) {
                 unreadBgHeight = textHeight;
             }
             Rect unreadBgBounds = new Rect(0, 0, unreadBgWidth, unreadBgHeight);
             unreadBgNinePatchDrawable.setBounds(unreadBgBounds);            int unreadMarginTop = 0;
             int unreadMarginRight = 0;
             if (info instanceof ShortcutInfo) {
                 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) {
                 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 {
                 canvas.drawText(unreadTextNumber,
                                 unreadBgWidth / 2,
                                 (unreadBgHeight + textHeight) / 2,
                                 unreadTextNumberPaint);
             }            canvas.restore();
         }
     }    public interface UnreadCallbacks {
         /**
          * Bind shortcuts and application icons with the given component, and
          * update folders unread which contains the given component.
          *
          * @param component
          * @param unreadNum
          */
         void bindComponentUnreadChanged(ComponentName component, int unreadNum);
        /**
          * Bind unread shortcut information if needed, this call back is used to
          * update shortcuts and folders when launcher first created.
          */
         void bindUnreadInfoIfNeeded();
     }
 }
 7.为桌面应用程序添加未读事件,4.2上用到的是ApplicationInfo和PageViewCellLayout,不过这里要改为AppInfo和AppsCustomizeCellLayout:    在
AppsCustomizePagedView.java中增加
 添加方法:
 +     /**
 +     * M: Update unread number of the given component in app customize paged view
 +     * with the given value, first find the icon, and then update the number.
 +     * NOTES: since maybe not all applications are added in the customize paged
 +     * view, we should update the apps info at the same time.
 +     *
 +     * @param component
 +     * @param unreadNum
 +     */
 +     public void updateAppsUnreadChanged(ComponentName component, int unreadNum) {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "updateAppsUnreadChanged: component = " + component
 +                    + ",unreadNum = " + unreadNum + ",mNumAppsPages = " + mNumAppsPages);
 +        }
 +        updateUnreadNumInAppInfo(component, unreadNum);
 +        for (int i = 0; i < mNumAppsPages; i++) {
 +            AppsCustomizeCellLayout cl = (AppsCustomizeCellLayout) getPageAt(i);
 +            if (cl == null) {
 +                return;
 +            }
 +            final int count = cl.getPageChildCount();
 +            View appIcon = null;
 +            AppInfo appInfo = null;
 +            for (int j = 0; j < count; j++) {
 +                appIcon = cl.getChildOnPageAt(j);
 +                appInfo = (AppInfo) appIcon.getTag();
 +                if (LauncherLog.DEBUG_UNREAD) {
 +                    LauncherLog.d(TAG, "updateAppsUnreadChanged: component = " + component
 +                            + ", appInfo = " + appInfo.componentName + ", appIcon = " + appIcon);
 +                }
 +                if (appInfo != null && appInfo.componentName.equals(component)) {
 +                    appInfo.unreadNum = unreadNum;
 +                    appIcon.invalidate();
 +                }
 +            }
 +        }
 +     }+     /**
 +     * M: Update unread number of all application info with data in UnreadLoader.
 +     */
 +    public void updateAppsUnread() {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "updateAppsUnreadChanged: mNumAppsPages = " + mNumAppsPages);
 +        }
 +
 +        updateUnreadNumInAppInfo(mApps);
 +        // Update apps which already shown in the customized pane.
 +        for (int i = 0; i < mNumAppsPages; i++) {
 +            AppsCustomizeCellLayout cl = (AppsCustomizeCellLayout) getPageAt(i);
 +            if (cl == null) {
 +                return;
 +            }
 +            final int count = cl.getPageChildCount();
 +            View appIcon = null;
 +            AppInfo appInfo = null;
 +            for (int j = 0; j < count; j++) {
 +                appIcon = cl.getChildOnPageAt(j);
 +                appInfo = (AppInfo) appIcon.getTag();
 +                appInfo.unreadNum = UnreadLoader.getUnreadNumberOfComponent(appInfo.componentName);
 +                appIcon.invalidate();
 +                if (LauncherLog.DEBUG_UNREAD) {
 +                    LauncherLog.d(TAG, "updateAppsUnreadChanged: i = " + i + ", appInfo = "
 +                            + appInfo.componentName + ", unreadNum = " + appInfo.unreadNum);
 +                }
 +            }
 +        }
 +    }+    /**
 +     * M: Update the unread number of the app info with given component.
 +     *
 +     * @param component
 +     * @param unreadNum
 +     */
 +    private void updateUnreadNumInAppInfo(ComponentName component, int unreadNum) {
 +        final int size = mApps.size();
 +        AppInfo appInfo = null;
 +        for (int i = 0; i < size; i++) {
 +            appInfo = mApps.get(i);
 +            if (appInfo.intent.getComponent().equals(component)) {
 +                appInfo.unreadNum = unreadNum;
 +            }
 +        }
 +    }+    /**
 +     * M: Update unread number of all application info with data in UnreadLoader.
 +     *
 +     * @param apps
 +     */
 +    public static void updateUnreadNumInAppInfo(final ArrayList<AppInfo> apps) {
 +        final int size = apps.size();
 +        AppInfo appInfo = null;
 +        for (int i = 0; i < size; i++) {
 +            appInfo = apps.get(i);
 +            appInfo.unreadNum = UnreadLoader.getUnreadNumberOfComponent(appInfo.componentName);
 +        }
 +    }8.为文件夹添加未读事件
 Folder.java类
 +   /**
 +     * M: Update unread number of the content shortcut.
 +     */
 +    public void updateContentUnreadNum() {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "Folder updateContentUnreadNum: mInfo = " + mInfo);
 +        }
 +        final int countX = mContent.getCountX();
 +        final int countY = mContent.getCountY();
 +        for (int j = 0; j < countY; j++) {
 +            for (int i = 0; i < countX; i++) {
 +                BubbleTextView shortcut = (BubbleTextView) mContent.getChildAt(i, j);
 +                if (shortcut != null) {
 +                    shortcut.invalidate();
 +                }
 +            }
 +        }
 +    }9.定义未读变量:ItemInfo.java类中
 +    /**
 +     * M: The unread num of the item.
 +     */
 +    int unreadNum = 0;
 然后在构造函数中给它初始化:
 +        unreadNum = info.unreadNum;
 在toString()方法中增加 该变量+ " unreadNum= " + unreadNum + ")";
 其次在ShortcutInfo.java类的toString方法中也增加该变量。 10.在Launcher.java类中调用写的方法:
 首先在实现类中增加implements UnreadLoader.UnreadCallbacks 。。。
 private UnreadLoader mUnreadLoader;//定义UnreadLoader对象
 在onCreate方法中添加
 +        /// M: added for unread feature, load and bind unread info.
 +        if (FeatureOption.XXX_LAUNCHER_UNREAD_SUPPORT) {//不同平台这个字符串可能不一样,XXX是平台名,这个字符串之后也一样的换成自己的就好了
 +            mUnreadLoader = app.getUnreadLoader();
 +            mUnreadLoader.loadAndInitUnreadShortcuts();
 +        }
 增加几个方法:
 +/**
 +     * M: Bind component unread information in workspace and all apps list.
 +     *
 +     * @param component the component name of the app.
 +     * @param unreadNum the number of the unread message.
 +     */
 +    public void bindComponentUnreadChanged(final ComponentName component, final int unreadNum) {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "bindComponentUnreadChanged: component = " + component
 +                    + ", unreadNum = " + unreadNum + ", this = " + this);
 +        }
 +        // Post to message queue to avoid possible ANR.
 +        mHandler.post(new Runnable() {
 +            public void run() {
 +                final long start = System.currentTimeMillis();
 +                if (LauncherLog.DEBUG_PERFORMANCE) {
 +                    LauncherLog.d(TAG, "bindComponentUnreadChanged begin: component = " + component
 +                            + ", unreadNum = " + unreadNum + ", start = " + start);
 +                }
 +                if (mWorkspace != null) {
 +                    mWorkspace.updateComponentUnreadChanged(component, unreadNum);
 +                }
 +
 +                if (mAppsCustomizeContent != null) {
 +                    mAppsCustomizeContent.updateAppsUnreadChanged(component, unreadNum);
 +                }
 +                if (LauncherLog.DEBUG_PERFORMANCE) {
 +                    LauncherLog.d(TAG, "bindComponentUnreadChanged end: current time = "
 +                            + System.currentTimeMillis() + ", time used = "
 +                            + (System.currentTimeMillis() - start));
 +                }
 +            }
 +        });
 +    }+   /**
 +     * M: Bind shortcuts unread number if binding process has finished.
 +     */
 +    public void bindUnreadInfoIfNeeded() {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "bindUnreadInfoIfNeeded: mBindingWorkspaceFinished = "
 +                    + mBindingWorkspaceFinished + ", thread = " + Thread.currentThread());
 +        }
 +        if (mBindingWorkspaceFinished) {
 +            bindWorkspaceUnreadInfo();
 +        }
 +
 +        if (mBindingAppsFinished) {
 +            bindAppsUnreadInfo();
 +        }
 +        mUnreadLoadCompleted = true;
 +    }+    /**
 +     * M: Bind unread number to shortcuts with data in UnreadLoader.
 +     */
 +    private void bindWorkspaceUnreadInfo() {
 +        mHandler.post(new Runnable() {
 +            public void run() {
 +                final long start = System.currentTimeMillis();
 +                if (LauncherLog.DEBUG_PERFORMANCE) {
 +                    LauncherLog.d(TAG, "bindWorkspaceUnreadInfo begin: start = " + start);
 +                }
 +                if (mWorkspace != null) {
 +                    mWorkspace.updateShortcutsAndFoldersUnread();
 +                }
 +                if (LauncherLog.DEBUG_PERFORMANCE) {
 +                    LauncherLog.d(TAG, "bindWorkspaceUnreadInfo end: current time = "
 +                            + System.currentTimeMillis() + ",time used = "
 +                            + (System.currentTimeMillis() - start));
 +                }
 +            }
 +        });
 +    }+    /**
 +     * M: Bind unread number to shortcuts with data in UnreadLoader.
 +     */
 +    private void bindAppsUnreadInfo() {
 +        mHandler.post(new Runnable() {
 +            public void run() {
 +                final long start = System.currentTimeMillis();
 +                if (LauncherLog.DEBUG_PERFORMANCE) {
 +                    LauncherLog.d(TAG, "bindAppsUnreadInfo begin: start = " + start);
 +                }
 +                if (mAppsCustomizeContent != null) {
 +                    mAppsCustomizeContent.updateAppsUnread();
 +                }
 +                if (LauncherLog.DEBUG_PERFORMANCE) {
 +                    LauncherLog.d(TAG, "bindAppsUnreadInfo end: current time = "
 +                            + System.currentTimeMillis() + ",time used = "
 +                            + (System.currentTimeMillis() - start));
 +                }
 +            }
 +        });
 +    }
 +11.接下来在LauncherAppState.java中添加一些方法,主要是注册广播,4.2上没这个
类,是在LauncherApplication.java中添加,这是4.4上新增的,基本上代替了
LauncherApplication.java
 首先导入FeatureOption该类,这个各个平台路径可能不一样,所以自己去找吧
 +     /// M: added for unread feature.
 +    private UnreadLoader mUnreadLoader; //定义对象在相应的地方注册广播
 +         /// M: register unread broadcast.
 +        if (FeatureOption.XXX_LAUNCHER_UNREAD_SUPPORT) {
 +            mUnreadLoader = new UnreadLoader(sContext);
 +            // Register unread change broadcast.
 +            filter = new IntentFilter();
 +            filter.addAction(Intent.XXX_ACTION_UNREAD_CHANGED);
 +            sContext.registerReceiver(mUnreadLoader, filter);
 +            LauncherLog.d(TAG, "register unread broadcast successfully");
 +        }
 同时在相应的地方注销广播
 +        /// M: added for unread feature, unregister unread receiver.
 +        if (FeatureOption.XXX_LAUNCHER_UNREAD_SUPPORT) {
 +            sContext.unregisterReceiver(mUnreadLoader);
 +        }
 在setLauncher方法中初始化未读事件
  /// M: added for unread feature, initialize unread loader.
         if (FeatureOption.XXX_LAUNCHER_UNREAD_SUPPORT) {
             mUnreadLoader.initialize(launcher);
         }
 增加一个方法:
 +      /**
 +     * M: Get unread loader, added for unread feature.
 +     */
 +    public UnreadLoader getUnreadLoader() {
 +        return mUnreadLoader;
 +    }
 13.Workspace.java类中增加方法:
 +     /**
 +     * M: Update unread number of shortcuts and folders in workspace and hotseat.
 +     */
 +    public void updateShortcutsAndFoldersUnread() {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "updateShortcutsAndFolderUnread: this = " + this);
 +        }
 +        final ArrayList<ShortcutAndWidgetContainer> childrenLayouts = getAllShortcutAndWidgetContainers();
 +        int childCount = 0;
 +        View view = null;
 +        Object tag = null;
 +        for (ShortcutAndWidgetContainer layout : childrenLayouts) {
 +            childCount = layout.getChildCount();
 +            for (int j = 0; j < childCount; j++) {
 +                view = layout.getChildAt(j);
 +                tag = view.getTag();
 +                if (LauncherLog.DEBUG_UNREAD) {
 +                    LauncherLog.d(TAG, "updateShortcutsAndFoldersUnread: tag = " + tag + ", j = "
 +                            + j + ", view = " + view);
 +                }
 +                if (tag instanceof ShortcutInfo) {
 +                    final ShortcutInfo info = (ShortcutInfo) tag;
 +                    final Intent intent = info.intent;
 +                    final ComponentName componentName = intent.getComponent();
 +                    info.unreadNum = MTKUnreadLoader.getUnreadNumberOfComponent(componentName);
 +                    ((BubbleTextView) view).invalidate();
 +                } else if (tag instanceof FolderInfo) {
 +                    ((FolderIcon) view).updateFolderUnreadNum();
 +                    ((FolderIcon) view).invalidate();
 +                }
 +            }
 +        }
 +    }+    /**
 +     * M: Update unread number of shortcuts and folders in workspace and hotseat
 +     * with the given component.
 +     *
 +     * @param component
 +     * @param unreadNum
 +     */
 +    public void updateComponentUnreadChanged(ComponentName component, int unreadNum) {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "updateComponentUnreadChanged: component = " + component
 +                    + ", unreadNum = " + unreadNum);
 +        }
 +        final ArrayList<ShortcutAndWidgetContainer> childrenLayouts = getAllShortcutAndWidgetContainers();
 +        int childCount = 0;
 +        View view = null;
 +        Object tag = null;
 +        for (ShortcutAndWidgetContainer layout : childrenLayouts) {
 +            childCount = layout.getChildCount();
 +            for (int j = 0; j < childCount; j++) {
 +                view = layout.getChildAt(j);
 +                tag = view.getTag();
 +                if (LauncherLog.DEBUG_UNREAD) {
 +                    LauncherLog.d(TAG, "updateComponentUnreadChanged: component = " + component
 +                            + ",tag = " + tag + ",j = " + j + ",view = " + view);
 +                }
 +                if (tag instanceof ShortcutInfo) {
 +                    final ShortcutInfo info = (ShortcutInfo) tag;
 +                    final Intent intent = info.intent;
 +                    final ComponentName componentName = intent.getComponent();
 +                    if (LauncherLog.DEBUG_UNREAD) {
 +                        LauncherLog.d(TAG, "updateComponentUnreadChanged 2: find component = "
 +                                + component + ",intent = " + intent + ",componentName = " + componentName);
 +                    }
 +                    if (componentName != null && componentName.equals(component)) {
 +                        LauncherLog.d(TAG, "updateComponentUnreadChanged 1: find component = "
 +                                + component + ",tag = " + tag + ",j = " + j + ",cellX = "
 +                                + info.cellX + ",cellY = " + info.cellY);
 +                        info.unreadNum = unreadNum;
 +                        ((BubbleTextView) view).invalidate();
 +                    }
 +                } else if (tag instanceof FolderInfo) {
 +                    ((FolderIcon) view).updateFolderUnreadNum(component, unreadNum);
 +                    ((FolderIcon) view).invalidate();
 +                }
 +            }
 +        }
 +        /// M: Update shortcut within folder if open folder exists.
 +        Folder openFolder = getOpenFolder();
 +        if (openFolder != null) {
 +            openFolder.updateContentUnreadNum();
 +        }
 +    } 14.接下来就简单了,在相应的地方去画要显示的未读数字就好了
 1)首先是PagedViewIcon.java中,这个画的是APP右上角的。
 先导包
 +// M: Add for unread event feature.
 +import android.graphics.Canvas;
 +import android.graphics.drawable.Drawable;
 +import android.graphics.drawable.NinePatchDrawable;
 在其Draw()方法中最后调用:(记得加在最后哦,不让你画的东东被app图标遮住了)
 +         /// M: For feature unread draw.
 +        UnreadLoader.drawUnreadEventIfNeed(canvas, this);2)其次在BubbleTextView.java类中draw方法中的
 if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent))改条件中增加:
             /// M: Draw unread event number.
             UnreadLoader.drawUnreadEventIfNeed(canvas, this);
 在draw方法最后也增加
         /// M: Draw unread event number.
         UnreadLoader.drawUnreadEventIfNeed(canvas, this);3)然后在FolderIcon.java中也要画:
 在dispatchDraw方法的最后:
 +        /// M: Draw unread event number.
 +        UnreadLoader.drawUnreadEventIfNeed(canvas, this);在onAdd(ShortcutInfo item)方法中
 /// M: added for unread feature, when add a item to a folder, we need to update
         /// the unread num of the folder.
         final ComponentName componentName = item.intent.getComponent();
         updateFolderUnreadNum(componentName, item.unreadNum);在onRemove(ShortcutInfo item)方法中添加
 /// M: added for Unread feature, when remove a item from a folder, we need to update
         /// the unread num of the folder
         final ComponentName componentName = item.intent.getComponent();
         updateFolderUnreadNum(componentName, item.unreadNum);不过还得写两个方法:
 +    /**
 +     * M: Update the unread message number of the shortcut with the given value.
 +     *
 +     * @param unreadNum the number of the unread message.
 +     */
 +    public void setFolderUnreadNum(int unreadNum) {
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "setFolderUnreadNum: unreadNum = " + unreadNum + ", mInfo = " + mInfo
 +                    + ", this = " + this);
 +        }
 +
 +        if (unreadNum <= 0) {
 +            mInfo.unreadNum = 0;
 +        } else {
 +            mInfo.unreadNum = unreadNum;
 +        }
 +    }+    /**
 +     * M: Update unread number of the folder, the number is the total unread number
 +     * of all shortcuts in folder, duplicate shortcut will be only count once.
 +     */
 +    public void updateFolderUnreadNum() {
 +        final ArrayList<ShortcutInfo> contents = mInfo.contents;
 +        final int contentsCount = contents.size();
 +        int unreadNumTotal = 0;
 +        final ArrayList<ComponentName> components = new ArrayList<ComponentName>();
 +        ShortcutInfo shortcutInfo = null;
 +        ComponentName componentName = null;
 +        int unreadNum = 0;
 +        for (int i = 0; i < contentsCount; i++) {
 +            shortcutInfo = contents.get(i);
 +            componentName = shortcutInfo.intent.getComponent();
 +            unreadNum = MTKUnreadLoader.getUnreadNumberOfComponent(componentName);
 +            if (unreadNum > 0) {
 +                shortcutInfo.unreadNum = unreadNum;
 +                int j = 0;
 +                for (j = 0; j < components.size(); j++) {
 +                    if (componentName != null && componentName.equals(components.get(j))) {
 +                        break;
 +                    }
 +                }
 +                if (LauncherLog.DEBUG_UNREAD) {
 +                    LauncherLog.d(TAG, "updateFolderUnreadNum: unreadNumTotal = " + unreadNumTotal
 +                            + ", j = " + j + ", components.size() = " + components.size());
 +                }
 +                if (j >= components.size()) {
 +                    components.add(componentName);
 +                    unreadNumTotal += unreadNum;
 +                }
 +            }
 +        }
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "updateFolderUnreadNum 1 end: unreadNumTotal = " + unreadNumTotal);
 +        }
 +        setFolderUnreadNum(unreadNumTotal);
 +    }+    /**
 +     * M: Update the unread message of the shortcut with the given information.
 +     *
 +     * @param unreadNum the number of the unread message.
 +     */
 +    public void updateFolderUnreadNum(ComponentName component, int unreadNum) {
 +        final ArrayList<ShortcutInfo> contents = mInfo.contents;
 +        final int contentsCount = contents.size();
 +        int unreadNumTotal = 0;
 +        ShortcutInfo appInfo = null;
 +        ComponentName name = null;
 +        final ArrayList<ComponentName> components = new ArrayList<ComponentName>();
 +        for (int i = 0; i < contentsCount; i++) {
 +            appInfo = contents.get(i);
 +            name = appInfo.intent.getComponent();
 +            if (name != null && name.equals(component)) {
 +                appInfo.unreadNum = unreadNum;
 +            }
 +            if (appInfo.unreadNum > 0) {
 +                int j = 0;
 +                for (j = 0; j < components.size(); j++) {
 +                    if (name != null && name.equals(components.get(j))) {
 +                        break;
 +                    }
 +                }
 +                if (LauncherLog.DEBUG_UNREAD) {
 +                    LauncherLog.d(TAG, "updateFolderUnreadNum: unreadNumTotal = " + unreadNumTotal
 +                            + ", j = " + j + ", components.size() = " + components.size());
 +                }
 +                if (j >= components.size()) {
 +                    components.add(name);
 +                    unreadNumTotal += appInfo.unreadNum;
 +                }
 +            }
 +        }
 +        if (LauncherLog.DEBUG_UNREAD) {
 +            LauncherLog.d(TAG, "updateFolderUnreadNum 2 end: unreadNumTotal = " + unreadNumTotal);
 +        }
 +        setFolderUnreadNum(unreadNumTotal);
 +    }
 +
 +    /**
 +     * M: Reset the value of the variable of sStaticValuesDirty.
 +     */
 +    public static void resetValuesDirty() {
 +        sStaticValuesDirty = true;
 +    }

唉终于是添加完了,好多内容啊,自己做的时候没发现,原理添加了这么多东西,难怪

花了我两天时间。接下来编译就好了,希望各位能一次通过,我当初可是出了七十多个