您的位置:首页 > 移动开发 > Android开发

Android Launcher界面未接来电和未读短信条数的显示

2014-05-23 15:49 483 查看
一 分析步骤和过程

我们需要实现的是当有一个未接来电和未读短信时,Launcher界面的Dialer和Msm的icon能够显示未读条数,其实和微信的差不多。里面有一个功能就是显示未读新闻的条数

步入正题,首先未接电话和未读短信都会插入都各自的数据库中,未读短信会插入到短信的数据库中,我们只需要监听数据库的变化,如果有未读短信插入数据库我们就更新Launcher界面的Msm的ICON来重新绘制ICON来显示所需要的东西。

1 首先我们监听各自的数据库,我们可以在Launcher的onCreate里做此操作代码如下分析:

private MissedCallContentObserver mMissedCallContentObserver;

private NewMmsContentObserver mNewMmsContentObserver

mMissedCallContentObserver = new MissedCallContentObserver(getApplicationContext(), new Handler());

getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, true, mMissedCallContentObserver);

mNewMmsContentObserver = new NewMmsContentObserver(getApplicationContext(), new Handler());

getContentResolver().registerContentObserver(Uri.parse("content://mms-sms/"), true, mNewMmsContentObserver ; );

我们完成注册后对应的onDestory里就有如下:

getContentResolver().unregisterContentObserver(mMissedCallContentObserver);

getContentResolver().unregisterContentObserver(mNewMmsContentObserver);

这个是监听未接来电数据库的变化具体看MissedCallContentObserver当数据库有数据变化是会执行对应的方法,这个监听者模式我就不详细介绍了,大家都是明白的也经常会用到此功能的具体实现如下:

public class MissedCallContentObserver extends ContentObserver {

public MissedCallContentObserver(Context context, Handler handler) {

super(handler);

}

@Override

public void onChange(boolean selfChange) {

mIconHandler.sendEmptyMessageDelayed(MSG_REFRESH_LAUNCHER, ICON_MSG_DELAYED);

}

}

这个是监听未接来电的方法,我们在看下未读短信的监听

public class NewMmsContentObserver extends ContentObserver{

public NewMmsContentObserver(Context context, Handler handler) {

super(handler);

}

@Override

public void onChange(boolean selfChange){

mIconHandler.sendEmptyMessageDelayed(MSG_REFRESH_LAUNCHER,ICON_MSG_DELAYED);

}

}

}

这两个类就实现了数据库的动态监听,当数据库有数据发生变化时,我们就这两个方法就会回调,我们就可以在onChange方法里做我们需要做的动作,更新ICON,更新为我们需要显示的样子,接下来我们开始分析onChange方法里的动作,我们在这个方法里利用Handler发送了一个message来执行更新Dialer和Msm的CION。

当然我们就要实现自己的Handler了具体实现如下:

private final static int MSG_REFRESH_LAUNCHER = 2000;

private final static int ICON_MSG_DELAYED = 2000;

private Handler mIconHandler = new Handler() {

public void handleMessage(Message msg) {

switch(msg.what) {

case MSG_REFRESH_LAUNCHER:

//mModel.startLoader(true, -1);

mModel.updateApp();

break;

}

};

};

当onChange方法触动后我们的Handler就能接受到消息,来完成更新,看看我们是如何更新的,Launcher里有很多更新界面的方法。我们这个开始用了 //mModel.startLoader(true, -1);这个方法会把launcher里所有的ICON全部更新,感觉这里有点不好,最后想到了一个好的办法,那就是只更新Dialer和Mms了,用的是mModel.updateApp();

这个方法是我们自己实现的看看源码

public void updateApp() {

enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, new String[] { "com.android.dialer", "com.android.mms" }));

}

其实这方法里调用的也是系统的方法,具体怎么实现完成的我们可以看看这个方法,此方法就不多介绍了,我们主要还是研究下这个功能的实现思路和方法。

当我们开始更新Dialer和MmS这两个iCON时,当然我们就要对这两个ICON做一些处理了

我们需要在PagedViewIcon类和BubbleTextView这两个类中对Dialer和Mms的ICON进行过滤来完成显示。

Launcher里面IconCache类是对每一个ICON的图片的绘制,我们就把Dialer和Mms的ICON图片做一些特殊的处理吧

我们先来看IconCache类里面的处理我们先来获取未接来电和未读短信的条数

public int getUnreadSmsCount() {

return findNewMmsCount(mContext) + findNewSmsCount(mContext);

}

这个方法是获取未读短信的总条数,里面为了过滤短信发送时回执报告

private int findNewSmsCount(Context ctx){

Cursor csr = null;

int newSmsCount = 0;

try {

// csr = mContext.getContentResolver().query(Uri.parse("content://sms"), null,"type = 1 and read = 0", null, null);

csr = mContext.getContentResolver().query(Uri.parse("content://sms/inbox"), null, "read = 0", null, null);

newSmsCount = csr.getCount();

} catch (Exception e) {

e.printStackTrace();

} finally {

csr.close();

}

return newSmsCount;

}

