200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Android短信发送流程之普通短信发送(原)

Android短信发送流程之普通短信发送(原)

时间:2020-06-10 04:40:53

相关推荐

Android短信发送流程之普通短信发送(原)

我们先来看最简单的流程入手分析,即收件人只有一个,而且不是长短信的情况

一、地址有效性检测

当点击发送按钮时,触发onClick事件:

[java]view plaincopy@ComposeMessageActivity.java publicvoidonClick(Viewv){ if((v==mSendButtonSms||v==mSendButtonMms)&&isPreparedForSending()){ //确认发送 confirmSendMessageIfNeeded(); }elseif((v==mRecipientsPicker)){ launchMultiplePhonePicker(); } }然后进行收件人地址信息的确认

[java]view plaincopyprivatevoidconfirmSendMessageIfNeeded(){ if(!isRecipientsEditorVisible()){ //当前的收件人编辑框不可见,说明所发送的对象已经存在短信的会话,也说明当前的收件人地址是ok的 sendMessage(true); return; } //判断是否为MMS booleanisMms=mWorkingMessage.requiresMms(); if(mRecipientsEditor.hasInvalidRecipient(isMms)){ //当前的收件人列表中包含无效地址 if(mRecipientsEditor.hasValidRecipient(isMms)){ //当前的收件人列表中有无效地址和有效地址,提示用户是否忽略,只发送有效的地址 Stringtitle=getResourcesString(R.string.has_invalid_recipient, mRecipientsEditor.formatInvalidNumbers(isMms)); newAlertDialog.Builder(this) .setTitle(title) .setMessage(R.string.invalid_recipient_message) .setPositiveButton(R.string.try_to_send, newSendIgnoreInvalidRecipientListener()) .setNegativeButton(R.string.no,newCancelSendingListener()) .show(); }else{ //当前的收件人列表中的地址全部无效,取消发送,提示用户 newAlertDialog.Builder(this) .setTitle(R.string.cannot_send_message) .setMessage(R.string.cannot_send_message_reason) .setPositiveButton(R.string.yes,newCancelSendingListener()) .show(); } }else{ //收件人地址都是有效的,发送 ContactListcontacts=mRecipientsEditor.constructContactsFromInput(false); mDebugRecipients=contacts.serialize(); sendMessage(true); } }经过地址有效性检测后,通过sendMessage()继续流程,这里传递的bCheckEcmMode参数代表是否检查当前Phone的状态,处于紧急状态时无法发送短信:

[java]view plaincopyprivatevoidsendMessage(booleanbCheckEcmMode){ if(bCheckEcmMode){ //判断当前是否为紧急呼叫模式 StringinEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE); if(Boolean.parseBoolean(inEcm)){ try{ //紧急状态下,无法发送短彩信 startActivityForResult(newIntent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS,null),REQUEST_CODE_ECM_EXIT_DIALOG); return; }catch(ActivityNotFoundExceptione){ Log.e(TAG,"CannotfindEmergencyCallbackModeExitDialog",e); } } } //判断当前是否有短信正在发送 if(!mSendingMessage){ //重置收件人控件的监听器 removeRecipientsListeners(); //进入WorkingMessage处理流程 mWorkingMessage.send(mDebugRecipients); mSentMessage=true; mSendingMessage=true; addRecipientsListeners(); mScrollOnSend=true;//inthenextonQueryComplete,scrollthelisttotheend. } //Butbailoutifwearesupposedtoexitafterthemessageissent. if(mSendDiscreetMode){ finish(); } }

二、创建短彩信的发送线程

在sendMessage()中经过对当前紧急服务的处理,然后判断如果当前没有短信正在发送,则通过WorkingMessage发送短信。这里的WorkingMessage是处理当前所编辑的信息的工具类,没有父类,在ComposeMessageActivity界面被创建时或者短信被发送出去时创建,主要负责区分短彩信的流程以及发送短信时UI的更新

[java]view plaincopy@WorkingMessage.java publicvoidsend(finalStringrecipientsInUI){ longorigThreadId=mConversation.getThreadId(); removeSubjectIfEmpty(true/*notify*/); prepareForSave(true/*notify*/); //拿到当前的会话 finalConversationconv=mConversation; StringmsgTxt=mText.toString(); if(requiresMms()||addressContainsEmailToMms(conv,msgTxt)){ //彩信发送 if(MmsConfig.getUaProfUrl()==null){ Stringerr="WorkingMessage.sendMMSsendingfailure.mms_config.xmlis"+ "missinguaProfUrlsetting.uaProfUrlisrequiredforMMSservice,"+ "butcanbeabsentforSMS."; RuntimeExceptionex=newNullPointerException(err); Log.e(TAG,err,ex); //now,let'sjustcrash. throwex; } finalUrimmsUri=mMessageUri; finalPduPersisterpersister=PduPersister.getPduPersister(mActivity); finalSlideshowModelslideshow=mSlideshow; finalCharSequencesubject=mSubject; finalbooleantextOnly=mAttachmentType==TEXT;//彩信发送线程 newThread(newRunnable(){ @Override publicvoidrun(){ finalSendReqsendReq=makeSendReq(conv,subject); slideshow.prepareForSend(); sendMmsWorker(conv,mmsUri,persister,slideshow,sendReq,textOnly); updateSendStats(conv); } },"WorkingMessage.sendMMS").start(); }else{ //短信发送流程 finalStringmsgText=mText.toString(); newThread(newRunnable(){ @Override publicvoidrun(){ preSendSmsWorker(conv,msgText,recipientsInUI); updateSendStats(conv); } },"WorkingMessage.sendSMS").start(); } //updatetheRecipientcachewiththenewtoaddress,ifit'sdifferent RecipientIdCache.updateNumbers(conv.getThreadId(),conv.getRecipients()); //Markthemessageasdiscardedbecauseitis"offthemarket"afterbeingsent. mDiscarded=true; }在上面的send流程中,WorkingMessage对短彩信进行分类,分别创建子线程进行发送,本节我们只关注短信流程,他是在preSendSmsWorker()中被发送的:

[java]view plaincopyprivatevoidpreSendSmsWorker(Conversationconv,StringmsgText,StringrecipientsInUI){ UserHappinessSignals.userAcceptedImeText(mActivity); //UI刷新 mStatusListener.onPreMessageSent(); //获取初始的线程ID longorigThreadId=conv.getThreadId(); //获取分配的线程ID longthreadId=conv.ensureThreadId(); StringsemiSepRecipients=conv.getRecipients().serialize(); //recipientsInUIcanbeemptywhentheusertypesinanumberandhitssend if(LogTag.SEVERE_WARNING&&((origThreadId!=0&&origThreadId!=threadId)||(!semiSepRecipients.equals(recipientsInUI)&&!TextUtils.isEmpty(recipientsInUI)))){ }else{ //发送短信 sendSmsWorker(msgText,semiSepRecipients,threadId); //删除草稿 deleteDraftSmsMessage(threadId); } }

在上面的preSendSmsWorker中进行了四个处理:

1、更新UI(更新编辑框等控件);

2、获取当前发送的ThreadID;

3、发送短信;

4、删除草稿;

接下来我们继续来看发送的过程:

[java]view plaincopyprivatevoidsendSmsWorker(StringmsgText,StringsemiSepRecipients,longthreadId){ //获取当前发送的收件人地址 String[]dests=TextUtils.split(semiSepRecipients,";"); //获取MessageSender对象,传递进去4个参数分别为:收件人、信息文本、当前的threadId、SimID。 MessageSendersender=newSmsMessageSender(mActivity,dests,msgText,threadId); try{ //通过MessageSender发送出去 sender.sendMessage(threadId); //Makesurethisthreadisn'toverthelimitsinmessagecount Recycler.getSmsRecycler().deleteOldMessagesByThreadId(mActivity,threadId); }catch(Exceptione){ Log.e(TAG,"FailedtosendSMSmessage,threadId="+threadId,e); } //更新UI mStatusListener.onMessageSent(); MmsWidgetProvider.notifyDatasetChanged(mActivity); }

经过上面WorkingMessage的sendSmsWorker过程,创建了MessageSender对象,并通过该对象的sendMessage()方法将信息发送出去,并在发送之后再次更新UI界面(正在发送中)。

三、通过SmsMessageSender拆分多个收件人

上面创建的MessageSender对象,继承自MessageSender接口,主要方法只有三个:

[java]view plaincopypublicbooleansendMessage(longtoken)throwsMmsException{}; privatebooleanqueueMessage(longtoken)throwsMmsException{}; privateStringgetOutgoingServiceCenter(longthreadId){};他的主要作用就是对当前收件人信息拆分后,把群发的短信构建成一个短信队列并保存在数据库中,然后通知SmsReceiverService将队列读取出来并发送出去。

下面来看其具体实现过程。

[java]view plaincopy@SmsMessageSender.java publicbooleansendMessage(longtoken)throwsMmsException{ returnqueueMessage(token); } privatebooleanqueueMessage(longtoken)throwsMmsException{ if((mMessageText==null)||(mNumberOfDests==0)){ //空信息不能发送 thrownewMmsException("Nullmessagebodyordest."); } SharedPreferencesprefs=PreferenceManager.getDefaultSharedPreferences(mContext); booleanrequestDeliveryReport=prefs.getBoolean( MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE, DEFAULT_DELIVERY_REPORT_MODE); //根据当前短信的收件人数目,遍历当前的发送队列 for(inti=0;i<mNumberOfDests;i++){ try{ //将当前要发送的短消息放入发送队列中 Sms.addMessageToUri(mContext.getContentResolver(), Uri.parse("content://sms/queued"),mDests[i], mMessageText,null,mTimestamp, true/*read*/, requestDeliveryReport, mThreadId); }catch(SQLiteExceptione){ if(LogTag.DEBUG_SEND){ Log.e(TAG,"queueMessageSQLiteException",e); } SqliteWrapper.checkSQLiteException(mContext,e); } } //通知SmsReceiverService发送短信 mContext.sendBroadcast(newIntent(SmsReceiverService.ACTION_SEND_MESSAGE, null, mContext, SmsReceiver.class)); returnfalse; }在上面这个过程中,将收件人地址拆分后,生成一个短信队列放入"content://sms/queued"中,然后给SmsReceiver发送了通知,这里的SmsReceiver作用仅仅是将该通知转发给SmsReceiverService而已:

[java]view plaincopy@SmsReceiver.java publicvoidonReceive(Contextcontext,Intentintent){ onReceiveWithPrivilege(context,intent,false); } protectedvoidonReceiveWithPrivilege(Contextcontext,Intentintent,booleanprivileged){ if(!privileged&&intent.getAction().equals(Intents.SMS_DELIVER_ACTION)){ return; } //将请求转交给SmsReceiverService来处理 intent.setClass(context,SmsReceiverService.class); intent.putExtra("result",getResultCode()); beginStartingService(context,intent); }也就是说,SmsMessageSender将要发送的短信放入队列中之后,经过SmsReceiver将该消息发送给了SmsReceiverService, 这里的SmsReceiverService是负责短信的收发的Service。

下面来看SmsReceiverService对于发送短消息的处理过程。

这个Service被创建时,会创建一个子线程(HandlerThread)以及该线程的Handler对象(ServiceHandler):

[java]view plaincopy@SmsReceiverService.java publicvoidonCreate(){ //创建子线程处理各种消息 HandlerThreadthread=newHandlerThread(TAG,Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mServiceLooper=thread.getLooper(); mServiceHandler=newServiceHandler(mServiceLooper); }当该Service被启动时,就会对当前的请求进行处理:

[java]view plaincopypublicintonStartCommand(Intentintent,intflags,intstartId){ mResultCode=intent!=null?intent.getIntExtra("result",0):0; //通知Handler处理当前的请求 Messagemsg=mServiceHandler.obtainMessage(); msg.arg1=startId; msg.obj=intent; mServiceHandler.sendMessage(msg); returnService.START_NOT_STICKY; }然后看当前Handler的处理:[java]view plaincopyprivatefinalclassServiceHandlerextendsHandler{ publicServiceHandler(Looperlooper){ super(looper); } @Override publicvoidhandleMessage(Messagemsg){ intserviceId=msg.arg1; Intentintent=(Intent)msg.obj; if(intent!=null&&MmsConfig.isSmsEnabled(getApplicationContext())){ Stringaction=intent.getAction(); interror=intent.getIntExtra("errorCode",0); if(MESSAGE_SENT_ACTION.equals(intent.getAction())){ handleSmsSent(intent,error); }elseif(SMS_DELIVER_ACTION.equals(action)){ handleSmsReceived(intent,error); }elseif(ACTION_BOOT_COMPLETED.equals(action)){ handleBootCompleted(); }elseif(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)){ handleServiceStateChanged(intent); }elseif(ACTION_SEND_MESSAGE.endsWith(action)){ //发送短信 handleSendMessage(); }elseif(ACTION_SEND_INACTIVE_MESSAGE.equals(action)){ handleSendInactiveMessage(); } } SmsReceiver.finishStartingService(SmsReceiverService.this,serviceId); } }从上面的case分支中我们看到,对于当前的发送短信的请求(ACTION_SEND_MESSAGE)将会通过handleSendMessage()来处理:[java]view plaincopyprivatevoidhandleSendMessage(){ if(!mSending){ //当前没有其他任务时就触发发送的操作 sendFirstQueuedMessage(); } } publicsynchronizedvoidsendFirstQueuedMessage(){ booleansuccess=true; finalUriuri=Uri.parse("content://sms/queued"); ContentResolverresolver=getContentResolver(); //从队列中拿到要发送的短信 Cursorc=SqliteWrapper.query(this,resolver,uri,SEND_PROJECTION,null,null,"dateASC"); if(c!=null){ try{ //发送队列中第一条短信 if(c.moveToFirst()){ StringmsgText=c.getString(SEND_COLUMN_BODY); Stringaddress=c.getString(SEND_COLUMN_ADDRESS); intthreadId=c.getInt(SEND_COLUMN_THREAD_ID); intstatus=c.getInt(SEND_COLUMN_STATUS); intmsgId=c.getInt(SEND_COLUMN_ID); UrimsgUri=ContentUris.withAppendedId(Sms.CONTENT_URI,msgId); //构建SmsSingleRecipientSender对象 SmsMessageSendersender=newSmsSingleRecipientSender(this, address,msgText,threadId,status==Sms.STATUS_PENDING, msgUri); try{ //发送 sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);; mSending=true; }catch(MmsExceptione){ mSending=false; messageFailedToSend(msgUri,SmsManager.RESULT_ERROR_GENERIC_FAILURE); success=false; sendBroadcast(newIntent(SmsReceiverService.ACTION_SEND_MESSAGE, null, this, SmsReceiver.class)); } } }finally{ c.close(); } } if(success){ unRegisterForServiceStateChanges(); } }

我们看到,经过SmsReceiverService中Handler的处理,将数据库中的当前要发送的短信队列取出来,然后取出队列中第一个短消息任务,通过SmsSingleRecipientSender的sendMessage()方法发送出去。至此SmsReceiverService的流程就走完了,他的作用主要就是拿到队列中的第一条短消息,构建SmsSingleRecipientSender对象并发送出去

四、通过SmsSingleRecipientSender拆分长短信

SmsSingleRecipientSender类继承自SmsMessageSender,他所提供的方法只有一个:

[java]view plaincopypublicbooleansendMessage(longtoken)throwsMmsException{};其处理内容就是对长短消息进行分割。然后注册两个广播(一个用于广播当前正在发送,另一个广播短信的送达状态报告),之后通过SmsManager发送出去。[java]view plaincopy@SmsSingleRecipientSender.java publicbooleansendMessage(longtoken)throwsMmsException{ if(mMessageText==null){ thrownewMmsException("Nullmessagebodyorhavemultipledestinations."); } SmsManagersmsManager=SmsManager.getDefault(); ArrayList<String>messages=null; //拆分长短信 if((MmsConfig.getEmailGateway()!=null)&&(Mms.isEmailAddress(mDest)||MessageUtils.isAlias(mDest))){ //彩信 StringmsgText; msgText=mDest+""+mMessageText; mDest=MmsConfig.getEmailGateway(); messages=smsManager.divideMessage(msgText); }else{ //短信 messages=smsManager.divideMessage(mMessageText); mDest=PhoneNumberUtils.stripSeparators(mDest); mDest=Conversation.verifySingleRecipient(mContext,mThreadId,mDest); } intmessageCount=messages.size(); if(messageCount==0){ thrownewMmsException("SmsMessageSender.sendMessage:divideMessagereturned"+"emptymessages.Originalmessageis\""+mMessageText+"\""); } booleanmoved=Sms.moveMessageToFolder(mContext,mUri,Sms.MESSAGE_TYPE_OUTBOX,0); if(!moved){ thrownewMmsException("SmsMessageSender.sendMessage:couldn'tmovemessage"+"tooutbox:"+mUri); } ArrayList<PendingIntent>deliveryIntents=newArrayList<PendingIntent>(messageCount); ArrayList<PendingIntent>sentIntents=newArrayList<PendingIntent>(messageCount); for(inti=0;i<messageCount;i++){ if(mRequestDeliveryReport&&(i==(messageCount-1))){ //所有短信被发送完毕后,在最后一条短信后面添加送达报告的Intent deliveryIntents.add(PendingIntent.getBroadcast( mContext,0, newIntent( MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION, mUri, mContext, MessageStatusReceiver.class), 0)); }else{ deliveryIntents.add(null); } //对于拆分后的短消息,需要在每条信息发送完毕后发送该Intent,从而接着发送剩下的拆分短信 Intentintent=newIntent(SmsReceiverService.MESSAGE_SENT_ACTION, mUri, mContext, SmsReceiver.class); intrequestCode=0; if(i==messageCount-1){ //收到该附加数据说明当前的拆分短信已经发送完毕 requestCode=1; intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT,true); } sentIntents.add(PendingIntent.getBroadcast(mContext,requestCode,intent,0)); } try{ //发送 smsManager.sendMultipartTextMessage(mDest,mServiceCenter,messages,sentIntents,deliveryIntents); }catch(Exceptionex){ thrownewMmsException("SmsMessageSender.sendMessage:caught"+ex+"fromSmsManager.sendTextMessage()"); } returnfalse; }经过上面的准备过程,在通过SmsManager发送信息之前,还添加了两个Intent:SmsReceiverService.MESSAGE_SENT_ACTION和MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION。这两个Intent的作用分别是:

MESSAGE_STATUS_RECEIVED_ACTION:当所有长短信(或短消息)发送完毕后,发送该Intent。

MESSAGE_SENT_ACTION:分割后的短消息,每发送一条,都会发送该Intent,当最后一条发送完毕后,将会在该Intent中附加EXTRA_MESSAGE_SENT_SEND_NEXT=true的数据

具体细节在发送完毕后再分析。

接下来看SmsManager,这里的SmsManager是单例模型,通过其自己的getDefault()或者getSmsManagerForSubscriber()方法就可以得到该对象。[java]view plaincopy@SmsManager.java publicvoidsendMultipartTextMessage(StringdestinationAddress,StringscAddress,ArrayList<String>parts,ArrayList<PendingIntent>sentIntents,ArrayList<PendingIntent>deliveryIntents){ if(TextUtils.isEmpty(destinationAddress)){ thrownewIllegalArgumentException("InvaliddestinationAddress"); } if(parts==null||parts.size()<1){ thrownewIllegalArgumentException("Invalidmessagebody"); } if(parts.size()>1){ //长短信发送 try{ ISmsiccISms=getISmsServiceOrThrow(); iccISms.sendMultipartText(ActivityThread.currentPackageName(), destinationAddress,scAddress,parts, sentIntents,deliveryIntents); }catch(RemoteExceptionex){ } }else{ //普通短信发送 PendingIntentsentIntent=null; PendingIntentdeliveryIntent=null; if(sentIntents!=null&&sentIntents.size()>0){ sentIntent=sentIntents.get(0); } if(deliveryIntents!=null&&deliveryIntents.size()>0){ deliveryIntent=deliveryIntents.get(0); } sendTextMessage(destinationAddress,scAddress,parts.get(0), sentIntent,deliveryIntent); } }在上面的流程中区分了长短信和普通短信的流程,我们目前只分析普通短消息,继续看sendTextMessage():[java]view plaincopypublicvoidsendTextMessage(StringdestinationAddress,StringscAddress,Stringtext,PendingIntentsentIntent,PendingIntentdeliveryIntent){ if(TextUtils.isEmpty(destinationAddress)){ thrownewIllegalArgumentException("InvaliddestinationAddress"); } if(TextUtils.isEmpty(text)){ thrownewIllegalArgumentException("Invalidmessagebody"); } try{ //继续 ISmsiccISms=getISmsServiceOrThrow(); iccISms.sendText(ActivityThread.currentPackageName(),destinationAddress,scAddress,text,sentIntent,deliveryIntent); }catch(RemoteExceptionex){ } }

到这里,SmsMessage通过调用iccISms对象的sendText()方法将短信继续传递,而SmsMessage的流程就此结束。

五、发送单条短信

上面的iccISms对象是UiccSmsController的客户端:

[java]view plaincopyprivatestaticISmsgetISmsService(){ returnISms.Stub.asInterface(ServiceManager.getService("isms")); }所以接下来我们需要进入UiccSmsController的流程中分析:

[java]view plaincopy@UiccSmsController.java publicvoidsendText(StringcallingPackage,StringdestAddr,StringscAddr,Stringtext,PendingIntentsentIntent,PendingIntentdeliveryIntent){ sendTextForSubscriber(getPreferredSmsSubscription(),callingPackage,destAddr,scAddr,text,sentIntent,deliveryIntent); } publicvoidsendTextForSubscriber(longsubId,StringcallingPackage,StringdestAddr,StringscAddr,Stringtext,PendingIntentsentIntent,PendingIntentdeliveryIntent){ IccSmsInterfaceManagericcSmsIntMgr=getIccSmsInterfaceManager(subId); if(iccSmsIntMgr!=null){ //通过IccSmsInterfaceManager发送短信 iccSmsIntMgr.sendText(callingPackage,destAddr,scAddr,text,sentIntent,deliveryIntent); }else{ } }在上面的UiccSmsController中将任务交给IccSmsInterfaceManager来继续处理。

IccSmsInterfaceManager这个类没有父类,他在创建PhoneProxy的时候进行初始化,其作用是把请求发送给相应的处理者。比如对于sendText()将会转交给ImsSMSDispatcher来实现。[java]view plaincopy@IccSmsInterfaceManager.java publicvoidsendText(StringcallingPackage,StringdestAddr,StringscAddr,Stringtext,PendingIntentsentIntent,PendingIntentdeliveryIntent){ //是否声明了发短信的权限 mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS,"SendingSMSmessage"); //该操作是否被用户允许 if(mAppOps.noteOp(AppOpsManager.OP_SEND_SMS,Binder.getCallingUid(),callingPackage)!=AppOpsManager.MODE_ALLOWED){ return; } //调用ImsSMSDispatcher发送 destAddr=filterDestAddress(destAddr); mDispatcher.sendText(destAddr,scAddr,text,sentIntent,deliveryIntent,null,callingPackage); }在上面这个过程中,先进行两级权限检查,然后通过ImsSMSDispatcher发送信息。

SMSDispatcher总共派生出三个子类:CdmaSMSDispatcher、GsmSMSDispatcher、ImsSMSDispatcher,在IccSmsInterfaceManager创建时只创建ImsSMSDispatcher,而在ImsSMSDispatcher创建过程中会对创建其他两种制式的SMSDispatcher,IccSmsInterfaceManager把请求发送给ImsSMSDispatcher后,由ImsSMSDispatcher根据当前网络状态选择使用CdmaSMSDispatcher还是GsmSMSDispatcher。[java]view plaincopy@ImsSMSDispatcher.java protectedvoidsendText(StringdestAddr,StringscAddr,Stringtext,PendingIntentsentIntent,PendingIntentdeliveryIntent,UrimessageUri,StringcallingPkg){ //根据当前网络类型发送,我们只分析GSM if(isCdmaMo()){ mCdmaDispatcher.sendText(destAddr,scAddr, text,sentIntent,deliveryIntent,messageUri,callingPkg); }else{ mGsmDispatcher.sendText(destAddr,scAddr, text,sentIntent,deliveryIntent,messageUri,callingPkg); } }在上面的过程中,根据当前网络环境使用不同的SMSDispatcher,对于GSM网络来说,当前使用的是GsmSMSDispatcher对象。

这是Framework层与RILJ最接近的对象,他将请求发送给RILJ。[java]view plaincopy@GsmSMSDispatcher.java protectedvoidsendText(StringdestAddr,StringscAddr,Stringtext,PendingIntentsentIntent,PendingIntentdeliveryIntent,UrimessageUri,StringcallingPkg){ //对短信内容进行编码 SmsMessage.SubmitPdupdu=SmsMessage.getSubmitPdu(scAddr,destAddr,text,(deliveryIntent!=null)); if(pdu!=null){ if(messageUri==null){ if(SmsApplication.shouldWriteMessageForPackage(callingPkg,mContext)){ //写入发件箱 messageUri=writeOutboxMessage( getSubId(), destAddr, text, deliveryIntent!=null, callingPkg); } }else{ //移到发件箱 moveToOutbox(getSubId(),messageUri,callingPkg); } HashMapmap=getSmsTrackerMap(destAddr,scAddr,text,pdu); //发送 SmsTrackertracker=getSmsTracker(map,sentIntent,deliveryIntent,getFormat(),messageUri,false); sendRawPdu(tracker); }else{ } }在上面的过程中,对短消息内容进行编码,然后把短消息写入(或移入)发件箱,然后利用当前的发地址、收地址、文本、附加Intent等信息创建SmsTracker对象,然后调用sendRawPdu(),这个方法是在GsmSMSDispatcher的父类SMSDispatcher中实现的:[java]view plaincopy@SMSDispatcher.java protectedvoidsendRawPdu(SmsTrackertracker){ HashMapmap=tracker.mData; bytepdu[]=(byte[])map.get("pdu"); if(mSmsSendDisabled){ tracker.onFailed(mContext,RESULT_ERROR_NO_SERVICE,0/*errorCode*/); return; } if(pdu==null){ tracker.onFailed(mContext,RESULT_ERROR_NULL_PDU,0/*errorCode*/); return; } PackageManagerpm=mContext.getPackageManager(); String[]packageNames=pm.getPackagesForUid(Binder.getCallingUid()); if(packageNames==null||packageNames.length==0){ //RefusetosendSMSifwecan'tgetthecallingpackagename. tracker.onFailed(mContext,RESULT_ERROR_GENERIC_FAILURE,0/*errorCode*/); return; } //Getpackageinfoviapackagemanager PackageInfoappInfo; try{ //XXXthisislossy-appscanshareaUID appInfo=pm.getPackageInfo(packageNames[0],PackageManager.GET_SIGNATURES); }catch(PackageManager.NameNotFoundExceptione){ Rlog.e(TAG,"Can'tgetcallingapppackageinfo:refusingtosendSMS"); tracker.onFailed(mContext,RESULT_ERROR_GENERIC_FAILURE,0/*errorCode*/); return; } //checkDestination()returnstrueifthedestinationisnotapremiumshortcodeorthe //sendingappisapprovedtosendtoshortcodes.Otherwise,amessageissenttoour //handlerwiththeSmsTrackertorequestuserconfirmationbeforesending. if(checkDestination(tracker)){ //checkforexcessiveoutgoingSMSusagebythisapp if(!mUsageMonitor.check(appInfo.packageName,SINGLE_PART_SMS)){ sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION,tracker)); return; } //发送 sendSms(tracker); } }这里会对要发送的信息以及当前环境进行检测,然后进入sendSms()流程,这个方法又回到了GsmSMSDispatcher中实现:[java]view plaincopy@GsmSMSDispatcher.java protectedvoidsendSms(SmsTrackertracker){ HashMap<String,Object>map=tracker.mData; bytepdu[]=(byte[])map.get("pdu"); if(tracker.mRetryCount>0){ //perTS23.040Section9.2.3.6:IfTP-MTISMS-SUBMIT(0x01)type //TP-RD(bit2)is1forretry //andTP-MRissettopreviouslyfailedsmsTP-MR if(((0x01&pdu[0])==0x01)){ pdu[0]|=0x04;//TP-RD pdu[1]=(byte)tracker.mMessageRef;//TP-MR } } //SendSMSviathecarrierapp. BroadcastReceiverresultReceiver=newSMSDispatcherReceiver(tracker); Intentintent=newIntent(Intents.SMS_SEND_ACTION); StringcarrierPackage=getCarrierAppPackageName(intent); if(carrierPackage!=null){ intent.setPackage(carrierPackage); intent.putExtra("pdu",pdu); intent.putExtra("smsc",(byte[])map.get("smsc")); intent.putExtra("format",getFormat()); if(tracker.mSmsHeader!=null&&tracker.mSmsHeader.concatRef!=null){ SmsHeader.ConcatRefconcatRef=tracker.mSmsHeader.concatRef; intent.putExtra("concat.refNumber",concatRef.refNumber); intent.putExtra("concat.seqNumber",concatRef.seqNumber); intent.putExtra("concat.msgCount",concatRef.msgCount); } intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); Rlog.d(TAG,"SendingSMSbycarrierapp."); mContext.sendOrderedBroadcast(intent,android.Manifest.permission.RECEIVE_SMS, AppOpsManager.OP_RECEIVE_SMS,resultReceiver, null,Activity.RESULT_CANCELED,null,null); }else{ //发送 sendSmsByPstn(tracker); } }然后来看sendSmsByPstn():[java]view plaincopyprotectedvoidsendSmsByPstn(SmsTrackertracker){ intss=mPhone.getServiceState().getState(); if(!isIms()&&ss!=ServiceState.STATE_IN_SERVICE){ tracker.onFailed(mContext,getNotInServiceError(ss),0/*errorCode*/); return; } //拿到SmsTracker中保存的信息 HashMap<String,Object>map=tracker.mData; bytesmsc[]=(byte[])map.get("smsc"); byte[]pdu=(byte[])map.get("pdu"); Messagereply=obtainMessage(EVENT_SEND_SMS_COMPLETE,tracker); if(0==tracker.mImsRetry&&!isIms()){ if(tracker.mRetryCount>0){ if(((0x01&pdu[0])==0x01)){ pdu[0]|=0x04;//TP-RD pdu[1]=(byte)tracker.mMessageRef;//TP-MR } } if(tracker.mRetryCount==0&&tracker.mExpectMore){ //调用RILJ发送短信 mCi.sendSMSExpectMore(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu),reply); }else{ mCi.sendSMS(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu),reply); } }else{ //通过IMS发送短信 mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu),tracker.mImsRetry, tracker.mMessageRef,reply); //incrementithere,soincaseofSMS_FAIL_RETRYoverIMS //nextretrywillbesentusingIMSrequestagain. tracker.mImsRetry++; } }在上面的发送之前,将SmsTracker中的内容解析出来,通过RILJ发送出去。并且注册了该请求的回应消息EVENT_SEND_SMS_COMPLETE,用于处理短信接收时的流程。

以上就是普通单收件人,短信的发送流程。

整个过程的流程图如下:

下一节来介绍长短信的发送流程

Source:/u010961631/article/details/50272705

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。