从MTK里面提取出来的图标未读提示角标功能:
创建文件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.PaintFlagsDrawFilter;
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.Log;
import android.util.Xml;
import android.view.View;
import com.android.internal.util.XmlUtils;
import com.android.launcher3.AppInfo;
import com.android.launcher3.FolderInfo;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
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 {
/*******************tangxuankai add start 2015.12.8********************/
/** M:
* Broadcast Action: action for NotificationPlus feature.
* The broadcat is sent to trigger showing transient statusbar.
* @hide
*/
public static final String MTK_ACTION_REQUEST_TRANSIENT_STATUSBAR = "com.mediatek.action.REQUEST_TRANSIENT_STATUSBAR";
/**
* M:
* Broadcast Action: action used for launcher unread number feature.
* The broadcat is sent when the unread number of application changes.
* @hide
*/
public static final String MTK_ACTION_UNREAD_CHANGED = "com.mediatek.action.UNREAD_CHANGED";
/**
* M:
* Extra used to indicate the unread number of which component changes.
* @hide
*/
public static final String MTK_EXTRA_UNREAD_COMPONENT = "com.mediatek.intent.extra.UNREAD_COMPONENT";
/**
* M:
* The number of unread messages.
* @hide
*/
public static final String MTK_EXTRA_UNREAD_NUMBER = "com.mediatek.intent.extra.UNREAD_NUMBER";
/*******************tangxuankai add end 2015.12.8********************/
private static final boolean LauncherLog_DEBUG = false;
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 (MTK_ACTION_UNREAD_CHANGED.equals(action)) {
final ComponentName componentName = (ComponentName) intent
.getExtra(MTK_EXTRA_UNREAD_COMPONENT);
final int unreadNum = intent.getIntExtra(MTK_EXTRA_UNREAD_NUMBER, -1);
// if (LauncherLog_DEBUG) {
// Log.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) {
Log.d(TAG, "initialize: callbacks = " + callbacks + ", mCallbacks = " + mCallbacks);
}
}
/**
* Load and initialize unread shortcuts.
*
* @param context
*/
public 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) {
Log.d(TAG, "initUnreadNumberFromSystem: key = " + shortcut.mKey
+ ", unreadNum = " + shortcut.mUnreadNum);
}
} catch (android.provider.Settings.SettingNotFoundException e) {
Log.e(TAG, "initUnreadNumberFromSystem SettingNotFoundException key = "
+ shortcut.mKey + ", e = " + e.getMessage());
}
}
if (LauncherLog_DEBUG) {
Log.d(TAG, "initUnreadNumberFromSystem end:" + getUnreadSupportShortcutInfo());
}
}
private void loadUnreadSupportShortcuts() {
long start = System.currentTimeMillis();
if (LauncherLog_DEBUG) {
Log.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) {
Log.w(TAG, "Got XmlPullParserException while parsing unread shortcuts.", e);
} catch (IOException e) {
Log.w(TAG, "Got IOException while parsing unread shortcuts.", e);
}
sUnreadSupportShortcutsNum = UNREAD_SUPPORT_SHORTCUTS.size();
if (LauncherLog_DEBUG) {
Log.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) {
Log.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) {
Log.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) {
Log.d(TAG, "getUnreadNumberAt: index = " + index
+ getUnreadSupportShortcutInfo());
}
return UNREAD_SUPPORT_SHORTCUTS.get(index).mUnreadNum;
}
/**
* Get unread number for the given component.
*
* @param component
* @return
*/
public 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
*/
public 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));
Typeface tpf45 = Typeface.create("qh45", 0);
unreadTextNumberPaint.setTypeface(tpf45);
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 AppInfo) {
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();
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
if (info.unreadNum > Launcher.MAX_UNREAD_COUNT) {
canvas.drawText(unreadTextNumber,
(unreadBgWidth - unreadTextPlusBounds.width()) / 2,
(unreadBgHeight + textHeight) / 2 - 6,
unreadTextNumberPaint);
canvas.drawText(unreadTextPlus,
(unreadBgWidth + unreadTextNumberBounds.width()) / 2,
(unreadBgHeight + textHeight) / 2 + fontMetrics.ascent / 2,
unreadTextPlusPaint);
} else {
canvas.drawText(unreadTextNumber,
unreadBgWidth / 2,
(unreadBgHeight + textHeight) / 2 - 6,
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();
}
}
创建文件unread_support_shortcuts.xml, 这个文件是配置需要支持未读提示应用的
<?xml version="1.0" encoding="UTF-8"?>
<unreadshortcuts xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3">
<shortcut
launcher:unreadPackageName="com.android.dialer"
launcher:unreadClassName="com.android.dialer.DialtactsActivity"
launcher:unreadType="0"
launcher:unreadKey="com_android_contacts_mtk_unread"
/>
<shortcut
launcher:unreadPackageName="com.android.mms"
launcher:unreadClassName="com.android.mms.ui.MainTabActivity"
launcher:unreadType="0"
launcher:unreadKey="com_android_mms_mtk_unread"
/>
<shortcut
launcher:unreadPackageName="com.android.email"
launcher:unreadClassName="com.android.email.activity.Welcome"
launcher:unreadType="0"
launcher:unreadKey="com_android_email_mtk_unread"
/>
</unreadshortcuts>
LauncherAppState.java增加一个mUnreadLoader变量
private UnreadLoader mUnreadLoader;
在构造函数里初始化mUnreadLoader, 注册广播接收器
private LauncherAppState() {
/// M: register unread broadcast.
if (Launcher.LAUNCHER_UNREAD_SUPPORT) {
mUnreadLoader = new UnreadLoader(sContext);
// Register unread change broadcast.
IntentFilter unreadfilter = new IntentFilter();
unreadfilter.addAction(UnreadLoader.MTK_ACTION_UNREAD_CHANGED);
sContext.registerReceiver(mUnreadLoader, unreadfilter);
}
}
在onTerminate()函数里取消监听
public void onTerminate() {
sContext.unregisterReceiver(mModel);
/**************************tangxuankai add start 2015.12.11**************************************/
/// M: register unread broadcast.
if (Launcher.LAUNCHER_UNREAD_SUPPORT) {
sContext.unregisterReceiver(mUnreadLoader);
}
/**************************tangxuankai add end 2015.12.11**************************************/
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
launcherApps.removeOnAppsChangedCallback(mModel);
PackageInstallerCompat.getInstance(sContext).onStop();
}
在 setLauncher()函数里初始化
LauncherModel setLauncher(Launcher launcher) {
getLauncherProvider().setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
/********************tangxuankai add start 2015.12.11*********************/
if (Launcher.LAUNCHER_UNREAD_SUPPORT) {
mUnreadLoader.initialize(launcher);
}
/********************tangxuankai add end 2015.12.11*********************/
mAccessibilityDelegate = ((launcher != null) && Utilities.ATLEAST_LOLLIPOP) ?
new LauncherAccessibilityDelegate(launcher) : null;
return mModel;
}
最后添加一个公共函数供外部取得mUnreadLoader变量
public UnreadLoader getUnreadLoader() {
return mUnreadLoader;
}
Launcher.java继承UnreadLoader.UnreadCallbacks接口
public class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener ,
UnreadLoader.UnreadCallbacks{
private UnreadLoader mUnreadLoader;
public static final boolean LAUNCHER_UNREAD_SUPPORT = true;
}
在onCreate函数里初始化mUnreadLoader
protected void onCreate(Bundle savedInstanceState) {
…………………………
if (LAUNCHER_UNREAD_SUPPORT) {
mUnreadLoader = app.getUnreadLoader();
mUnreadLoader.loadAndInitUnreadShortcuts();
}
…………………………
}
增加下面几个函数,其中registerUnreadMMSObserver()在onCreate函数里注册短信、电话的未读消息监听器,在onDestroy里取消注册unregisterUnreadMMSObserver();
/**
* for unread msg
*/
private static void recordUnreadMessageNumberToSys(Context context, int unreadMsgNumber) {
android.provider.Settings.System.putInt(context.getContentResolver(),
"com_android_mms_mtk_unread", unreadMsgNumber);
}
private static void broadcastUnreadMessageNumber(Context context, int unreadMsgNumber) {
Intent intent = new Intent();
intent.setAction(UnreadLoader.MTK_ACTION_UNREAD_CHANGED);
intent.putExtra(UnreadLoader.MTK_EXTRA_UNREAD_NUMBER, unreadMsgNumber);
intent.putExtra(UnreadLoader.MTK_EXTRA_UNREAD_COMPONENT,
new ComponentName("com.android.mms", "com.android.mms.ui.MainTabActivity"));
context.sendBroadcast(intent);
recordUnreadMessageNumberToSys(context, unreadMsgNumber);
}
private static void broadcastUnreadPhoneNumber(Context context, int newCallsCount) {
Intent newIntent = new Intent(UnreadLoader.MTK_ACTION_UNREAD_CHANGED);
newIntent.putExtra(UnreadLoader.MTK_EXTRA_UNREAD_NUMBER, newCallsCount);
newIntent.putExtra(UnreadLoader.MTK_EXTRA_UNREAD_COMPONENT, new ComponentName("com.android.dialer",
"com.android.dialer.DialtactsActivity"));
context.sendBroadcast(newIntent);
android.provider.Settings.System.putInt(context.getContentResolver(), "com_android_contacts_mtk_unread", Integer
.valueOf(newCallsCount));
}
int oldSMSCount = -1;
private ContentObserver newMmsContentObserver = new ContentObserver(new Handler()) {
public void onChange(boolean selfChange) {
qeuryNewMMs();
}
};
int oldPhoneCount = -1;
private ContentObserver newPhoneContentObserver = new ContentObserver(new Handler()) {
public void onChange(boolean selfChange) {
qeuryNewPhoneCall();
}
};
private void registerUnreadMMSObserver() {
unregisterUnreadMMSObserver();
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, newMmsContentObserver);
getContentResolver().registerContentObserver(Uri.parse("content://mms-sms"), true, newMmsContentObserver);
registerUnreadPhoneSObserver();
}
private void registerUnreadPhoneSObserver() {
unregisterUnreadPhoneObserver();
getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, false, newPhoneContentObserver);
}
private synchronized void unregisterUnreadMMSObserver() {
try {
if (newMmsContentObserver != null) {
getContentResolver().unregisterContentObserver(newMmsContentObserver);
}
if (newMmsContentObserver != null) {
getContentResolver().unregisterContentObserver(newMmsContentObserver);
}
} catch (Exception e) {
Log.e(TAG, "unregisterObserver fail");
}
unregisterUnreadPhoneObserver();
}
private synchronized void unregisterUnreadPhoneObserver() {
try {
if (newPhoneContentObserver != null) {
getContentResolver().unregisterContentObserver(newPhoneContentObserver);
}
} catch (Exception e) {
Log.e(TAG, "unregisterUnreadPhoneObserver newPhoneContentObserver fail");
}
}
private void qeuryNewMMs() {
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
int result = -1;
try{
Cursor crSms = getContentResolver().query(Uri.parse("content://sms"), null, "type = 1 and read = 0", null, null);
if (crSms != null) {
result = crSms.getCount();
crSms.close();
}
Cursor crMms = getContentResolver().query(Uri.parse("content://mms/inbox"), null, "read = 0", null, null);
if (crMms != null) {
result = result + crMms.getCount();
crMms.close();
}
} catch (Exception e){
Log.d("txk", "getNewSmsCount Exception e = " + e.toString());
e.printStackTrace();
}
if (oldSMSCount != result) {
oldSMSCount = result;
broadcastUnreadMessageNumber(Launcher.this, result);
}
}
}.start();
}
private void qeuryNewPhoneCall() {
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
int result = -1;
try{
Cursor csr = getContentResolver().query(Calls.CONTENT_URI, null, "type = 3 and new = 1", null, null);
if (csr != null) {
result = csr.getCount();
csr.close();
}
} catch (Exception e){
Log.d("txk", "getMissPhoneCount Exception e = " + e.toString());
e.printStackTrace();
}
if (oldPhoneCount != result) {
oldPhoneCount = result;
broadcastUnreadPhoneNumber(Launcher.this, result);
}
}
}.start();
}
@Override
public void bindComponentUnreadChanged(final ComponentName component,
final int unreadNum) {
// TODO Auto-generated method stub
// Post to message queue to avoid possible ANR.
mHandler.post(new Runnable() {
public void run() {
final long start = System.currentTimeMillis();
if (mWorkspace != null) {
mWorkspace.updateComponentUnreadChanged(component, unreadNum);
}
//
// if (mAppsCustomizeContent != null) {
// mAppsCustomizeContent.updateAppsUnreadChanged(component, unreadNum);
// }
}
});
}
@Override
public void bindUnreadInfoIfNeeded() {
// TODO Auto-generated method stub
if (mBindingWorkspaceFinished) {
bindWorkspaceUnreadInfo();
}
if (mBindingAppsFinished) {
bindAppsUnreadInfo();
}
mUnreadLoadCompleted = true;
}
/**
* M: Bind unread number to shortcuts with data in MTKUnreadLoader.
*/
private void bindWorkspaceUnreadInfo() {
mHandler.post(new Runnable() {
public void run() {
final long start = System.currentTimeMillis();
if (mWorkspace != null) {
mWorkspace.updateShortcutsAndFoldersUnread();
}
}
});
}
/**
* M: Bind unread number to shortcuts with data in MTKUnreadLoader.
*/
private void bindAppsUnreadInfo() {
mHandler.post(new Runnable() {
public void run() {
final long start = System.currentTimeMillis();
if (mAppsView != null) {
mAppsView.updateAppsUnread();
}
}
});
}
itemInfo.java增加一个公共变量存储未读条数
public class ItemInfo {
……………………
public int unreadNum = 0; //tangxuankai add 2015.12.8
……………………
}
public void copyFrom(ItemInfo info) {
id = info.id;
cellX = info.cellX;
cellY = info.cellY;
spanX = info.spanX;
spanY = info.spanY;
rank = info.rank;
screenId = info.screenId;
itemType = info.itemType;
container = info.container;
user = info.user;
contentDescription = info.contentDescription;
unreadNum = info.unreadNum; //tangxuankai add 2015.12.8
}
workspace.java 增加两个函数
/**
* M: Update unread number of shortcuts and folders in workspace and hotseat.
*/
public void updateShortcutsAndFoldersUnread() {
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 (tag instanceof ShortcutInfo) {
final ShortcutInfo info = (ShortcutInfo) tag;
final Intent intent = info.intent;
final ComponentName componentName = intent.getComponent();
info.unreadNum = UnreadLoader.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) {
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 (tag instanceof ShortcutInfo) {
final ShortcutInfo info = (ShortcutInfo) tag;
final Intent intent = info.intent;
final ComponentName componentName = intent.getComponent();
if (componentName != null && componentName.equals(component)) {
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();
}
}
BubbleTextView.java
@Override
public void draw(Canvas canvas) {
if (!mCustomShadowsEnabled) {
// Draw the fast scroll focus bg if we have one
if (mFastScrollMode == FAST_SCROLL_FOCUS_MODE_DRAW_CIRCLE_BG &&
mFastScrollFocusFraction > 0f) {
DeviceProfile grid = mLauncher.getDeviceProfile();
int iconCenterX = getScrollX() + (getWidth() / 2);
int iconCenterY = getScrollY() + getPaddingTop() + (grid.iconSizePx / 2);
canvas.drawCircle(iconCenterX, iconCenterY,
mFastScrollFocusFraction * (getWidth() / 2), mFastScrollFocusBgPaint);
}
super.draw(canvas);
UnreadLoader.drawUnreadEventIfNeed(canvas, this); //tangxuankai add 2015.12.25
return;
}
final Drawable background = mBackground;
if (background != null) {
final int scrollX = getScrollX();
final int scrollY = getScrollY();
if (mBackgroundSizeChanged) {
background.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop());
mBackgroundSizeChanged = false;
}
if ((scrollX | scrollY) == 0) {
background.draw(canvas);
} else {
canvas.translate(scrollX, scrollY);
background.draw(canvas);
canvas.translate(-scrollX, -scrollY);
}
}
// If text is transparent, don't draw any shadow
if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent)) {
getPaint().clearShadowLayer();
super.draw(canvas);
UnreadLoader.drawUnreadEventIfNeed(canvas, this); //tangxuankai add 2015.12.09
return;
}
// We enhance the shadow by drawing the shadow twice
getPaint().setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
super.draw(canvas);
canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(),
getScrollX() + getWidth(),
getScrollY() + getHeight(), Region.Op.INTERSECT);
getPaint().setShadowLayer(SHADOW_SMALL_RADIUS, 0.0f, 0.0f, SHADOW_SMALL_COLOUR);
super.draw(canvas);
canvas.restore();
UnreadLoader.drawUnreadEventIfNeed(canvas, this); //tangxuankai add 2015.12.09
}
FolderIcon.java
protected void dispatchDraw(Canvas canvas) {
………………………………
UnreadLoader.drawUnreadEventIfNeed(canvas, this); //tangxuankai add 2015.12.09
}
增加几个函数
/************************tangxuankai add start 2015.12.09***************************/
/**
* 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 (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 = UnreadLoader.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 (j >= components.size()) {
components.add(componentName);
unreadNumTotal += unreadNum;
}
}
}
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 (j >= components.size()) {
components.add(name);
unreadNumTotal += appInfo.unreadNum;
}
}
}
setFolderUnreadNum(unreadNumTotal);
}
/**
* M: Reset the value of the variable of sStaticValuesDirty.
*/
public static void resetValuesDirty() {
sStaticValuesDirty = true;
}
/************************tangxuankai add end 2015.12.09***************************/
AllAppsContainerView.java 增加几个函数
/**********************************tangxuankai add 2015.12.11 start **********************************/
/**
* 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) {
updateUnreadNumInAppInfo(component, unreadNum);
if (mApps != null){
AppInfo appInfo = null;
List<AppInfo> appList = mApps.getApps();
for (int i = 0; i < appList.size(); i++) {
// final int count = cl.getPageChildCount();
// PagedViewIcon appIcon = null;
appInfo = appList.get(i);
if (appInfo != null && appInfo.componentName.equals(component)) {
appInfo.unreadNum = unreadNum;
// appIcon.invalidate();
}
}
}
}
/**
* M: Update unread number of all application info with data in MTKUnreadLoader.
*/
public void updateAppsUnread() {
if (mApps != null) {
updateUnreadNumInAppInfo(mApps.getApps());
}
}
/**
* 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.getApps().size();
List<AppInfo> appInfoList = null;
for (AppInfo appInfo : appInfoList) {
if (appInfo.intent.getComponent().equals(component)) {
appInfo.unreadNum = unreadNum;
}
}
}
/**
* M: Update unread number of all application info with data in MTKUnreadLoader.
*
* @param apps
*/
public static void updateUnreadNumInAppInfo(List<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);
}
}
/**********************************tangxuankai add 2015.12.11 end **********************************/