SMS注册与接收短信
2016-02-29 18:57
369 查看
Android4.2
在Android4.0中,Phone应用的Application类PhoneApp的onCreate方法中调用了
在PhoneFactory的makeDefaultPhone方法中初始化了RIL类的静态对象sCommandsInterface与Phone的静态对象sProxyPhone。
RIL构造时判断出手机网络良好就会启动一个线程,线程的Runnable对象是RILReceiver的对象。在run方法中构建Sockect并向下层发起连接
接下来读取4个代表类型的字节。走if流程processUnsolicited (p)。
接下来再读取4个字节的int数据代表事件类型,接收短信走RIL_UNSOL_RESPONSE_NEW_SMS(1003)流程
mGsmSmsRegistrant的notifyRegistrant方法把得到数据用handler传递出去了,接下来跟踪handler是哪个类传过来的。
在构造Phone对象时
调用了GsmSMSDispatcher中的dispatchMessage(SmsMessageBase smsb)方法,在此方法中对USIM做了其他处理。判断了系统属性是否允许接收短信,对接收短信的限制可以在这个方法里做。最后调用了SMSDispatcher的dispatchNormalMessage(smsb)方法,在此方法又根据解析数据的来的信息判断流程,最后走到dispatchPdus(byte[][] pdus)方法,此方法发送广播
下面就是应用层接收广播与处理得到的数据过程了:
接收广播的是SmsReceiver的子类PrivilegedSmsReceiver,最后又把接收到的Intent传递到SmsReceiverService.class中去处理了
handleSmsReceived方法把收到的数据存到数据库里并发收到信息的通知。
在Android4.0中,Phone应用的Application类PhoneApp的onCreate方法中调用了
PhoneFactory.makeDefaultPhones(this);而在4.2中此方法被移到了PhoneGlobals中,PhoneGlobals类继承自ContextWrapper。
在PhoneFactory的makeDefaultPhone方法中初始化了RIL类的静态对象sCommandsInterface与Phone的静态对象sProxyPhone。
RIL构造时判断出手机网络良好就会启动一个线程,线程的Runnable对象是RILReceiver的对象。在run方法中构建Sockect并向下层发起连接
s = new LocalSocket(); l = new LocalSocketAddress(SOCKET_NAME_RIL, LocalSocketAddress.Namespace.RESERVED); s.connect(l);如果连接不上每隔4秒重连一次。如果连接正常,则获取流,调用readRilMessage(is, buffer)方法返回除去开头4个字节外能从流中获取的字节数并把获取的字节存于8k大小限制的buffer中,如果读不到任何字节返回-1。如果返回值为-1,则跳出处理流程,重新进入for循环,否则把获取的字节存于Parcel对象中并调用processResponse(p)处理获取到的数据。
private void processResponse (Parcel p) { int type; type = p.readInt(); if (type == RESPONSE_UNSOLICITED) { processUnsolicited (p); } else if (type == RESPONSE_SOLICITED) { processSolicited (p); } releaseWakeLockIfDone(); }
接下来读取4个代表类型的字节。走if流程processUnsolicited (p)。
接下来再读取4个字节的int数据代表事件类型,接收短信走RIL_UNSOL_RESPONSE_NEW_SMS(1003)流程
case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break;
protected Object responseString(Parcel p) { String response; response = p.readString(); return response; }获取数据中的String后继续处理
case RIL_UNSOL_RESPONSE_NEW_SMS: { if (RILJ_LOGD) unsljLog(response); // FIXME this should move up a layer String a[] = new String[2]; a[1] = (String)ret; SmsMessage sms; sms = SmsMessage.newFromCMT(a); if (mGsmSmsRegistrant != null) { mGsmSmsRegistrant .notifyRegistrant(new AsyncResult(null, sms, null)); } break;如上:mGsmSmsRegistrant定义在Ril的父类中通过下方法赋对象
public void setOnNewGsmSms(Handler h, int what, Object obj) { mGsmSmsRegistrant = new Registrant (h, what, obj); }
mGsmSmsRegistrant的notifyRegistrant方法把得到数据用handler传递出去了,接下来跟踪handler是哪个类传过来的。
在构造Phone对象时
sProxyPhone[i] = new YZPhoneProxy(new TDPhone(context, sCommandsInterface[i], sPhoneNotifier[i]));可以看出Ril对象赋给了TDPhone对象,TDPhone对象赋给了YZTPhoneProxy对象。查看TDPhone对象的构造发现其调用了其父类GSMPhone的构造,在GSMPhone构造方法中初始化了SMSDispatcher对象
mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);在GsmSMSDispatcher的构造方法中调用了setOnNewGsmSms方法把自己注册在Ril.java里了。
public GsmSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor, SmsUsageMonitor usageMonitor) { super(phone, storageMonitor, usageMonitor); mDataDownloadHandler = new UsimDataDownloadHandler(mCm); mCm.setOnNewGsmSms(this, EVENT_NEW_SMS, null); mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null); mCm.setOnNewGsmBroadcastSms(this, EVENT_NEW_BROADCAST_SMS, null); }也就是说Ril类里接收普通短信的数据最终传到了GsmSMSDispatcher类的handleMessage方法里,不过GsmSMSDispatcher的handleMessage没处理,而是在其父类SMSDispatcher的handleMessage方法中处理的。
case EVENT_NEW_SMS: // A new SMS has been received by the device if (false) { Log.d(TAG, "New SMS Message Received"); } SmsMessage sms; ar = (AsyncResult) msg.obj; if (ar.exception != null) { Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception); return; } sms = (SmsMessage) ar.result; try { int result = dispatchMessage(sms.mWrappedSmsMessage); if (result != Activity.RESULT_OK) { // RESULT_OK means that message was broadcast for app(s) to handle. // Any other result, we should ack here. boolean handled = (result == Intents.RESULT_SMS_HANDLED); notifyAndAcknowledgeLastIncomingSms(handled, result, null); } } catch (RuntimeException ex) { Log.e(TAG, "Exception dispatching message", ex); notifyAndAcknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null); } break;
调用了GsmSMSDispatcher中的dispatchMessage(SmsMessageBase smsb)方法,在此方法中对USIM做了其他处理。判断了系统属性是否允许接收短信,对接收短信的限制可以在这个方法里做。最后调用了SMSDispatcher的dispatchNormalMessage(smsb)方法,在此方法又根据解析数据的来的信息判断流程,最后走到dispatchPdus(byte[][] pdus)方法,此方法发送广播
protected void dispatchPdus(byte[][] pdus) { Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION); intent.putExtra("pdus", pdus); intent.putExtra("format", getFormat()); dispatch(intent, RECEIVE_SMS_PERMISSION); }
下面就是应用层接收广播与处理得到的数据过程了:
接收广播的是SmsReceiver的子类PrivilegedSmsReceiver,最后又把接收到的Intent传递到SmsReceiverService.class中去处理了
} else if (SMS_RECEIVED_ACTION.equals(action)) { handleSmsReceived(intent, error);
private void handleSmsReceived(Intent intent, int error) { SmsMessage[] msgs = Intents.getMessagesFromIntent(intent); String format = intent.getStringExtra("format"); Uri messageUri = insertMessage(this, msgs, error, format); if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) { SmsMessage sms = msgs[0]; Log.v(TAG, "handleSmsReceived" + (sms.isReplace() ? "(replace)" : "") + " messageUri: " + messageUri + ", address: " + sms.getOriginatingAddress() + ", body: " + sms.getMessageBody()); } if (messageUri != null) { long threadId = MessagingNotification.getSmsThreadId(this, messageUri); // Called off of the UI thread so ok to block. Log.d(TAG, "handleSmsReceived messageUri: " + messageUri + " threadId: " + threadId); MessagingNotification.blockingUpdateNewMessageIndicator(this, threadId, false); } }
handleSmsReceived方法把收到的数据存到数据库里并发收到信息的通知。
相关文章推荐
- POJ3630 Phone List 题解&代码
- ZOJ Paint the Grid Reloaded
- [HDU 2896] - 病毒侵袭 ac 自动机
- 一次多进程的小尝试
- hadoop搭建完毕后启动hadoop弹出ssh警告提示的解决办法
- ser2net和socat
- python入门
- 关于学科的疑惑
- [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
- IOS 将数组转化成NSData数据进行保存
- ACM_模板_母函数
- vps安全设置
- linux服务器上设置多主机头,设置多web站点
- The repository for high quality TypeScript type definitions
- bean的初始化过程和对应源代码
- less
- IOS开发之UIView总结
- uva10271 经典DP
- hiredis aeStop仅在redis命令的回调函数中生效 分析
- 大数据之一:几个概念