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

仿小米增加短信的收藏功能

2016-03-23 17:37 387 查看
本人一直作Android开发,但是不是纯应用开发,是ODM公司,和大多数Android应用开发有点不同,大部分时间在解bug做项目,偶尔也会做一些系统应用上的需求开发以及个人兴趣会看看app应用和动手操作. 平时的总结都是保存在本地或者使用印象笔记,记录得比较零散.以前就很想写博客,看到很多Android应用开发的大牛分享很多高质量的文章, 很是羡慕. 今天也动手分享一下项目中的东西.
由于是系统应用,只有在特定开发机型上使用,不好上源码,而且也有公司保密原因.所以我主要写开发中的大体思路和一些知识点的总结。这个是去年的一个项目开发.目前也应用到了好多个项目中了.

一、功能需求和目标
仿照小米收藏短信功能,在短信会话界面,对长按某一条短信后,弹出包含收藏/取消收藏的Menu选项,并且该界面显示出是收藏状态/未收藏状态; 然后主界面会有收藏item列; 点击收藏列进入收藏界面,长按短信可以进行复制\取消\转发\保存到SIM卡等操作.

二.解决方法概述:

开发环境: Ubuntu系统。安卓源码android5.1上MTK6735平台及相应的编译环境。手机有root权限,eng或者userdebug版本.
短信message是存储在SQLite数据库mmssms.db中的,通过在数据库对应的表中增加字段favorite(可对照原生Mms的lock字段)来对收藏短信进行标记。界面的显示可以根据当前Mms的会话界面基础上进行修改。
总的来说就三步,修改数据库字段,添加ContentProvider查询和UI界面的修改。从界面到数据库的修改都可以参考lock字段来进行.

涉及知识点:
ContentProvider的相关知识;
SQL语言增删改查的简单了解;
适配器模式.
Android中Handler操作,异步查询数据操作.

三、主要步骤及涉及主要文件:



图1 修改的文件列表

1.数据库字段的增加。

(1)首先要找到短信使用的数据库,使用DDMS工具导出db文件,然后使用sqlite工具查看数据库。
通过DDMS工具查看FileExplorer找到文件/data/data/com.android.providers.telephony/databases/mmssms.db导出到本地电脑上(也可以在终端上使用命令adb pull /data/data/com.android.providers.telephony/databases/mmssms.db ~/),再使用工具SQLiteExpert查看,如下:



图2 未添加favorite字段的sms表

如图左边一列所示这个数据库中有多张表,每张表都有不同作用,如表canonical_addresses是短信会话中所有会话联系人地址的列表,一个会话对应一个_id和address,包含文本短信、彩信、邮件等;cellbroadcast是小区广播信息有关的表;part和pdu是和彩信有关的表;sms是文本信息的表。我们选其中sms表来看,如上图sms表右边的所有字段,可以仿照lock字段进行添加我们需要的favorite字段。

(2)其中我们主要修改sms/pdu/cellbroadcast三张表,在表中增加favorite字段。然后编译TelephonyProvider,push到手机,删除手机中的mmssms.db数据库,重启手机,再重复(1)步骤导出db文件,查看数据库表是否增加了favorite字段来验证修改是否成功。其中favorite默认是0,表示用户没有收藏,1表示用户收藏此信息。
sms表的具体修改:

M:asp/packages/providers/TelephonyProvider/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
——数据库修改文件

MmsSmsDatabaseHelper继承自SQLiteOpenHelper,这个类是专门用来进行数据库管理的,包括create、update等等。

......
private void createSmsTables(SQLiteDatabase db) {

        // N.B.: Whenever the columns here are changed, the columns in

        // {@ref MmsSmsProvider} must be changed to match.

        db.execSQL("CREATE TABLE sms (" +

                   "_id INTEGER PRIMARY KEY," +

                   "thread_id INTEGER," +

                   "address TEXT," +

                   /// M: Code analyze 016, unknown, new column in sms table.

                   "m_size INTEGER," +

                   "person INTEGER," +

                   "date INTEGER," +

                   "date_sent INTEGER DEFAULT 0," +

                   "protocol INTEGER," +

                   "read INTEGER DEFAULT 0," +

                   "status INTEGER DEFAULT -1," + // a TP-Status value

......

                   "locked INTEGER DEFAULT 0," +

                   //Mms start 

                   "favorite INTEGER DEFAULT 0," +

                   //Mms end 

                   /// M: Code analyze 015, new feature, support for gemini.

                   "sim_id INTEGER DEFAULT -1," +

                   "error_code INTEGER DEFAULT 0," +

......

很明显在这个函数中创建了sms表,另外两个类似这样的修改,就不举例代码了。

此时在重新编译该修改模块(终端命令mmm package/providers/TelephonyProvider/),将out目录下生成的TelephonyProvider.apk push到手机中(终端命令adb push TelephonyProvider.apk system/priv-app/),重启手机之前一定要删除之前DDMS下用FileExplorer看到的mmssms.db数据库文件,不然重启也不生效,因为数据库文件存在了,不会再重新创建,走我们修改后的代码。

重复(1)步骤导出db文件,查看数据库表是否增加了favorite字段来验证修改是否成功。如下图右边显示已经有favorite字段了,表示修改成功。



图3 添加favorite字段后得到的sms数据库表

2.在MmsSmsProvider添加查询URL及方法,供全局查找和修改

M:asp/packages/providers/TelephonyProvider/src/com/android/providers/telephony/MmsSmsProvider.java ——继承ContentProvider的文件

这个文件比较多,只要在其中query时添加一个查询的URL
4000
就行了,其中涉及到SQL语句的组织,我自己也了解不深,只是边学边用的。,ContentProvider的知识有了解的,对这个部分就很熟悉流程了。贴一个关键的查询收藏功能的方法:
private Cursor getFavoriteMessage(String[] projection, String selection,

            String sortOrder){

        String[] mmsProjection = createMmsProjection(projection);

        SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();

        SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();

mmsQueryBuilder.setTables(MmsProvider.TABLE_PDU);

        smsQueryBuilder.setTables(SmsProvider.TABLE_SMS);

String[] smsColumns = handleNullMessageProjection(projection);

        String[] mmsColumns = handleNullMessageProjection(mmsProjection);

Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS);

        columnsPresentInTable.add("pdu._id");

        String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(

                MmsSms.TYPE_DISCRIMINATOR_COLUMN, mmsColumns,

                columnsPresentInTable, 0, "mms", selection,

                null, null);

        String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(

                MmsSms.TYPE_DISCRIMINATOR_COLUMN, smsColumns, 

                SMS_COLUMNS, 0, "sms", selection,

                null, null);

        SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();

        String unionQuery = null;  

        unionQuery = unionQueryBuilder.buildUnionQuery(

                new String[] { smsSubQuery, mmsSubQuery}, sortOrder, null);

        Cursor cursor = mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY);

        MmsLog.d(LOG_TAG, "getFavoriteMessage query: " + unionQuery);

        MmsLog.d(LOG_TAG, "cursor count: " + cursor.getCount());

        return cursor;
}

