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


本人一直在手机ODM公司做Android开发,不是纯应用开发,和大多数Android应用开发有点区别。偶尔也会做一些系统应用上的需求开发以及个人兴趣会看看app应用和动手操作。平时的总结都是保存在本地或者使用印象笔记,记录得比较零散,今天分享在博客上。
由于是系统应用,只有在特定开发机型上使用,不好上源码,而且项目有保密要求。所以我主要写开发中的大体思路和一些知识点的总结。这个是去年的一个项目开发.目前也应用到了好多个项目中了.

一、功能需求和目标
仿照小米收藏短信功能,在短信会话界面,对长按某一条短信后,弹出包含收藏/取消收藏的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就行了,其中涉及到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);


本身由于是系统应用,只有在特定开发机型上使用,代码也太多,不好上源码. 主要记录一些思路和相关知识点总结吧.有时间也谢谢短信通知类消息聚合的开发.


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值