Android入门-短信-彩信部分内容的获取方法

来源:互联网 发布:key-value数据库原理 编辑:程序博客网 时间:2024/06/04 19:51

android短信模块中,短信彩信的收发是重点,不同于短信,基本所有短信元素全部保存在mmssms.db的sms表中。

注:mmssms.db在/data/data/com.previder.telephony/databases/下

关于mmssms.db的表的具体定义可以看这个博客哦~ http://blog.csdn.net/t12x3456/article/details/9336869

彩信的存取是pdu表,pdu表里面通过各种外键来将彩信的各元素联系起来,来看一下彩信pdu表中的元素有哪些:

 

这些数据源代表的意义通过命名可以稍微了解到一些,如sub存储的彩信主题,locked存储的是该信息是否锁定。表格元素的设定各芯片厂商各不相同,对于手机内置应用的定制和功能开发,也会有修改到这些表。这里不是我们的讨论重点。

下面主要将到怎样在代码中通过cursor组合外键来来获取彩信需要显示的部分信息,已彩信在notification显示时获取的方法为例说明。代码中类和常量的定义未加说明,可以从名称理解。

select的定义,即projection:

private static final String[] MMS_STATUS_PROJECTION = new String[] {        Mms.THREAD_ID, Mms.DATE, Mms._ID, Mms.SUBJECT, Mms.SUBJECT_CHARSET };

where的定义,即判断条件:

private static final String NEW_INCOMING_MM_CONSTRAINT =            "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX            + " AND " + Mms.SEEN + "=0"            + " AND (" + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_NOTIFICATION_IND            + " OR " + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_RETRIEVE_CONF + "))";

获取查询游标:

Cursor cursor = SqliteWrapper.query(context, resolver, Mms.CONTENT_URI,                            MMS_STATUS_PROJECTION, NEW_INCOMING_MM_CONSTRAINT,                            null, Mms.DATE + " desc");

 

表设计里面甚至彩信发送人地址都没有!太过分了,那首先我们获取address和联系人对象:

long msgId = cursor.getLong(COLUMN_MMS_ID);//获取彩信pdu的idUri msgUri = Mms.CONTENT_URI.buildUpon().appendPath(    Long.toString(msgId)).build();//根据msgId查询这条信息UriString address = AddressUtils.getFrom(context, msgUri);//根据Uri和上下文获取发信人地址Contact contact = Contact.get(address, false);//根据地址获取联系人对象

 

(1)分析下AddressUtils.getFrom(context, msgUri);其实也很简单,就是另外一个查询数据库的操作,直接上源码,有心人可以把这个查询和上面查询组合,不过好复杂的样子,我讨厌数据库。

public static String getFrom(Context context, Uri uri) {        String msgId = uri.getLastPathSegment();        Uri.Builder builder = Mms.CONTENT_URI.buildUpon();        builder.appendPath(msgId).appendPath("addr");        Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),                            builder.build(), new String[] {Addr.ADDRESS, Addr.CHARSET},                            Addr.TYPE + "=" + PduHeaders.FROM, null, null);        if (cursor != null) {            try {                if (cursor.moveToFirst()) {                    String from = cursor.getString(0);                    if (!TextUtils.isEmpty(from)) {                        byte[] bytes = PduPersister.getBytes(from);                        int charset = cursor.getInt(1);                        return new EncodedStringValue(charset, bytes)                                .getString();                    } else { /// M: @{                        Log.d(TAG, "getFrom EncodedStringValue1 is null");                    }                    /// @}                }            } finally {                cursor.close();            }        }        /// M: @{        Log.d(TAG, "getFrom EncodedStringValue2 is null");        /// @}        return context.getString(R.string.hidden_sender_address);    }

 

(2)再分析Contact.get(address, false);直接上源码吧,我也不分析了- - 原因同上!

private Contact get(String number, boolean isMe, boolean canBlock) {            if (Log.isLoggable(LogTag.CONTACT, Log.DEBUG)) {                logWithTrace("get(%s, %s, %s)", number, isMe, canBlock);            }            final Object obj = new Object();            if (TextUtils.isEmpty(number)) {                number = "";        // In some places (such as Korea), it's possible to receive                                    // a message without the sender's address. In this case,                                    // all such anonymous messages will get added to the same                                    // thread.            }            // Always return a Contact object, if if we don't have an actual contact            // in the contacts db.            Contact contact = internalGet(number, isMe);            Runnable r = null;            synchronized (contact) {                // If there's a query pending and we're willing to block then                // wait here until the query completes.                /// M: make sure the block can update contact immediately @{                if (canBlock) {                    contact.mIsStale = true;                }                /// @}                // If we're stale and we haven't already kicked off a query then kick                // it off here.                if (contact.mIsStale) {                    contact.mIsStale = false;                    if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {                        log("async update for " + contact.toString() + " canBlock: " + canBlock +                                " isStale: " + contact.mIsStale);                    }                    final Contact c = contact;                    r = new Runnable() {                        public void run() {                            updateContact(c);                            /// M:@{                            synchronized (obj) {                                obj.notifyAll();                            }                            c.mQueryPending = false;                            /// @}                        }                    };                }            }            // do this outside of the synchronized so we don't hold up any            // subsequent calls to "get" on other threads            //MmsLog.d(M_TAG, "get(" + number + ", " + isMe + ", " + canBlock + "): mWaitTime = " + mWaitTime);            if (r != null) {                if (canBlock) {                    /// M: @{                    pushTask(r);                    synchronized (obj) {                        try {                            obj.wait(mWaitTime);                        } catch (InterruptedException ex) {                            // do nothing                        }                    }                    if (mWaitTime < mMaxWaitTime) {                        mWaitTime += 5;                    }                } else {                    pushTask(r);                }            } else {                if ((mWaitTime -= mMinWaitTime) < mMinWaitTime) {                    mWaitTime = mMinWaitTime;                }            }            /// @}            return contact; }


地址和联系人获取到之后,我们开始获取彩信主题,表内有这个元素,直接获取,可能有些编码要处理,这个就不写了。

然后根据thread_id开始各种查询了!

long threadId = cursor.getLong(COLUMN_THREAD_ID);long timeMillis = cursor.getLong(COLUMN_DATE) * 1000;Bitmap attachedPicture = null;String messageBody = null;int attachmentType = WorkingMessage.TEXT;try {    GenericPdu pdu = sPduPersister.load(msgUri);//获取Uri对应pdu类    if (pdu != null && pdu instanceof MultimediaMessagePdu) {        SlideshowModel slideshow = SlideshowModel.createFromPduBody(context,((MultimediaMessagePdu)pdu).getBody());//彩信的幻灯片        attachmentType = getAttachmentType(slideshow);        SlideModel firstSlide = slideshow.get(0);//获取第一张幻灯片,因为在通知栏只需要显示彩信预览即可        if (firstSlide != null) {            if (cursor.getCount() <= 1) {                if (firstSlide.hasImage()) {                    int maxDim = dp2Pixels(MAX_BITMAP_DIMEN_DP);                    attachedPicture = firstSlide.getImage().getBitmap(maxDim, maxDim);//获取第一张幻灯片的图片                }            }            if (firstSlide.hasText()) {                messageBody = firstSlide.getText().getText();            }        }    }} catch (final MmsException e) {    Log.e(TAG, "MmsException loading uri: " + msgUri, e);}


这样彩信预览相关的元素就全部获取到了。基本都是些查表和对接口的掌握。

 

上述的主体方法在\packages\apps\Mms\src\com\android\mms\transaction\MessagingNotification.java中有定义。

小伙伴们也可自行前往观看。

 

原创粉丝点击