如何在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.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<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;
+ }
唉终于是添加完了,好多内容啊,自己做的时候没发现,原理添加了这么多东西,难怪
花了我两天时间。接下来编译就好了,希望各位能一次通过,我当初可是出了七十多个
errors呢!