高通平台的MMS源码中提供了搜索功能,但要先选择分类(名字,号码,信息内容,彩信主题),再输入字符,根据分类进行搜索。
而在Contacts中却不需要分类,直接根据输入字符搜索任意匹配字段。相比之下,MMS搜索功能繁琐,用户体验不好。
那么我们来修改一下代码,实现MMS搜索,自动匹配任意字段吧
分析:查看代码TelephonyProvidersrccomandroidproviders elephonyMmsSmsProvider.java中,
从搜索语句sql设计看:名字和号码的搜索属于一类, 信息内容和主题搜索属于一类。
(名字搜索——先根据名字查询对应号码,再根据号码搜索会话)
从搜索结果看:名字和号码的搜索结果为thread表, 信息内容和主题搜索的结果为sms/mms表
具体设计:输入一个字符,可能是名字,也可能是号码,也可能是内容,也可能是主题。所以需要针对每种类型分别搜索,然后将结果合并。
对于名字和号码,在where语句中用or分别匹配;
对于短信/彩信内容和彩信主题搜索,用UNION将三个sql组合(因为查询字段个数一样,可以取同样的别名)
//---add by antoon private Cursor getMsgSearchResult(Uri uri, SQLiteDatabase db) { String keyStr = uri.getQueryParameter("key_str"); String addressStr = uri.getQueryParameter("addressStr"); Log.i("antoon", LOG_TAG + " , keyStr = " + keyStr); Log.i("antoon", LOG_TAG + " , addressStr = " + addressStr); String threadIdString = getSearchedThreadIdString(addressStr); Log.i("antoon", LOG_TAG + " , threadIdString = " + threadIdString); String searchString = "%" + addEscapeCharacter(keyStr) + "%"; Log.i("antoon", LOG_TAG + " , searchString = " + searchString); Cursor cursor; if(DEFAULT_STRING_ZERO.equals(threadIdString)){ cursor = getSmsMmsSearchContent(searchString); }else { Cursor cursorThread = getSearchedThreadIds(threadIdString); Cursor cursorMsg = getSmsMmsSearchContent(searchString); cursor = new MergeCursor(new Cursor[]{cursorThread, cursorMsg}); } return cursor; } private String getSearchedThreadIdString(String keyStr) { String[] addresses = keyStr.split(","); int count = addresses.length; Set<Long> result = new HashSet<Long>(count); for (int i = 0; i < count; i++) { String address = addresses[i]; if (address != null && !address.equals(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) { Set<Long> ids = getThreadIdsByAddress(address); if (ids != null) { result.addAll(ids); } else { Log.e(LOG_TAG, "Address ID not found for: " + address); } } } long[] addressIdSet = getSortedSet(result); String threadIdString = getCommaSeparatedId(addressIdSet); if (TextUtils.isEmpty(threadIdString)) { threadIdString = DEFAULT_STRING_ZERO; } return threadIdString; } private Set<Long> getThreadIdsByAddress(String address) { String searchString = "%" + addEscapeCharacter(address) + "%"; boolean isEmail = Mms.isEmailAddress(address); String refinedAddress = isEmail ? address.toLowerCase() : address; String selection = "address LIKE ?"; String[] selectionArgs; if (isEmail) { selectionArgs = new String[] { refinedAddress }; } else { selection += " OR " + String.format("PHONE_NUMBERS_EQUAL(address, ?, %d)", (mUseStrictPhoneNumberComparation ? 1 : 0)); selectionArgs = new String[] { searchString, refinedAddress }; } Cursor cursor = null; Set<Long> addressIds = new HashSet<Long>(); try { SQLiteDatabase db = mOpenHelper.getReadableDatabase(); cursor = db.query( "canonical_addresses", ID_PROJECTION, selection, selectionArgs, null, null, null); if (cursor.getCount() == 0) { return null; } while(cursor.moveToNext()){ addressIds.add(cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID))); } } finally { if (cursor != null) { cursor.close(); } } return addressIds; } private synchronized Cursor getSearchedThreadIds(String threadIdString) { String THREAD_QUERY = String.format( "SELECT %s FROM threads WHERE (_id in (%s))", THREADS_PROJECTION, threadIdString); SQLiteDatabase db = mOpenHelper.getReadableDatabase(); return db.rawQuery(THREAD_QUERY, EMPTY_STRING_ARRAY); } private synchronized Cursor getSmsMmsSearchContent(String keyStr) { String smsQuery = String.format( "SELECT %s FROM sms WHERE (body LIKE ? ESCAPE '" + SEARCH_ESCAPE_CHARACTER + "') ", SMS_CONTENT_PROJECTION); String mmsContentQuery = String.format(Locale.US, "SELECT %s FROM pdu,part,addr WHERE ((part.mid=pdu._id) AND " + "(addr.msg_id=pdu._id) AND " + "(addr.type=%d) AND " + "(part.ct='text/plain') AND " + "(body like ? escape '" + SEARCH_ESCAPE_CHARACTER + "')) GROUP BY pdu._id", MMS_CONTENT_PROJECTION, PduHeaders.TO); String mmsSubjectQuery = String.format( "SELECT %s FROM pdu,addr WHERE (" + "(addr.msg_id = pdu._id) AND (addr.type=%d) AND " + "(body like ? escape '" + SEARCH_ESCAPE_CHARACTER + "')) GROUP BY pdu._id", MMS_SUBJECT_PROJECTION, PduHeaders.TO); String rawQuery = String.format( "%s UNION %s UNION %s ORDER BY date ASC", smsQuery, mmsContentQuery, mmsSubjectQuery); SQLiteDatabase db = mOpenHelper.getReadableDatabase(); return db.rawQuery(rawQuery, new String[] {keyStr,keyStr,keyStr}); } public static final String THREADS_PROJECTION = "'thread' AS transport_type, _id, recipient_ids, message_count, date";
//下面三个查询字段个数一样,字段名称也一样 private static final String SMS_CONTENT_PROJECTION = "'sms' AS transport_type, _id, address, body, date";
private static final String MMS_CONTENT_PROJECTION = "'mms' AS transport_type, pdu._id, addr.address AS address, part.text as body," + "pdu.date * 1000 AS date"; private static final String MMS_SUBJECT_PROJECTION = "'mms' AS transport_type, pdu._id, addr.address AS address, pdu.sub as body, " + "pdu.date * 1000 AS date"; //---end add