unread support

从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  **********************************/






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值