sms接收流程(Java app)
新信息到达framework后,由SMSDispatcher.java通过广播的形式将其发送给app处理
1. PrivilegedSmsReceiver.java
这是一个Receiver,继承自SmsReceiver,可以接收广播:android.provider.Telephony.SMS_RECEIVED, android.provider.Telephony.WAP_PUSH_RECEIVED
它的onReceive()方法中直接调用了SmsReceiver.onReceiveWithPrivilege()来进行处理
2. SmsReceiver.java
通过方法onReceiveWithPrivilege()处理,其会启动SmsReceiverService服务
intent.setClass(context, SmsReceiverService.class);
intent.putExtra("result", getResultCode());
beginStartingService(context, intent);
context.startService(intent);
3. SmsReceiverService.java
内部用一个Handler来处理各种消息,如:MESSAGE_SENT_ACTIOIN,SMS_RECIEVED_ACTION, ACTION_SEND_MESSAGE;其中,SMS_RECEIVED_ACTION消息对应接收到新信息,调用handleSmsReced(intent, error)进行处理。
A.SmsMessage[] msgs = Intent.getMessageFromIntent(intent);
// 从intent中提取出相关字段,这个intent对象是Framework在发送广播的时候生成的,数据包含
// pdus -- 原始的PDUs信息
// format --
// phone_id --
这里最终会从puds中解析出SmsMessage对象
B.Uri messageUri = insertMessage(this, msgs, error, format, phoneId);
// 三步:
判断是否为 CLASS_0 类型,这种类型的sms直接显示,不做存储;
判断是否为 replace short message;
直接将新信息插入数据库;
(对于非 CLASS_0 类型的短信,会进行两种处理,替换现有的消息,或是当作新消息插入。
原则就是如果在数据库中已有的短信中,与新来的短信的原始地址和协议标识都一样,那么就把其替换成新进的短信,否则就当作新短信插入。)
replaceMessage(Context context, SmsMessage[] msgs, int error, int phoneId);
具体的替换流程:先用新进的短信生成一个ContentValues,再用短信的地址和协议标识当作条件到数据库中去查询,如果查到了,就替换,否则就存储。
storeMessage(Context context, SmsMessage[] msgs, int error, int phoneId);
先生成一个CotentValues,然后取出短信的Thread Id和地址,地址要与联系人数据库同步一下,以保证是能识别的地址。如果Thread Id不是合法的,那么就用同步过的地址尝试重新生成Thread Id,尝试5次。然后把刷新过的Thread Id放到ContentValues中,把ContentValues插入到数据库中。如果设置为把信息存储到SIM卡,还要调用SmsManager把信息拷贝到SIM卡上。计算短信的大小,并更新至数据库。删除过期的短信,和超过数量限制的短信,然后返回插入后得到的短信Uri。
C.MessageNotification.blockingUpdateNewMessageIndicator(this, true, false);
// 这里利用一个类管理Notification信息,
class MmsSmsNotificationInfo {
Intent mClickIntent, String mDescription, int mIconResourceId, CharSequence mTicker, long mTimeMillis, String mTitle, int count
}
当调用到这里时,会去查询数据库中没有读取的信息,根据读取的相关数据生成一个MmsSmsNotificationInfo对象,并将其加入到一个set中,最后利用这个set中的第一个元素进行notify,显示新信息在notification上