android开发笔记之锁屏界面未读短信未接来电提醒(android 4.4)

android开发笔记之锁屏界面未读短信未接来电提醒(android 4.4)_第1张图片

客户需求

最近在做一个项目,android 4.4系统,客户要求在锁屏界面有未读短信未接来电的提醒功能。而平台没有此功能,要自己实现。并且时间非常紧,………。(其实软件工程师基本上都是这样,坑,坑,坑)

效果图

读取数据

(1)读取未接来电的数量

主是是判断db数据库中的type和new二个字段是否同时是Calls.MISSED_TYPE 和1(type == Calls.MISSED_TYPE,new == 1).

通话记录的db数据库在:
/data/data/com.android.providers.contacts/databases/contacts2.db

calls表中

public int getUnreadCallNum(){  
        Log.d(TAG, "TinnoUnreadCallContentObserver---getUnreadCallNum" );   
        Cursor cursor = context.getContentResolver().query(
                CallLog.Calls.CONTENT_URI,
                new String[] {Calls.TYPE},
                " type=? and new=?",
                new String[] {Calls.MISSED_TYPE + "", "1"},
                "date desc");       
        Log.d(TAG, "TinnoUnreadCallContentObserver---getUnreadCallNum--cursor:"+cursor);                
        int count = 0;
        if (cursor != null) {
            try {
                count = cursor.getCount();
                Log.d(TAG, "TinnoUnreadCallContentObserver---getUnreadCallNum--count:"+count);
            } finally {
                cursor.close();
            }
        }
        Log.d(TAG, "getUnreadCallNum count=" + count);
        return count;
    }

(2)读取未读短信数量:
这主要是未读短信和未读彩信的和:

    public int getNewSmsCount() { 
          int result = 0; 
          Cursor csr = context.getContentResolver().query(
                  Uri.parse("content://sms"), 
                  null, 
                  "type = 1 and read = 0", 
                  null, 
                  null); 
          if (csr != null) { 
            result = csr.getCount(); 
            csr.close(); 
          } 
          return result; 
    } 

    public int getNewMmsCount() { 
          int result = 0; 
          Cursor csr = context.getContentResolver().query(
                  Uri.parse("content://mms/inbox"), 
                  null, 
                  "read = 0",
                  null, 
                  null); 
          if (csr != null) { 
            result = csr.getCount(); 
            csr.close(); 
          } 
          return result; 
    } 

读取上面的数据,是要在AndroidManifest.xml文件中定义一下权限:

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

界面显示

好了,要显示的数据得来了,下面就把这些数据在锁屏界面来显示吧。

是不是觉得下面非常简单了,事实上,界面显示才是这个功能的真正的难点所在,我花费了大量的时间在这个界面显示上。那么,坑人的地方,是在那里呢?

因为我本身有MTK的实现了此能的代码,我一开始想直接移植此功能,非常可惜,由于平台差异太大,导致我移植后,一开机systemui就直接报错,根本就没有办法调试和分析,而导致systemui报错的地方,就是界面的布局文件是显示。

最好,我还是老老实实的一步一步的添加控件,一步一步的调试,才把这个界面显示添加上去。有时候,最笨的方法才是最可靠的方法

我们先在keyguard_selector_view.xml文件中,添加显示未读短信和未接来电和图标和数量:

<com.android.keyguard.KeyguardSelectorView  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard" android:id="@+id/keyguard_selector_view" android:layout_width="match_parent" android:layout_height="match_parent" androidprv:layout_maxWidth="420dp" androidprv:layout_maxHeight="@dimen/keyguard_security_height" android:clipChildren="false" android:clipToPadding="false" android:orientation="vertical" android:contentDescription="@string/keyguard_accessibility_slide_unlock">

    <FrameLayout  android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:clipChildren="false" android:clipToPadding="false" android:gravity="center">

        <include layout="@layout/keyguard_message_area" android:layout_width="match_parent" android:layout_height="wrap_content" />

        <View  android:id="@+id/keyguard_selector_view_frame" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:background="@drawable/kg_bouncer_bg_white"/>
     <!-- add hexiaoming for lockscreen unread event start-->
    <FrameLayout  android:id="@+id/flUnreadIncall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="40dp" android:layout_marginLeft="40dp">

        <ImageView  android:id="@+id/unreadIncall" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="10dp" android:background="@drawable/mtk_ic_newevent_phone" android:visibility="invisible"/>

        <TextView  android:id="@+id/unreadIncallNum" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:gravity="center" android:background="@drawable/mtk_ic_newevents_numberindication" android:visibility="invisible"/>
    </FrameLayout>

    <FrameLayout  android:id="@+id/flUnreadIncall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="40dp" android:layout_marginLeft="220dp">

        <ImageView  android:id="@+id/unreadMms" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="10dp" android:background="@drawable/mtk_ic_newevent_smsmms" android:visibility="invisible"/>

        <TextView  android:id="@+id/unreadMmsNum" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:gravity="center" android:background="@drawable/mtk_ic_newevents_numberindication" android:visibility="invisible"/>
    </FrameLayout>
    <!-- add hexiaoming for lockscreen unread event end-->
        <FrameLayout  android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="20dp" android:id="@+id/keyguard_unlock_panel">
            <include layout="@layout/keyguard_glow_pad_container" />
        </FrameLayout>

        <include layout="@layout/keyguard_eca" android:id="@+id/keyguard_selector_fade_container" android:layout_width="match_parent" android:layout_height="48dp" android:layout_gravity="bottom|center_horizontal" />
    </FrameLayout>

