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

如何在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
内容如下:
+
+
+
+    +        launcher:unreadPackageName="com.android.dialer"
+        launcher:unreadClassName="com.android.dialer.DialtactsActivity"
+        launcher:unreadType="0"
+        launcher:unreadKey="com_android_contacts_unread"
+     />
+     +        launcher:unreadPackageName="com.android.mms"
+        launcher:unreadClassName="com.android.mms.ui.BootActivity"
+        launcher:unreadType="0"
+        launcher:unreadKey="com_android_mms_unread"
+     />
+     +        launcher:unreadPackageName="com.android.email"
+        launcher:unreadClassName="com.android.email.activity.Welcome"
+        launcher:unreadType="0"
+        launcher:unreadKey="com_android_email_unread"
+     />
+     +        launcher:unreadPackageName="com.android.calendar"
+        launcher:unreadClassName="com.android.calendar.AllInOneActivity"
+        launcher:unreadType="0"
+        launcher:unreadKey="com_android_calendar_unread"
+     />
+     +        launcher:unreadPackageName="com.orangelabs.rcs"
+       

launcher:unreadClassName="com.mediatek.rcse.activities.ChatMainActivity"
+        launcher:unreadType="0"
+        launcher:unreadKey="com_android_rcse_unread"
+    />
+    +        launcher:unreadPackageName="com.android.cellbroadcastreceiver"
+       

launcher:unreadClassName="com.android.cellbroadcastreceiver.CellBroadcastLis

tActivity"
+        launcher:unreadType="0"
+        launcher:unreadKey="com_android_calendar_unread"
+    />
+    +        launcher:unreadPackageName="com.mediatek.cellbroadcastreceiver"
+       

launcher:unreadClassName="com.mediatek.cellbroadcastreceiver.CellBroadcastLi

stActivity"
+        launcher:unreadType="0"
+        launcher:unreadKey="com_mediatek_cellbroadcastreceiver_unread"
+    />
+

3.添加几种需要用到而之前没有的权限:

b/packages/apps/Launcher3/AndroidManifest.xml


+   

android:name="android.permission.ADVANCED_WIDGET_API"/>
+   
+   
+   

4.定义要用的字符串:b/packages/apps/Launcher3/res/values/attrs.xml
+    
+   
+        
+       
+       
+       
+   

5.定义显示的数字大小尺寸,这个可以自己修改到满意,这个是四行五列排列的

1080*1920屏幕大小的尺寸。
b/packages/apps/Launcher3/res/values/dimens.xml
+  
+    20dp
+    16dp
+    8dp
+    16dp
+    14dp
+    16dp
+    16dp
+    20dp
+    16dp
+    8dp
+    14sp
+    10sp
6.接下来就是写一个类了,这里命名为UnreadLoader.java:
b/packages/apps/Launcher3/src/com/android/launcher3/UnreadLoader.java

package 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

UNREAD_SUPPORT_SHORTCUTS = new ArrayList();

    private static int sUnreadSupportShortcutsNum = 0;
    private static final Object LOG_LOCK = new Object();

    private Context mContext;

    private WeakReference 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(callbacks);
        if (LauncherLog.DEBUG_UNREAD) {
            LauncherLog.d(TAG, "initialize: callbacks = " + callbacks + ",

mCallbacks = " + mCallbacks);
        }
    }

    /**
     * Load and initialize unread shortcuts.
     *
     * @param context
     */
    void loadAndInitUnreadShortcuts() {
        new AsyncTask() {
            @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

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 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 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 contents = mInfo.contents;
+        final int contentsCount = contents.size();
+        int unreadNumTotal = 0;
+        final ArrayList components = new

ArrayList();
+        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 contents = mInfo.contents;
+        final int contentsCount = contents.size();
+        int unreadNumTotal = 0;
+        ShortcutInfo appInfo = null;
+        ComponentName name = null;
+        final ArrayList components = new

ArrayList();
+        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;
+    }

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

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

errors呢!

你可能感兴趣的:(android开发)