怎么在android4.4上添加未读信息,未接来电或日历等新事件图标提醒

前几天修改MTK8312平台遇到一个bug,就是来电,短信,邮件或者日历有新消息时,桌面图标没有提示有几条信息,方便用户进行查看,其实MTK平台中是有这方面接口定义的,下面就让我们来查看一下源码吧(此案例主要是针对dialer做详细说明,其他应用需要更新的话,只需要定义接口和发送广播即可).

1、MTK中未读消息intent的定义,方便后续发送广播

所在目录:

frameworks\base\core\java\android\content\Intent.java
添加相关代码如下:

 /**
     * 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";

2、查找未读信息并发送需要处理的广播所在位置

packages/apps/Calendar/src/com/mediatek/calendar/MTKUtils.java  //日历
packages/apps/Email/src/com/android/email/NotificationController.java //邮件
packages/providers/ContactsProvider/src/com/android/providers/contacts/CallLogProvider.java //电话
packages/providers/TelephonyProvider/src/com/android/providers/telephony/MmsSmsProvider.java //短信

这里以dialer为例,找到上述目录后,添加如下代码:

 public static final void notifyNewCallsCount(SQLiteDatabase db, Context context) {
        Cursor c = null;
        if (VvmUtils.isVvmEnabled()) {
            c = db.rawQuery("select count(_id) from calls where type in (3,4) AND new=1", null);
        } else {
            c = db.rawQuery("select count(_id) from calls where type=3 AND new=1", null);
        }

        int newCallsCount = 0;
        if (c != null) {
            if (c.moveToFirst()) {
                newCallsCount = c.getInt(0);
            }
            c.close();
        }

        LogUtils.i(TAG, "[notifyNewCallsCount] newCallsCount = " + newCallsCount);
        //send count=0 to clear the unread icon
        if (newCallsCount >= 0) {
            Intent newIntent = new Intent(Intent.MTK_ACTION_UNREAD_CHANGED);
            newIntent.putExtra(Intent.MTK_EXTRA_UNREAD_NUMBER, newCallsCount);
            newIntent.putExtra(Intent.MTK_EXTRA_UNREAD_COMPONENT, new ComponentName(Constants.CONTACTS_PACKAGE,
                    Constants.CONTACTS_DIALTACTS_ACTIVITY));
            context.sendBroadcast(newIntent);
            android.provider.Settings.System.putInt(context.getContentResolver(), Constants.CONTACTS_UNREAD_KEY, Integer
                    .valueOf(newCallsCount));
        }
    }
3、广播的接收,需要自己在Launcher中 定义一个广播类,extends BroadcastReceiver,目录如下:

packages\apps\Launcher3\src\com\android\launcher3\MTKUnreadLoader.java
重写广播方法如下:

 @Override
    public void onReceive(final Context context, final Intent intent) {
        final String action = intent.getAction();
        if (Intent.MTK_ACTION_UNREAD_CHANGED.equals(action)) {
            final ComponentName componentName = (ComponentName) intent
                    .getExtra(Intent.MTK_EXTRA_UNREAD_COMPONENT);
            final int unreadNum = intent.getIntExtra(Intent.MTK_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);
                        }
                    }
                }
            }
        }
    }
4、注册广播所在位置,这里通过代码中动态注册广播

所在目录:packages\apps\Launcher3\src\com\android\launcher3\LauncherApplication.java

注册代码如下,在onCreate方法中添加:

if (FeatureOption.MTK_LAUNCHER_UNREAD_SUPPORT) {
            mUnreadLoader = new MTKUnreadLoader(getApplicationContext());
            // Register unread change broadcast.
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.MTK_ACTION_UNREAD_CHANGED);
            registerReceiver(mUnreadLoader, filter);
        }

5、应用图标显示未读消息的的数字,通过在 MTKUnreadLoader.java中添加静态方法如下:

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 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();
            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();
        }
    }
7、定义未读消息所在的xml文件,这里支持电话,短信,邮件和日历

所在目录: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/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.BootActivity"
        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"
     />
     <shortcut
        launcher:unreadPackageName="com.android.calendar"
        launcher:unreadClassName="com.android.calendar.AllInOneActivity"
        launcher:unreadType="0"
        launcher:unreadKey="com_android_calendar_mtk_unread"
     />
     <shortcut
        launcher:unreadPackageName="com.orangelabs.rcs"
        launcher:unreadClassName="com.mediatek.rcse.activities.ChatMainActivity"
        launcher:unreadType="0"
        launcher:unreadKey="com_android_rcse_mtk_unread"
    />
    <shortcut
        launcher:unreadPackageName="com.android.cellbroadcastreceiver"
        launcher:unreadClassName="com.android.cellbroadcastreceiver.CellBroadcastListActivity"
        launcher:unreadType="0"
        launcher:unreadKey="com_android_calendar_mtk_unread"
    />
    <shortcut
        launcher:unreadPackageName="com.mediatek.cellbroadcastreceiver"
        launcher:unreadClassName="com.mediatek.cellbroadcastreceiver.CellBroadcastListActivity"
        launcher:unreadType="0"
		launcher:unreadKey="com_mediatek_cellbroadcastreceiver_mtk_unread"
    />
</unreadshortcuts>
8、事件的图标显示,可以根据尺寸,做一张.9图片,eg: ic_newevents_numberindication.9.png

9、MTKUnreadLoader.java中定义一些接口回调方法,供Launcher3实现和调用

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

10、 Launcher3.java实现 UnreadCallbacks 方法

 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 MTKUnreadLoader.
     */
    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 MTKUnreadLoader.
     */
    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、Workspace.java中进行icon更新的方法

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

注意事项:对于shortcut,folder 和hotseat,更新的代码可能不一样,最后都记得调用 MTKUnreadLoader中的drawUnreadEventIfNeed方法

具体:在各自的onDraw方法中添加MTKUnreadLoader.drawUnreadEventIfNeed(canvas,this).

eg:  FolderIcon.java在dispatchDraw()方法中添加

        BubbleTextView.java在draw()方法中添加



















你可能感兴趣的:(怎么在android4.4上添加未读信息,未接来电或日历等新事件图标提醒)