本文分析使用的是android5.0的源代码,涉及的相关文件:

frameworks\opt\telephony\src\java\com\android\internal\telephony\RIL.java

frameworks\base\core\java\com\android\internal\util\StateMachine.java

frameworks\opt\telephony\src\java\com\android\internal\telephony\InboundSmsTracker.java

frameworks\opt\telephony\src\java\com\android\internal\telephony\InboundSmsHandler.java

frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm\GsmInboundSmsHandler.java

先上时序图如下:

第一部分:RIL.java

当安卓系统收到短信后,首先被提交到RIL.java中进行处理:

1,在RIL类中有一个内部类RILReceiver,在该类的run方法中用来不断循环,获取socket传来的数据,调用readRilMessage方法获取短信Parcel对象p,调用 processResponse(p)方法进行处理

    class RILReceiver implements Runnable {byte[] buffer;RILReceiver() {buffer = new byte[RIL_MAX_COMMAND_BYTES];}@Overridepublic voidrun() {int retryCount = 0;String rilSocket = "rild";try {for (;;) {LocalSocket s = null;LocalSocketAddress l;if (mInstanceId == null || mInstanceId == 0 ) {rilSocket = SOCKET_NAME_RIL[0];} else {rilSocket = SOCKET_NAME_RIL[mInstanceId];}try {s = new LocalSocket();l = new LocalSocketAddress(rilSocket,LocalSocketAddress.Namespace.RESERVED);s.connect(l);} catch (IOException ex){try {if (s != null) {s.close();}} catch (IOException ex2) {//ignore failure to close after failure to connect}// don't print an error message after the the first time// or after the 8th timeif (retryCount == 8) {Rlog.e (RILJ_LOG_TAG,"Couldn't find '" + rilSocket+ "' socket after " + retryCount+ " times, continuing to retry silently");} else if (retryCount > 0 && retryCount < 8) {Rlog.i (RILJ_LOG_TAG,"Couldn't find '" + rilSocket+ "' socket; retrying after timeout");}try {Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);} catch (InterruptedException er) {}retryCount++;continue;}retryCount = 0;mSocket = s;Rlog.i(RILJ_LOG_TAG, "Connected to '" + rilSocket + "' socket");int length = 0;try {InputStream is = mSocket.getInputStream();for (;;) {Parcel p;length = readRilMessage(is, buffer);if (length < 0) {// End-of-stream reachedbreak;}p = Parcel.obtain();p.unmarshall(buffer, 0, length);p.setDataPosition(0);//Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes");processResponse(p);p.recycle();}} catch (java.io.IOException ex) {Rlog.i(RILJ_LOG_TAG, "'" + rilSocket + "' socket closed",ex);} catch (Throwable tr) {Rlog.e(RILJ_LOG_TAG, "Uncaught exception read length=" + length +"Exception:" + tr.toString());}Rlog.i(RILJ_LOG_TAG, "Disconnected from '" + rilSocket+ "' socket");setRadioState (RadioState.RADIO_UNAVAILABLE);try {mSocket.close();} catch (IOException ex) {}mSocket = null;RILRequest.resetSerial();// Clear request list on closeclearRequestList(RADIO_NOT_AVAILABLE, false);}} catch (Throwable tr) {Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr);}/* We're disconnected so we don't know the ril version */notifyRegistrantsRilConnectionChanged(-1);}}

2,在processResponse方法中,对应接收短信的Parcel类型是RESPONSE_UNSOLICITED(未经请求),发送短信时是RESPONSE_SOLICITED(被请求的),因此接收短信将调用processUnsolicited (p)方法。

private void processResponse (Parcel p) {int type;type = p.readInt();if (type == RESPONSE_UNSOLICITED) {processUnsolicited (p);} else if (type == RESPONSE_SOLICITED) {RILRequest rr = processSolicited (p);if (rr != null) {rr.release();decrementWakeLock();}}}

3,processUnsolicited方法将对不同的命令调用不同的操作,通过调试可以发现将调用的是RIL_UNSOL_RESPONSE_NEW_SMS分支的操作,把从Parcel中取出来的字符串封装成一个SmsMessage对象

private void processUnsolicited (Parcel p) {…………case RIL_UNSOL_RESPONSE_NEW_SMS: {if (RILJ_LOGD) unsljLog(response);// FIXME this should move up a layerString 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;
…………
}

4,然后调用   mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));

这里需要注意的是mGsmSmsRegistrant这个对象。该对象是在 RIL类的父类BaseCommands类中申明,并通过setOnNewGsmSms方法来进行初始化的,给这个Registrant指定handler h,待发送给handler的消息的类型 what 以及待发送给handler的待处理的对象obj

   frameworks\opt\telephony\src\java\com\android\internal\telephony\BaseCommands.java@Overridepublic void setOnNewGsmSms(Handler h, int what, Object obj) {mGsmSmsRegistrant = new Registrant (h, what, obj);//注意这个what}

知道了这个mGsmSmsRegistrant这个对象是一个Registrant对象后,我们来看他的notifyRegistrant方法

   public void notifyRegistrant(AsyncResult ar){internalNotifyRegistrant (ar.result, ar.exception);}/*package*/ voidinternalNotifyRegistrant (Object result, Throwable exception){Handler h = getHandler();if (h == null) {clear();} else {Message msg = Message.obtain();msg.what = what;//这个what是在new Registrant(Handler h, int what, Object obj)进行初始化时赋值的一个成员变量msg.obj = new AsyncResult(userObj, result, exception);h.sendMessage(msg);}}

通过internalNotifyRegistrant方法我们可以发现,msg中包含了消息的类型,msg.obj中包含了我们将要处理的短信对象(SMsMessage对象),然后通过初始化时指定的Handler对象来处理这个msg,因此,我们需要找到这个处理短信数据的对象的Handler类。

在GsmInboundSmsHandler.java的GsmInboundSmsHandler类中发现GsmInboundSmsHandler构造函数中调用了setOnNewGsmSms方法

 frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm\GsmInboundSmsHandler.javaprivate GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,PhoneBase phone) {super("GsmInboundSmsHandler", context, storageMonitor, phone,GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone));phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi);}GsmInboundSmsHandler父类是InboundSmsHandler
InboundSmsHandler的父类是StateMachine
getHandler()是StateMachine类中的方法,返回成员变量private SmHandler mSmHandler;public final Handler getHandler() {return mSmHandler;}

因此,我们可以发现。 mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));这个函数的实质就是,向SmHandler对象发送了一个消息Msg,消息的类型是EVENT_NEW_SMS,消息包含的对象时短信SmsMessgae对象。

至此,第一部分RIL.java部分的短信处理完毕

第二部分:StateMachine,InboundSmsHandler,GsmInboundSmsHandler 通过状态机处理短信接收流程

这一部分是和android4.X版本中的短信接收较为不同的部分。这部分使用的是一个状态机的设计模式来解决短信问题。(暂未完全理解)

接下来涉及到的主要三个类StateMachine,InboundSmsHandler,GsmInboundSmsHandler,他们之间是继承的关系,InboundSmsHandler 继承自StateMachine,GsmInboundSmsHandler继承自InboundSmsHandler。

在第二部分的StateMachine类中主要是通过StateMachine的内部类SmHandler来进行消息的分发处理。(SmHandler代码都在StateMachine.java中)

(通过时序图我们可以发现StateMachine(SmHandler)主要是处理消息的分发,主要是负责到达短信的处理, GsmInboundSmsHandler仅负责Gsm短信相关的判断处理。我们可以发现,消息的分发是最一般的处理,短信处理是次一般的处理,而Gsm短信则是最特殊的处理。不得不说,这源码写的真的漂亮)

在第一部分中RIL层向SmHandler对象发送了一个类型为EVENT_NEW_SMS的消息。由Handler机制,我们可以知道,必然会通过SmHandler的handleMessage方法进行处理,即时序图中的第5步。

6,SmHandler的handleMessage方法主要是就是调用SmHandler的processMsg方法来处理消息。


private final State processMsg(Message msg) {StateInfo curStateInfo = mStateStack[mStateStackTopIndex];if (mDbg) {mSm.log("processMsg: " + curStateInfo.state.getName());}if (isQuit(msg)) {transitionTo(mQuittingState);} else {while (!curStateInfo.state.processMessage(msg)) {/*** Not processed*/curStateInfo = curStateInfo.parentStateInfo;if (curStateInfo == null) {/*** No parents left so it's not handled*/mSm.unhandledMessage(msg);break;}if (mDbg) {mSm.log("processMsg: " + curStateInfo.state.getName());}}}return (curStateInfo != null) ? curStateInfo.state : null;}

这里需要注意curStateInfo.state是一个State对象,主要包括在InboundSmsHandler类中定义几个内部类,DefaultState,StartupState,IdleState,DeliveringState,WaitingState这5个State之间相关转换,这5个类都是继承自State类。

我是这么理解InboundSmsHandler的,中文表述成,已到达短信处理机,这个处理机有5个状态,分别是DefaultState,StartupState,IdleState,DeliveringState,WaitingState。在我的调试过程中,主要是两个状态的转换,当第一次调用SmHandler的processMsg方法时,curStateInfo.state.processMessage(msg)是通过WaitingState类的processMessage方法处理消息,然后无法进行处理返回后,通过curStateInfo = curStateInfo.parentStateInfo;把WaitingState变成其父状态DeliveringState。然后再调用curStateInfo.state.processMessage(msg),即调用DeliveringState的processMessage的方法进行短信消息处理。

 InboundSmsHandler.javaclass DeliveringState extends State {@Overridepublic void enter() {if (DBG) log("entering Delivering state");}@Overridepublic void exit() {if (DBG) log("leaving Delivering state");}@Overridepublic boolean processMessage(Message msg) {log("DeliveringState.processMessage:" + msg.what);switch (msg.what) {case EVENT_NEW_SMS:// handle new SMS from RILhandleNewSms((AsyncResult) msg.obj);sendMessage(EVENT_RETURN_TO_IDLE);return HANDLED;case EVENT_INJECT_SMS:// handle new injected SMShandleInjectSms((AsyncResult) msg.obj);sendMessage(EVENT_RETURN_TO_IDLE);return HANDLED;case EVENT_BROADCAST_SMS:// if any broadcasts were sent, transition to waiting stateif (processMessagePart((InboundSmsTracker) msg.obj)) {transitionTo(mWaitingState);}return HANDLED;case EVENT_RETURN_TO_IDLE:// return to idle after processing all other messagestransitionTo(mIdleState);return HANDLED;case EVENT_RELEASE_WAKELOCK:mWakeLock.release();    // decrement wakelock from previous entry to Idleif (!mWakeLock.isHeld()) {// wakelock should still be held until 3 seconds after we enter Idleloge("mWakeLock released while delivering/broadcasting!");}return HANDLED;// we shouldn't get this message type in this state, log error and halt.case EVENT_BROADCAST_COMPLETE:case EVENT_START_ACCEPTING_SMS:default:// let DefaultState handle these unexpected message typesreturn NOT_HANDLED;}}}

已知消息类型是EVENT_NEW_SMS,即执行EVENT_NEW_SMS分支的代码,即时序图中第13步调用handleNewSms((AsyncResult) msg.obj)

   void handleNewSms(AsyncResult ar) {if (ar.exception != null) {loge("Exception processing incoming SMS: " + ar.exception);return;}int result;try {SmsMessage sms = (SmsMessage) ar.result;result = dispatchMessage(sms.mWrappedSmsMessage);} catch (RuntimeException ex) {loge("Exception dispatching message", ex);result = Intents.RESULT_SMS_GENERIC_ERROR;}// RESULT_OK means that the SMS will be acknowledged by special handling,// e.g. for SMS-PP data download. Any other result, we should ack here.if (result != Activity.RESULT_OK) {boolean handled = (result == Intents.RESULT_SMS_HANDLED);notifyAndAcknowledgeLastIncomingSms(handled, result, null);}}

14,该方法取出消息中包含的SmsMessage对象。然后调用方法dispatchMessage;

15,在dispatchMessage中调用dispatchMessageRadioSpecific方法,该方法是在GsmInboundSmsHandler类中定义的方法。

16,dispatchMessageRadioSpecific方法的最后重新回到InboundSmsHandler.java中的dispatchNormalMessage方法,把短信重新包装成一个InboundSmsTracker对象

17-19,然后调用addTrackerToRawTableAndSendMessage(tracker)方法,该方法会调用父类StateMachine的sendMessage(EVENT_BROADCAST_SMS, tracker)方法,向其内部类SmHandler对象发送一个消息,消息的类型是EVENT_BROADCAST_SMS,消息包含的对象是InboundSmsTracker对象

20-23,StateMachine的内部类SmHandler对象再次处理消息,最后消息也将在DeliveringState的processMessage方法中处理,执行其EVENT_BROADCAST_SMS分支的代码。

24:最后调用InboundSmsHandler类中的processMessagePart((InboundSmsTracker) msg.obj)方法

   /*** Process the inbound SMS segment. If the message is complete, send it as an ordered* broadcast to interested receivers and return true. If the message is a segment of an* incomplete multi-part SMS, return false.* @param tracker the tracker containing the message segment to process* @return true if an ordered broadcast was sent; false if waiting for more message segments*/boolean processMessagePart(InboundSmsTracker tracker) {int messageCount = tracker.getMessageCount();byte[][] pdus;int destPort = tracker.getDestPort();if (messageCount == 1) {// single-part messagepdus = new byte[][]{tracker.getPdu()};} else {// multi-part messageCursor cursor = null;try {// used by several query selection argumentsString address = tracker.getAddress();String refNumber = Integer.toString(tracker.getReferenceNumber());String count = Integer.toString(tracker.getMessageCount());// query for all segments and broadcast message if we have all the partsString[] whereArgs = {address, refNumber, count};cursor = mResolver.query(sRawUri, PDU_SEQUENCE_PORT_PROJECTION,SELECT_BY_REFERENCE, whereArgs, null);int cursorCount = cursor.getCount();if (cursorCount < messageCount) {// Wait for the other message parts to arrive. It's also possible for the last// segment to arrive before processing the EVENT_BROADCAST_SMS for one of the// earlier segments. In that case, the broadcast will be sent as soon as all// segments are in the table, and any later EVENT_BROADCAST_SMS messages will// get a row count of 0 and return.return false;}// All the parts are in place, deal with thempdus = new byte[messageCount][];while (cursor.moveToNext()) {// subtract offset to convert sequence to 0-based array indexint index = cursor.getInt(SEQUENCE_COLUMN) - tracker.getIndexOffset();pdus[index] = HexDump.hexStringToByteArray(cursor.getString(PDU_COLUMN));// Read the destination port from the first segment (needed for CDMA WAP PDU).// It's not a bad idea to prefer the port from the first segment in other cases.if (index == 0 && !cursor.isNull(DESTINATION_PORT_COLUMN)) {int port = cursor.getInt(DESTINATION_PORT_COLUMN);// strip format flags and convert to real port number, or -1port = InboundSmsTracker.getRealDestPort(port);if (port != -1) {destPort = port;}}}} catch (SQLException e) {loge("Can't access multipart SMS database", e);return false;} finally {if (cursor != null) {cursor.close();}}}BroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);if (destPort == SmsHeader.PORT_WAP_PUSH) {// Build up the data streamByteArrayOutputStream output = new ByteArrayOutputStream();for (byte[] pdu : pdus) {// 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done thisif (!tracker.is3gpp2()) {SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);pdu = msg.getUserData();}output.write(pdu, 0, pdu.length);}int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, this);if (DBG) log("dispatchWapPdu() returned " + result);// result is Activity.RESULT_OK if an ordered broadcast was sentreturn (result == Activity.RESULT_OK);}Intent intent = new Intent(Intents.SMS_FILTER_ACTION);List<String> carrierPackages = null;UiccCard card = UiccController.getInstance().getUiccCard();if (card != null) {carrierPackages = card.getCarrierPackageNamesForIntent(mContext.getPackageManager(), intent);}if (carrierPackages != null && carrierPackages.size() == 1) {intent.setPackage(carrierPackages.get(0));intent.putExtra("destport", destPort);} else {setAndDirectIntent(intent, destPort);}intent.putExtra("pdus", pdus);intent.putExtra("format", tracker.getFormat());dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,AppOpsManager.OP_RECEIVE_SMS, resultReceiver, UserHandle.OWNER);return true;}

该方法主要是创建了 BroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);一个广播接收器。

创建了intent,并通过setAndDirectIntent方法把intent的action设置成  Intents.SMS_DELIVER_ACTION。这代表这个广播只能被默认短信应用接收。

最后调用dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,AppOpsManager.OP_RECEIVE_SMS, resultReceiver, UserHandle.OWNER);发送广播。

  /*** Dispatch the intent with the specified permission, appOp, and result receiver, using* this state machine's handler thread to run the result receiver.** @param intent the intent to broadcast* @param permission receivers are required to have this permission* @param appOp app op that is being performed when dispatching to a receiver* @param user user to deliver the intent to*/protected void dispatchIntent(Intent intent, String permission, int appOp,BroadcastReceiver resultReceiver, UserHandle user) {intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());if (user.equals(UserHandle.ALL)) {// Get a list of currently started users.int[] users = null;try {users = ActivityManagerNative.getDefault().getRunningUserIds();} catch (RemoteException re) {}if (users == null) {users = new int[] {user.getIdentifier()};}// Deliver the broadcast only to those running users that are permitted// by user policy.for (int i = users.length - 1; i >= 0; i--) {UserHandle targetUser = new UserHandle(users[i]);if (users[i] != UserHandle.USER_OWNER) {// Is the user not allowed to use SMS?if (mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) {continue;}// Skip unknown users and managed profiles as wellUserInfo info = mUserManager.getUserInfo(users[i]);if (info == null || info.isManagedProfile()) {continue;}}// Only pass in the resultReceiver when the USER_OWNER is processed.mContext.sendOrderedBroadcastAsUser(intent, targetUser, permission, appOp,users[i] == UserHandle.USER_OWNER ? resultReceiver : null,getHandler(), Activity.RESULT_OK, null, null);}} else {mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp,resultReceiver,getHandler(), Activity.RESULT_OK, null, null);}}

29,最后调用sendOrderedBroadcastAsUser方法发送广播,且该广播的最后一个接收者是之前创建的 SmsBroadcastReceiver类型的广播

30,因此,当发送完这条给默认短信应用专用的短信广播后,将会回到SmsBroadcastReceiver的onReceive方法中

    /*** Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and* logs the broadcast duration (as an error if the other receivers were especially slow).*/private final class SmsBroadcastReceiver extends BroadcastReceiver {private final String mDeleteWhere;private final String[] mDeleteWhereArgs;private long mBroadcastTimeNano;SmsBroadcastReceiver(InboundSmsTracker tracker) {mDeleteWhere = tracker.getDeleteWhere();mDeleteWhereArgs = tracker.getDeleteWhereArgs();mBroadcastTimeNano = System.nanoTime();}@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action.equals(Intents.SMS_FILTER_ACTION)) {int rc = getResultCode();if (rc == Activity.RESULT_OK) {// Overwrite pdus data if the SMS filter has set it.Bundle resultExtras = getResultExtras(false);if (resultExtras != null && resultExtras.containsKey("pdus")) {intent.putExtra("pdus", (byte[][]) resultExtras.get("pdus"));}if (intent.hasExtra("destport")) {int destPort = intent.getIntExtra("destport", -1);intent.removeExtra("destport");setAndDirectIntent(intent, destPort);if (SmsManager.getDefault().getAutoPersisting()) {final Uri uri = writeInboxMessage(intent);if (uri != null) {// Pass this to SMS apps so that they know where it is storedintent.putExtra("uri", uri.toString());}}dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.OWNER);} else {loge("destport doesn't exist in the extras for SMS filter action.");}} else {// Drop this SMS.log("SMS filtered by result code " + rc);deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs);sendMessage(EVENT_BROADCAST_COMPLETE);}} else if (action.equals(Intents.SMS_DELIVER_ACTION)) {// Now dispatch the notification only intentintent.setAction(Intents.SMS_RECEIVED_ACTION);intent.setComponent(null);// All running users will be notified of the received sms.dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.ALL);} else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) {// Now dispatch the notification only intentintent.setAction(Intents.WAP_PUSH_RECEIVED_ACTION);intent.setComponent(null);// Only the primary user will receive notification of incoming mms.// That app will do the actual downloading of the mms.dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.OWNER);} else {// Now that the intents have been deleted we can clean up the PDU data.if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)&& !Intents.SMS_RECEIVED_ACTION.equals(action)&& !Intents.DATA_SMS_RECEIVED_ACTION.equals(action)&& !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) {loge("unexpected BroadcastReceiver action: " + action);}int rc = getResultCode();if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) {loge("a broadcast receiver set the result code to " + rc+ ", deleting from raw table anyway!");} else if (DBG) {log("successful broadcast, deleting from raw table.");}deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs);sendMessage(EVENT_BROADCAST_COMPLETE);int durationMillis = (int) ((System.nanoTime() - mBroadcastTimeNano) / 1000000);if (durationMillis >= 5000) {loge("Slow ordered broadcast completion time: " + durationMillis + " ms");} else if (DBG) {log("ordered broadcast completed in: " + durationMillis + " ms");}}}}

看到else if (action.equals(Intents.SMS_DELIVER_ACTION))分支处,重新设置intent的action为 Intents.SMS_RECEIVED_ACTION,然后同样通过dispatchIntent方法,将这条广播发送给所有人。即所有普通应用将收到这条广播。

疑问:为什么sendOrderedBroadcastAsUser方法发送的有序广播无法被截断?

分析完了短信接收,最大的疑问就是都是通过dispatchIntent方法最后调用sendOrderedBroadcastAsUser方法来发送广播,这样子理论上来说都是发送的有序广播。那么和网上的说法发送两条广播一条是发送给默认短信应用的有序广播,一条是发给所有人的无序广播的说法不一致啊。。

接下来,我进行了试验测试,

我写了两个应用A,B,都注册短信广播,并且A的广播优先级高于B,A和B都获取短信后调用abortBroadcast截断广播。

A广播代码:

package com.yyt.sockettest;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;public class SmsBroadCastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubBundle bundleres = getResultExtras(true);if(bundleres==null){Log.e("smsA", "bundleRes null");}else{Log.e("smsA", "bundleRes not null");int xx=bundleres.getInt("myCount");Log.e("Broadcast ResInt", Integer.toString(xx));}bundleres.putInt("myCount", 100);setResultExtras(bundleres);Bundle bundle = intent.getExtras();   Object[] object = (Object[])bundle.get("pdus");   SmsMessage sms[]=new SmsMessage[object.length];   for(int i=0;i<object.length;i++)   {   sms[i] = SmsMessage.createFromPdu((byte[])object[i]);   Toast.makeText(context, "来自"+sms[i].getDisplayOriginatingAddress()+" 的消息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show();   }   Log.e("smssms", sms[0].getDisplayMessageBody());//终止广播,在这里我们可以稍微处理,根据用户输入的号码可以实现短信防火墙。abortBroadcast();   Message msg = Message.obtain();msg.obj = sms[0].getDisplayMessageBody();MainActivity.handler.sendMessage(msg);}}
静态注册的广播,优先级为1000<receiver android:name=".SmsBroadCastReceiver">  <intent-filter android:priority="1000">  <action android:name="android.provider.Telephony.SMS_RECEIVED"/>  </intent-filter>  </receiver>  

B广播代码:

package com.example.testsms2;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;public class SmsBroadCastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubBundle bundleres = getResultExtras(true);if(bundleres==null){Log.e("smsB", "bundleRes null");}else{Log.e("smsB", "bundleRes not null");int xx=bundleres.getInt("myCount");Log.e("Broadcast ResInt22", Integer.toString(xx));}bundleres.putInt("myCount", 500);setResultExtras(bundleres);Bundle bundle = intent.getExtras();   Object[] object = (Object[])bundle.get("pdus");   SmsMessage sms[]=new SmsMessage[object.length];   for(int i=0;i<object.length;i++)   {   sms[i] = SmsMessage.createFromPdu((byte[])object[i]);   Toast.makeText(context, "来自"+sms[i].getDisplayOriginatingAddress()+" 的消息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show();   }   Log.e("smssms2222", sms[0].getDisplayMessageBody());//终止广播,在这里我们可以稍微处理,根据用户输入的号码可以实现短信防火墙。abortBroadcast();   Message msg = Message.obtain();msg.obj = sms[0].getDisplayMessageBody();}}在MainActivity的OnCreate方法中动态注册receiver = new SmsBroadCastReceiver();IntentFilter iFilter =new IntentFilter("android.provider.Telephony.SMS_RECEIVED");iFilter.setPriority(20000);registerReceiver(receiver, iFilter);

模拟发送短信测试后,发现A,B应用都能获取到短信。。。
我又进行测试,通过getResultExtras发现A,B都能获取到非空的budle对象,且B应用输出数字0,A应用输出数字500,说明B确实优先A收到的短信,但是截断不成功。

理论上说如果接收的是无序广播,那么getResultExtras方法返回的值必然是空,而非空,则代表是有序广播,那么无法截断又如何解释呢。。。。。。。

奇怪的问题。。。未完待续。。。。。。。。。。。。。

Android5.0框架层短信接收过程分析相关推荐

  1. Android6.0下的短信接收与发送功能的实现

    最近学习了android6.0下的短信功能,发现<第一行代码>一书中的实现代码中使用的createFromPdu(byte[] pdu)函数,在API23中已经被弃用,取而代之的是crea ...

  2. 手机同步软件(PhoneSync2.0)--新增短信接收功能

    前一篇文章"PyQt开发的手机同步软件(方便的电话本编辑和短信群发功能)"发布了自己写的款手机同步软件,前两天有朋友对该软件提出了一些建议,于是就针对性的改了改,主要是添加了短信接 ...

  3. Android6.0的SMS(短信)源码分析--短信接收

    1     SMS接收流程 Android6.0中对短信的处理比起老版本还是变化有点大的.在分析源代码之前,我们可以先猜测一下Android中接收短信的大致流程.首先根据之前分析phone应用的经验, ...

  4. tp框架融入短信发送和验证

    tp框架融入短信发送和验证 页面布局 <form action="" method="post" id="reg_form">& ...

  5. android 4.2.1短信接收以及应用接收顺序

    先说下android上短信接收的流程,直接从RILJ开始讲.processUnsolicited方法接收到新短信消息后,BaseCommands中注册的事件会通过消息机制执行. RILJ中执行的是如下 ...

  6. android短信接收处理和发送

    关于短信接收处理方面,当前已经有一些app做的比较好了,比如发给手机发验证码验证的问题,很多app在手机接收到验证码后,不需要输入,就直接可以跳过验证界面,这就是用到了对接收到的短信的处理.至于短信的 ...

  7. 【教程】通过lothelper实现短信接收测试

    在日常的应用开发过程中,经常需要进行短信发送测试. 而个人号码又不便接入企业的开发测试环境当中,因此使用lothelper这种公共的短信接收平台就非常方便了. lothelper平台简介:官网直达地址 ...

  8. Zabbix5.0如何发送短信

    Zabbix5.0如何发送短信 本文章主要是介绍如何对接自己的短信平台,不是直接对接运营商. 1.选择报警媒介 也可以创建一个新的报警媒介 2.告警配置 这边选用自己脚本模式,按照自己的短信平台的AP ...

  9. 手机短信接收验证码的实现原理

    关于手机短信接收验证码的实现原理: 思路: A:获得验证码: 1.找到相关的表. 2.用什么发送,post,get ,ajax,当然ajax首选 3.post之前要js先判断是手机号码11位,并且全部 ...

最新文章

  1. Kubernetes 集群无损升级实践
  2. 如何获取并操作listview中的控件
  3. uva 10047 the monocyle (四维bfs)
  4. win10虚拟机dhcp服务器设置,win10 dhcp服务器设置方法
  5. ubuntu安装matlab2009,Ubuntu中安装Matlab2010a
  6. 数据结构与算法--7.树的基础知识
  7. ARM Linux.2.6.34内核移植
  8. ajax jsonp img
  9. Python内置函数(66)——vars
  10. 根据经纬度和日期计算日出日落时间
  11. 恢复Windows默认文件资源管理器(Files设置后,恢复亲测可用)
  12. oeasy php,oeasy之PhotoshopCS3视频教程 - 轻松自学网
  13. 改进维纳滤波的实现——光学稀疏孔径成像系统图像恢复算法研究 陈灏
  14. swagger knife4j 解决接口下载文件响应乱码问题
  15. JVM3:实战:内存分配与回收策略
  16. 微信小程序获取input输入框的值
  17. [论文阅读1]Re-identification with RGB-D sensors
  18. 算法4 Java解答 2.4.18
  19. ITK 数据表达(图像)
  20. 女朋友让你帮他破解邻居家的wifi?看完这篇文章你就会了

热门文章

  1. 批量删除电脑或手机中的空文件夹
  2. 在html中字怎么修改位置,css怎么设置字体位置?
  3. MATLAB语音信号处理
  4. Mybatis-----实验小结
  5. jmeter常见问题总结
  6. 【腾讯BUG】QQ群贴超大表情BUG,恶意炸群BUG
  7. 蓝桥杯练习 小明上楼梯(递归设计)
  8. 【JavaScript】JavaScript模拟实现面向对象一张图帮助你深刻理解原型链和原型对象
  9. 三器六垢_本初行者劉暢友居士浅谈如何学佛(三)
  10. 社区版pycharm的django创建app失败问题解决