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

一 分析步骤和过程

    我们需要实现的是当有一个未接来电和未读短信时,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源码博大精深值得我们好好学习和探究。



你可能感兴趣的:(Android Launcher界面未接来电和未读短信条数的显示)