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

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

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


未接短信

我们可以通过接收 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() 方法对原有图标进行修饰,在其左上角添加上红底白字的角标。


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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值