private int findNewMmsCount(Context ctx){

Cursor csr = null;

int newMmsCount = 0;

try {

csr = mContext.getContentResolver().query(Uri.parse("content://mms/inbox"), null, "read = 0 and m_type != 134", null, null);

newMmsCount = csr.getCount();

} catch (Exception e) {

e.printStackTrace();

} finally {

csr.close();

}

return newMmsCount;

}

再来看未接来电

public int getUnreceivedCallCount() {

ContentResolver localContentResolver = mContext.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 j;

if (localCursor == null) {

return -1;

} else {

try {

j = localCursor.getCount();

localCursor.close();

} finally {

localCursor.close();

}

}

return j;

}

这两个方法来完成未接来电和未读短信条数的获取。

我们来看看PagedViewIcon是如何来过滤和更新ICON 的

if (name != null) {

if ("com.android.dialer".equals(name.getPackageName())

&& "com.android.dialer.DialtactsActivity".equals(name.getClassName())) {

int unreceivedCall = iconCache.getUnreceivedCallCount();

mIcon = iconCache.createNotifyImage(unreceivedCall, mIcon, getPaint(), name.getPackageName());

name.getPackageName());

} else if ("com.android.mms".equals(name.getPackageName())

&& "com.android.mms.ui.ModeChooser".equals(name.getClassName())) {

int unreadSmsCount = iconCache.getUnreadSmsCount();

mIcon = iconCache.createNotifyImage(unreadSmsCount, mIcon, getPaint(), name.getPackageName());

}

}

这里我们对这两个应用做了特殊的处理,同理在看下BubbleTextView里面的方法

public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) {

Bitmap b = info.getIcon(iconCache);

final Intent intentnew = info.intent;

final ComponentName name = intentnew.getComponent();

if (name != null) {

if ("com.android.dialer".equals(name.getPackageName())

&& "com.android.dialer.DialtactsActivity".equals(name.getClassName())) {

int unreceivedCall = iconCache.getUnreceivedCallCount();

b = iconCache.createNotifyImage(unreceivedCall, b, getPaint(), name.getPackageName());

} else if ("com.android.mms".equals(name.getPackageName())

&& "com.android.mms.ui.ModeChooser".equals(name.getClassName())) {

int unreadSmsCount = iconCache.getUnreadSmsCount();

b = iconCache.createNotifyImage(unreadSmsCount, b, getPaint(), name.getPackageName());

}

}

这就基本完成了这两个ICON的过滤功能

iconCache.createNotifyImage(unreceivedCall, b, getPaint(), name.getPackageName())这个方法我们就知道是绘制ICON图片的显示我们在IconCache里面研究下看怎么绘制的

public Bitmap createNotifyImage(int number, Bitmap bitmap, Paint paint, String packageName) {

String num = String.valueOf(number);

if (number == 0) {

Bitmap bitmap2 = getAppIcon(packageName);

if(bitmap2 != null) {

return zoomBitmap(bitmap2, bitmap.getWidth(), bitmap.getHeight());

}

}

if(number > 99) {

num = "99+";

} Drawable drawable = mContext.getResources().getDrawable(R.drawable.notification_icon);

Bitmap originalBitmap = ((BitmapDrawable) drawable).getBitmap();

int width = originalBitmap.getWidth();

int height = originalBitmap.getHeight();

int textSize = 22;

int textHeight = 30;

int textStartX = 0;

if (number > 99) {

textStartX = 20;} else if (number > 9){

textStartX = 22;

} else {

textStartX = 24;

}

if (mIconDpi < 320) {

textSize = 15;

textHeight = 22;

if (number > 99) {

textStartX = 12;

} else if (number > 9){

textStartX = 14;

} else {

textStartX = 16;

}

} Matrix matrix = new Matrix();

matrix.preScale(1, -1);

Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(newBitmap);Paint defaultPaint = new Paint();

defaultPaint.setAntiAlias(true);

defaultPaint.setFakeBoldText(true);

defaultPaint.setTextSize(textSize);

defaultPaint.setTextAlign(Align.CENTER);

defaultPaint.setColor(0xffffffff);

canvas.drawBitmap(originalBitmap, 0, 0, null);

canvas.drawText(num, textStartX, textHeight, defaultPaint);

Canvas canvas1 = new Canvas(bitmap);

canvas1.drawBitmap(newBitmap, bitmap.getWidth() - newBitmap.getWidth() , 0, paint);

return bitmap;

}通过这个方法我们就完成了过滤ICON的绘制

基本功能的思路我们已经讲解完成,代码只是一些大概,如需要详细的了解我们还要继续研究Android Launcher的源码分析,

Launcher源码博大精深值得我们好好学习和探究。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: