Android MTK N 平台上如何在桌面上添加未接来电和未接信息数字角标

来源:互联网 发布:梦三国2mac版本 编辑:程序博客网 时间:2024/06/08 04:48

本篇博客我们来实现在桌面上添加未接来电和未接信息数字角标的功能。

想要实现这个功能,我们需要监听到未接来电/未接短信的变化,同时获取到未接来电/未接短信的数量,当监听到变化时对对应的图标进行重绘,在图标左上角添加上对应的角标。


未接短信

我们可以通过接收 Intent.ACTION_UNREAD_CHANGED 这个广播 Action 来监听未接短信数量的变化,同时通过 Intent.EXTRA_UNREAD_NUMBER 来获取未接短信数量。

未接来电

我们可以通过 ContentObserver 观察 CallLog.Calls.CONTENT_URI 这个 URI,同时根据这个 URI 来获取未接来电数量。


接下来我们看下代码:首先要在 AndroidManifest.xml 中添加对应的权限。

<uses-permission android:name="android.permission.READ_CALL_LOG"/>

然后我们来看最重要的 Launcher.java:

public class Launcher extends Activity        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,                   View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener {    ......    //add by chenmj    private BroadcastReceiver mUnreadSmsReceiver;    private ContentObserver mUnreadPhoneContentObserver;    private static final int REQUEST_CODE_CALL_LOG = 111;    //end    ......     @Override    protected void onCreate(Bundle savedInstanceState) {         ......        //add by chenmj        mUnreadSmsReceiver = new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                int unreadNumber = intent.getIntExtra(Intent.EXTRA_UNREAD_NUMBER, -1);                mIconCache.setUnreadSmsNumber(unreadNumber);            }        };        IntentFilter unreadFilter = new IntentFilter();        unreadFilter.addAction(Intent.ACTION_UNREAD_CHANGED);        registerReceiver(mUnreadSmsReceiver, unreadFilter);        mUnreadPhoneContentObserver = new ContentObserver(null) {            @Override            public void onChange(boolean selfChange, Uri uri) {                mIconCache.setUnreadPhoneNumber(getUnreceivedCallCount());                super.onChange(selfChange);            }        };        if (checkSelfPermission(Manifest.permission.READ_CALL_LOG)                 != PackageManager.PERMISSION_GRANTED) {            requestPermissions(new String[] {Manifest.permission.READ_CALL_LOG},                    REQUEST_CODE_CALL_LOG);        }else {            mIconCache.setUnreadPhoneNumber(getUnreceivedCallCount());            getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI,                    true, mUnreadPhoneContentObserver);        }        //end         ......    }    ......    //add by chenmj    public int getUnreceivedCallCount() {        ContentResolver localContentResolver = getContentResolver();        Uri localUri = CallLog.Calls.CONTENT_URI;        String[] arrayOfString = new String[1];        arrayOfString[0] = "_id";        Cursor localCursor = localContentResolver.query(localUri, arrayOfString, "type=3 and new<>0", null, null);        int unreadNumber;        if (localCursor == null) {            return -1;        } else {            try {                unreadNumber = localCursor.getCount();                localCursor.close();            } finally {                localCursor.close();            }        }        return unreadNumber;    }    //end     ......    public void onRequestPermissionsResult(int requestCode, String[] permissions,            int[] grantResults) {         ......        //add by chenmj        if(REQUEST_CODE_CALL_LOG == requestCode) {            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {                mIconCache.setUnreadPhoneNumber(getUnreceivedCallCount());                getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI,                    true, mUnreadPhoneContentObserver);            }        }        //end     ......    }     ......    @Override    public void onDestroy() {         ......        //add by chenmj        if(mUnreadSmsReceiver != null) {            unregisterReceiver(mUnreadSmsReceiver);        }        if(mUnreadPhoneContentObserver != null) {            getContentResolver().unregisterContentObserver(mUnreadPhoneContentObserver);        }        //end         ......    }

在 Launcher.java 的 onCreate() 方法中,我对 Intent.ACTION_UNREAD_CHANGED 广播进行了注册,以及对 CallLog.Calls.CONTENT_URI URI进行了内容监听,当对应的内容发生变化时会分别从 Intent.EXTRA_UNREAD_NUMBER 和 CallLog.Calls.CONTENT_URI 中获取未读信息/未接电话数量,并调用在 IconCache 中新添加的方法 setUnreadSmsNumber/setUnreadPhoneNumber 对未读信息/未接电话数量进行更新,并通知对应的图标进行刷新。上面的代码包含了运行时权限等逻辑,但是都比较简单且不说本篇的重点,就略过不说了。

我们接下来看看 IconCache.java 的代码。

public class IconCache {    //add by chenmj 20171024 add startreadSmsNumber = -1;    private int mUnreadPhoneNumber = -1;    private int mUnreadSmsNumber = -1;    //end    ......private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,            UserHandleCompat user, boolean usePackageIcon, boolean useLowResIcon) {        ......       //add by chenmj       if("com.android.mms".equals(componentName.getPackageName())) {           entry.icon = addUnreadInfoFlag(entry.icon, mUnreadSmsNumber);       }       if("com.android.dialer".equals(componentName.getPackageName())) {           entry.icon = addUnreadInfoFlag(entry.icon, mUnreadPhoneNumber);       }       //end     return entry;     }    ......    //add by chenmj    private Bitmap addUnreadInfoFlag(Bitmap orgBitmap, int unreadNumber) {        if(unreadNumber < 1) {            return orgBitmap;        }        Paint paint = new Paint();        paint.setAntiAlias(true);        paint.setTextSize(18);        paint.setTextAlign(Paint.Align.CENTER);        paint.setColor(Color.RED);        Bitmap bitmap = orgBitmap.copy(Bitmap.Config.ARGB_8888, true);        Canvas canvas = new Canvas(bitmap);        canvas.drawCircle(bitmap.getWidth() / 5,                bitmap.getHeight() / 5, bitmap.getHeight() / 8, paint);        String unreadNumberText = String.valueOf(unreadNumber);        Rect textRect = new Rect();        paint.getTextBounds(unreadNumberText, 0, unreadNumberText.length(), textRect);        paint.setColor(Color.WHITE);        canvas.drawText(unreadNumberText,                bitmap.getWidth() / 5,                bitmap.getHeight() / 5 + textRect.height() / 2, paint);        return bitmap;    }    public void setUnreadSmsNumber(int unreadNumber) {        if(mUnreadSmsNumber == unreadNumber) {            return;        }        mUnreadSmsNumber = unreadNumber;        LauncherAppState.getInstance().getModel()                .enqueuePackageUpdated("com.android.mms");    }    public void setUnreadPhoneNumber(int unreadNumber) {        if(mUnreadPhoneNumber == unreadNumber) {            return;        }        mUnreadPhoneNumber = unreadNumber;        LauncherAppState.getInstance().getModel()                .enqueuePackageUpdated("com.android.dialer");    }    //end     ......

setUnreadSmsNumber 和 setUnreadPhoneNumber 方法的逻辑基本一致,都是将未读/未接数量保存起来,然后通过调用 LauncherModel 的 enqueuePackageUpdated 方法通知对应的图标进行刷新。需要注意的是, enqueuePackageUpdated 方法是在 LauncherModel 中新添加的方法,如下:

    //add by chenmj    public void enqueuePackageUpdated(String packageName) {        enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,                 new String[] { packageName }, UserHandleCompat.myUserHandle()));    }    //end

IconCache.java 的绘制入口有多个,但是都会执行到 CacheLocked() 这个方法,因此我们就在这个方法末尾进行判断。如果图标的包名是短信或者电话的包名,我们就通过 addUnreadInfoFlag() 方法对原有图标进行修饰,在其左上角添加上红底白字的角标。


就这样,添加未接来电和未接短信数字角标的功能就完成了。如有错漏,欢迎矫正。

阅读全文
0 0