3.界面修改

由于UI界面代码比较多,更不好贴代码了,主要讲解下思路和关键文件说明

(1)会话界面

M:asp/packages/apps/Mms/src/com/android/mms/ui/MessageItem.java 

——这个文件主要是对信息Message抽象出来的一个类,所以我们添加了一个favorite字段,必然要在这个类中增加一个变量来表示短信的favorite是否为1(即该某个短信Message对象是否被用户收藏)。

其中肯定也要对其构造方法,进行初始化该字段的值。

M:asp/packages/apps/Mms/src/com/android/mms/ui/ComposeMessageActivity.java ——会话界面短信列表的修改,长按某条信息之后,有对短信进行收藏/取消收藏的Menu操作.

长按ListView的item弹出Menu这个应该是比较简单的,可以在现有基础上修改.复写onCreateOptionsMenu();onPrepareOptionsMenu();

关键性方法是点击某个menu选项之后的收藏/取消收藏操作,修改数据库.
private void favoriteMessage(final MessageItem msgItem, final boolean favorite){
Uri uri;
if ("sms".equals(msgItem.mType)) {
uri = Sms.CONTENT_URI;
} else {
uri = Mms.CONTENT_URI;
}
final Uri favoriteUri = ContentUris.withAppendedId(uri, msgItem.mMsgId);

final ContentValues values = new ContentValues(1);
values.put("favorite", favorite ? 1 : 0);
Log.d(TAG, "favoriteMessage: favoriteUri = " + favoriteUri +",values = " + values);

new Thread(new Runnable(){
public void run(){
getContentResolver().update(favoriteUri, values, null, null);
}
}, "ComposeMessageActivity.favoriteMessage").start();
}

---M:asp/packages/apps/Mms/src/com/android/mms/ui/MessageListItem.java ---LinearLayout布局文件,控制收藏图标的显示与否.

           


图4 会话界面添加后显示

图5

图6

(2)收藏界面-略讲

主要仿照ComposeMessageActivity界面,ContextMenu,ListView,分割线等都同上,res的layout文件图片等就不细说了

A:asp/packages/apps/Mms/src/com/android/mms/ui/FavoriteMessageActivity.java

---M:asp/packages/apps/Mms/src/com/android/mms/ui/MessageListAdapter.java ---如果FavoriteMessageActivity复用这个MessageListAdapter,则需要修改以下文件,如果是单独重新写的MessageListAdapter则就不用修改以下这个个文件了.我在现有基础上改的

——短信列表显示的adpter适配,listView与MessageItem的适配器模式。里面有关查询数组列表PROJECTION需要添加favorite字段;

另外在newView复写的时候,收藏界面使用的不同layout文件
if (context instanceof FavoriteMessageActivity){
return mInflater.inflate(R.layout.favorite_message_list_item, parent, false);
}

(3)主界面-略讲

M:asp/packages/apps/Mms/src/com/android/mms/ui/ConversationList.java---主要是在ListView上面增加一个HeadView,代码不想贴了,比较简单的.另外就是要主要每次全局刷新界面的时候,收藏里面的内容都要修改,如果item上面有提示也要跟着刷新,这个可以参考每个会话在ConversationList中如何刷新的.
View headerFavorite = inflater.inflate(R.layout.conversation_list_myfavorite, null);

        getListView().addHeaderView(headerFavorite, null, true);

本身由于是系统应用,只有在特定开发机型上使用,代码也太多,不好上源码. 主要记录一些思路和相关知识点总结吧.有时间也谢谢短信通知类消息聚合的开发.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android系统应用