</com.android.keyguard.KeyguardSelectorView>

然后在KeyguardSelectorView.java文件中,添加对显示ui的实现逻辑,而这主要是依靠对call log和短信,彩信三个db数据库的监听来实现的。

先定义:

    private SecurityMessageDisplay mSecurityMessageDisplay;
    private Drawable mBouncerFrame;

   //add hexiaoming for lockscreen unread event start
    private boolean isSupportUnreadEventLockscreen = true;
    private TextView unreadIncallNum = null;
    private ImageView unreadIncall = null;
    private Handler handler;   
    private TextView unreadMmsNum = null;
    private ImageView unreadMms = null;
    private TinnoUnreadCallContentObserver tinnoUnreadCallContentObserver = null;
    private TinnoUnreadMmsContentObserver tinnoUnreadMmsContentObserver = null;
    //add hexiaoming for lockscreen unread event end

再初始化和注册监听:

@Override
protected void onFinishInflate() {
        super.onFinishInflate();
        mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
        mGlowPadView.setOnTriggerListener(mOnTriggerListener);
        if (SystemProperties.getBoolean("ro.board.has.3in1speaker", false)) {
            mGlowPadView.setVibrateEnabled(false); // Do not vibrate when unlocking phone.
        }
        updateTargets();

        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
        View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
        mBouncerFrame = bouncerFrameView.getBackground();
        //add hexiaoming for lockscreen unread event start
        if(isSupportUnreadEventLockscreen){
            unreadIncallNum = (TextView)findViewById(R.id.unreadIncallNum);
            unreadIncall = (ImageView)findViewById(R.id.unreadIncall); 
            handler = new Handler(); 
            tinnoUnreadCallContentObserver = new TinnoUnreadCallContentObserver(
                    handler,
                    getContext(),
                    unreadIncallNum,
                    unreadIncall); 
            getContext().getContentResolver().registerContentObserver(
                    TinnoUnreadCallContentObserver.MISS_CALL_URI,
                    true,
                    tinnoUnreadCallContentObserver); 
            unreadMmsNum = (TextView)findViewById(R.id.unreadMmsNum);
            unreadMms = (ImageView)findViewById(R.id.unreadMms);

            tinnoUnreadMmsContentObserver = new TinnoUnreadMmsContentObserver(
                    handler,
                    getContext(),
                    unreadMmsNum,
                    unreadMms);
            getContext().getContentResolver().registerContentObserver(
                    Uri.parse("content://sms"),
                    true,
                    tinnoUnreadMmsContentObserver);

            getContext().getContentResolver().registerContentObserver(
                    TinnoUnreadMmsContentObserver.UNREAD_MMSSMS_URI,
                    true,
                    tinnoUnreadMmsContentObserver);
        }       
        //add hexiaoming for lockscreen unread event end
    }

至此,逻辑部分已经实现,您还需要在Android.mk文件中添加下面的定义,才可以编译:

#add hexiaoming for lockscreen unread event start
LOCAL_JAVA_LIBRARIES += telephony-common mms-common
#add hexiaoming for lockscreen unread event end

bug的解决

你以为就ok了,当然,如果从我们开发者来说,是的,功能是可以了。但是,对于使用者来说,不是这样的。
测试提出来,说有一个bug:当我们有一个未接来电时,我们点击拨号应用,按道理来说,这个未接来电是要不再显示的,但是我们还是会显示未接来电。

我看了一下操作,思考了一下,其实原理非常简单,因为在点击拨号进入应用时,我们没有把未接来电改为已读来电,当然是还显示未接来电了。

那修改就简单了,我直接在拨号应用的主界面,当进来时,直接把未接来电改为已读来电就可以了。

实现逻辑:
Dialer\src\com\android\dialer\DialtactsActivity.java

   @Override
    protected void onResume() {
        super.onResume();
        ............
        ............
        //add hexiaoming for lockscreen new event start
        removeMissedCall();
        //add hexiaoming for lockscreen new event end
    }

    //add hexiaoming for lockscreen new event start
    private void removeMissedCall() {
        // TODO Auto-generated method stub
        new AsyncTask<Void, Void, Void>() {
            @Override
            public Void doInBackground(Void... params) {

// Cursor cursor = context.getContentResolver().query(
// CallLog.Calls.CONTENT_URI,
// new String[] {Calls.TYPE},
// " type=? and new=?",
// new String[] {Calls.MISSED_TYPE + "", "1"},
// "date desc");

                ContentValues values = new ContentValues();    
                values.put(Calls.TYPE, Calls.MISSED_TYPE);
                values.put("new", 0); 

                String where = "type=? and new=?";
                String[] selectValue = {Calls.MISSED_TYPE + "", "1"};      

                Log.d("debug_hxm","removeMissedCall--update");
                getContentResolver().update(
                        CallLog.Calls.CONTENT_URI, 
                         values,
                         where, 
                         selectValue);
                return null;
            }
        }.execute(null, null, null);
    }
     //add hexiaoming for lockscreen new event end

源码下载地址:

http://download.csdn.net/detail/hfreeman2008/9657800

你可能感兴趣的:(Android开发,未接来电,锁屏界面,未读短信)