1.      点击发送按钮Src/com/android/mms/ui/ComposeMessageActivity.javapublic void onClick(View v) {if ((v == mSendButton) && isPreparedForSending()) {confirmSendMessageIfNeeded(); //确认是否需要发送短信—-》}}2.src/com/android/mms/ui/ComposeMessageActivity.javaprivate void confirmSendMessageIfNeeded() {if (!isRecipientsEditorVisible()) {  //编辑联系人不可见时,也就是给已存在会话的联系人发送短信时sendMessage(true);return;}boolean isMms = mWorkingMessage.requiresMms();   //是否需要以彩信形式发送if (mRecipientsEditor.hasInvalidRecipient(isMms)) {//是否含有不合法的收件人if (mRecipientsEditor.hasValidRecipient(isMms)) {//有合法的和不合法的,弹出尝试发送对话框String title =getResourcesString(R.string.has_invalid_recipient,mRecipientsEditor.formatInvalidNumbers(isMms));new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(title).setMessage(R.string.invalid_recipient_message).setPositiveButton(R.string.try_to_send,newSendIgnoreInvalidRecipientListener()).setNegativeButton(R.string.no, new CancelSendingListener()).show();} else {//如果全是不合法的联系人,提示不能发送信息new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(R.string.cannot_send_message).setMessage(R.string.cannot_send_message_reason).setPositiveButton(R.string.yes, new CancelSendingListener()).show();}} else {//判断收件人没有问题,接着发送信息 --》sendMessage(true);}}3. src/com/android/mms/ui/ComposeMessageActivity.javaprivate void sendMessage(boolean bCheckEcmMode) {Log.v(TAG, "sendMessage");if (bCheckEcmMode) {// TODO: expose this in telephony layer for SDK buildString inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);     //判断电话是否处于紧急拨号模式,得到的inEcm一般为空Log.v(TAG, "inEcm = " + inEcm);if (Boolean.parseBoolean(inEcm)) {try {startActivityForResult(new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS,null),REQUEST_CODE_ECM_EXIT_DIALOG);return;} catch (ActivityNotFoundException e) {// continue to send messageLog.e(TAG, "Cannot find EmergencyCallbackModeExitDialog", e);}}}if (!mSendingMessage) {// send can change the recipients. Make sure we remove the listeners firstand then add// them back once the recipient list has settled.removeRecipientsListeners();  //取消对收件人的监听mWorkingMessage.send();   //发送信息—-》mSentMessage = true;mSendingMessage = true;addRecipientsListeners(); //重新添加收件人监听}// But bail out if we are supposed to exit after the message is sent.if (mExitOnSent) {//如果mExitOnSent为true,信息发送完成后退出Activityfinish();}}4. src/com/android/mms/data/WorkingMessage.java/*** Send this message over the network.  Will call back with onMessageSent() once* it has been dispatched to the telephonystack.  This WorkingMessage object is* no longer useful after this method hasbeen called.*/public void send() {if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {LogTag.debug("send");}// Get ready to write to disk.prepareForSave(true /* notify */);//主要做一下同步收件人和WorkingMessage,彩信时在准备其他一些东西// We need the recipient list for both SMS and MMS.final Conversation conv = mConversation;String msgTxt = mText.toString();Log.v(TAG, "msgText = " + msgTxt);if (requiresMms() ||addressContainsEmailToMms(conv, msgTxt)) {// Make local copies of the bits we need for sending a message,// because we will be doing it off of the main thread, which will// immediately continue on to resetting some of this state.final Uri mmsUri = mMessageUri;final PduPersister persister = PduPersister.getPduPersister(mContext);final SlideshowModel slideshow = mSlideshow;final SendReq sendReq = makeSendReq(conv,mSubject);// Do the dirty work of sending the message off of the main UI thread.new Thread(new Runnable() {public void run() {// Make sure the text in slide 0 is no longer holding onto a reference to// the text in the message text box.slideshow.prepareForSend();sendMmsWorker(conv, mmsUri,persister, slideshow, sendReq);}}).start();} else {// Same rules apply as above.final String msgText = mText.toString();//取出短消息Log.v(TAG, "msgText = " + msgText);new Thread(new Runnable() {public void run() {preSendSmsWorker(conv, msgText);//发送信息--》}}).start();}// update the Recipient cache with the new to address, if it's differentRecipientIdCache.updateNumbers(conv.getThreadId(),conv.getRecipients());// Mark the message as discarded because it is "off the market"after being sent.mDiscarded = true;}5. src/com/android/mms/data/WorkingMessage.javaprivate void preSendSmsWorker(Conversation conv, StringmsgText) {// If user tries to send the message, it's a signal the inputtedtext is what they wanted.UserHappinessSignals.userAcceptedImeText(mContext);mStatusListener.onPreMessageSent();//重置一些信息,比如清空输入内容框、一些监听等等// Make sure we are still using the correct thread ID for our// recipient set.long threadId = conv.ensureThreadId();//新建获得会话线程IDLog.v(TAG, "threadId = " + threadId);final String semiSepRecipients =conv.getRecipients().serialize();// just do a regular send. We're already on a non-ui thread so noneed to fire// off another thread to do this work.sendSmsWorker(msgText, semiSepRecipients, threadId);//发送信息----》// Be paranoid and clean any draft SMS up.deleteDraftSmsMessage(threadId);//删除草稿}6. src/com/android/mms/data/WorkingMessage.javaprivate void sendSmsWorker(String msgText, String semiSepRecipients, longthreaded) {String[] dests = TextUtils.split(semiSepRecipients,“;”);Log.v(TAG, “sendSmsWorker – semiSepRecipients is “ + semiSepRecipients);if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {LogTag.debug(“sendSmsWorker sending message”);}MessageSender sender = new SmsMessageSender(mContext, dests, msgText, threaded);try {sender.sendMessage(threadId);//根据ThreadID发送信息----》// Make sure this thread isn't over the limits in message countRecycler.getSmsRecycler().deleteOldMessagesByThreadId(mContext, threadId);} catch (Exception e) {Log.e(TAG, "Failed to send SMS message, threadId=" + threadId, e);}mStatusListener.onMessageSent();}7. src/com/android/mms/transaction/SmsMessageSender.javapublic boolean sendMessage(long token) throwsMmsException {// In order to send the message one by one, instead of sending now, themessage will split,// and be put into the queue along with each destinationsreturn queueMessage(token);}8. src/com/android/mms/transaction/SmsMessageSender.javaprivate boolean queueMessage(long token) throwsMmsException {if ((mMessageText == null) || (mNumberOfDests == 0)) {// Don't try to send an empty message.throw new MmsException("Null message body or dest.");}Log.v("SMsMessageSender", "queueMessage");SharedPreferences prefs =PreferenceManager.getDefaultSharedPreferences(mContext);boolean requestDeliveryReport =prefs.getBoolean(MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE,DEFAULT_DELIVERY_REPORT_MODE);Log.v("SmsMessageSender", "add Message to 'content://sms/queued'");for (int i = 0; i < mNumberOfDests; i++) {//根据收件人数目分别建立短信放入发送队列try {Sms.addMessageToUri(mContext.getContentResolver(),Uri.parse("content://sms/queued"), mDests[i],mMessageText, null, mTimestamp,true /* read */,requestDeliveryReport,mThreadId);} catch (SQLiteException e) {SqliteWrapper.checkSQLiteException(mContext, e);}}// Notify the SmsReceiverService to send the message outmContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,null,mContext,SmsReceiver.class));  //通知SmsReceiverService来发送短信,传递参数ACTION_SEND_MESSAGEreturn false;}9. src/com/android/mms/transaction/SmsReceiverService.java/*** Handle incoming transactionrequests.* The incoming requests are initiatedby the MMSC Server or by the MMS Client itself.*/@Overridepublic void handleMessage(Message msg) {int serviceId = msg.arg1;Intent intent = (Intent)msg.obj;if (intent != null) {String action =intent.getAction();int error = intent.getIntExtra("errorCode", 0);if (MESSAGE_SENT_ACTION.equals(intent.getAction())){handleSmsSent(intent,error);} else if (SMS_RECEIVED_ACTION.equals(action)) {handleSmsReceived(intent,error);} else if (ACTION_BOOT_COMPLETED.equals(action)) {handleBootCompleted();} else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)){handleServiceStateChanged(intent);} else if (ACTION_SEND_MESSAGE.endsWith(action)) {handleSendMessage();//处理发送信息}}// NOTE: We MUST not call stopSelf() directly, since we need to// make sure the wake lock acquired by AlertReceiver is released.SmsReceiver.finishStartingService(SmsReceiverService.this, serviceId);}}10. src/com/android/mms/transaction/SmsReceiverService.javaprivate void handleSendMessage(){Log.v(TAG, "handleSendMessage");if (!mSending) {//如果没有发送,则准备发送sendFirstQueuedMessage();}}11. src/com/android/mms/transaction/SmsReceiverService.javapublic synchronized void sendFirstQueuedMessage() {Log.v(TAG, "sendFirstQueuedMessage");boolean success = true;// get all the queued messages from the databasefinal Uri uri = Uri.parse("content://sms/queued");ContentResolver resolver =getContentResolver();//查询队列中的信息,包括上次没有发送出去存放在发送队列的信息       Cursor c = SqliteWrapper.query(this, resolver, uri,SEND_PROJECTION, null, null, "date ASC");   // date ASC so we send out in// same order the user tried// to send messages.if (c != null) {try {if (c.moveToFirst()) {String msgText =c.getString(SEND_COLUMN_BODY);String address =c.getString(SEND_COLUMN_ADDRESS);int threadId = c.getInt(SEND_COLUMN_THREAD_ID);int status = c.getInt(SEND_COLUMN_STATUS);Log.v(TAG, "address = " + address);Log.v(TAG, "msgText = " + msgText);Log.v(TAG, "status = " + status);int msgId = c.getInt(SEND_COLUMN_ID);Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI,msgId);Log.v(TAG, "msgId = " + msgId);SmsMessageSender sender = newSmsSingleRecipientSender(this,address, msgText,threadId, status == Sms.STATUS_PENDING,msgUri);if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {Log.v(TAG, "sendFirstQueuedMessage " + msgUri +", address: " + address +", threadId: " + threadId +", body: " + msgText);}try {sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);//进行单个信息发送mSending = true;} catch (MmsExceptione) {Log.e(TAG, "sendFirstQueuedMessage: failed to send message" + msgUri+ ", caught ", e);success = false;}}} finally {c.close();}}if (success) {// We successfully sent all the messages in the queue. We don't need to// be notified of any service changes any longer.unRegisterForServiceStateChanges();}}12. src/com/android/mms/transaction/SmsSingleRecipientSender.javapublic boolean sendMessage(long token) throwsMmsException {if (mMessageText == null) {// Don't try to send an empty message, and destination should be just// one.throw new MmsException("Null message body or have multiple destinations.");}SmsManager smsManager = SmsManager.getDefault();ArrayList<String> messages = null;if ((MmsConfig.getEmailGateway() != null) &&(Mms.isEmailAddress(mDest) || MessageUtils.isAlias(mDest))) {String msgText;msgText = mDest + "" + mMessageText;mDest = MmsConfig.getEmailGateway();messages =smsManager.divideMessage(msgText);} else {Log.v("SmsSingleRecipient", "divideMessage");messages = smsManager.divideMessage(mMessageText);//短信通道被限制160个字节,因此内容过长将会以多条短信发送,这个动作就是将长短信拆分成合适的大小// remove spaces from destination number (e.g. "801 555 1212"-> "8015551212")mDest = mDest.replaceAll("", "");}int messageCount = messages.size();if (messageCount ==0) {// Don't try to send an empty message.throw new MmsException("SmsMessageSender.sendMessage: divideMessage returned " +"empty messages. Original message is \"" + mMessageText + "\"");}Log.v("SmsSingleRecipientSender", "move to Sms.MESSAGE_TYPE_OUTBOX");Log.v("SmsSingleRecipientSender", "mUri = " + mUri);boolean moved = Sms.moveMessageToFolder(mContext, mUri, Sms.MESSAGE_TYPE_OUTBOX,0);//移动到发件箱if (!moved) {throw new MmsException("SmsMessageSender.sendMessage: couldn't move message " +"to outbox: " + mUri);}ArrayList<PendingIntent>deliveryIntents =  newArrayList<PendingIntent>(messageCount);ArrayList<PendingIntent>sentIntents = new ArrayList<PendingIntent>(messageCount);for (int i = 0; i < messageCount; i++) {if (mRequestDeliveryReport) {// TODO: Fix: It should not be necessary to// specifythe class in this intent.  Doing that// unnecessarily limits customizability.deliveryIntents.add(PendingIntent.getBroadcast(mContext, 0,new Intent(MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION,mUri,mContext,MessageStatusReceiver.class),0));}Intent intent  = new Intent(SmsReceiverService.MESSAGE_SENT_ACTION,mUri,mContext,SmsReceiver.class);//触发SmsReceiverService的MESSAGE_SENT_ACTION消息if (i == messageCount -1) {intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT, true);}sentIntents.add(PendingIntent.getBroadcast(mContext, 0, intent, 0));//设置回调的Intent为intent,}try {smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents);//调用Framework中的API来发送短信,会回调sentIntents来处理发送的情况} catch (Exception ex) {throw new MmsException("SmsMessageSender.sendMessage: caught " + ex +" from SmsManager.sendTextMessage()");}if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {log("sendMessage: address=" + mDest + ", threadId=" + mThreadId +", uri=" + mUri + ", msgs.count=" + messageCount);}return false;}13. src/com/android/mms/transaction/SmsReceiverService.java/*** Handle incoming transactionrequests.* The incoming requests are initiatedby the MMSC Server or by the MMS Client itself.*/@Overridepublic void handleMessage(Message msg) {int serviceId = msg.arg1;Intent intent = (Intent)msg.obj;if (intent != null) {String action =intent.getAction();int error = intent.getIntExtra("errorCode", 0);if (MESSAGE_SENT_ACTION.equals(intent.getAction())) {handleSmsSent(intent, error);} else if (SMS_RECEIVED_ACTION.equals(action)) {handleSmsReceived(intent,error);} else if (ACTION_BOOT_COMPLETED.equals(action)) {handleBootCompleted();} else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)){handleServiceStateChanged(intent);} else if (ACTION_SEND_MESSAGE.endsWith(action)) {handleSendMessage();}}// NOTE: We MUST not call stopSelf() directly, since we need to// make sure the wake lock acquired by AlertReceiver is released.SmsReceiver.finishStartingService(SmsReceiverService.this, serviceId);}}14. src/com/android/mms/transaction/SmsReceiverService.javaprivate void handleSmsSent(Intentintent, int error) {Log.v(TAG, "handleSmsSent - error is " + error);Uri uri = intent.getData();Log.v(TAG, "uri = " + uri);mSending = false;boolean sendNextMsg =intent.getBooleanExtra(EXTRA_MESSAGE_SENT_SEND_NEXT, false);if (mResultCode == Activity.RESULT_OK) {//发送成功的情况Log.v(TAG, "mResultCode == Activity.RESULT_OK");if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {Log.v(TAG, "handleSmsSent sending uri: " + uri);}Log.v(TAG, "moveMessageToFolder intoSms.MESSAGE_TYPE_SENT");//将短信移动到已发送if (!Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_SENT,error)) {Log.e(TAG, "handleSmsSent: failed to move message " + uri + " to sentfolder");}if (sendNextMsg) {//如果需要,发送下一条sendFirstQueuedMessage();//只是查发送队列的信息去发送}// Update the notification for failed messages since they may be deleted.MessagingNotification.updateSendFailedNotification(this);} else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF) ||(mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) {Log.v(TAG, "mResultCode ==SmsManager.RESULT_ERROR_RADIO_OFF");if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {Log.v(TAG, "handleSmsSent: no service, queuing message w/ uri:" + uri);}// We got an error with no service or no radio. Register for state changesso// when the status of the connection/radio changes, we can try to send the// queued up messages.registerForServiceStateChanges();//来服务和信号时调用sendFirstQueuedMessage()去发送// We couldn't send the message, put in the queue to retry later.Log.v(TAG, "uri = " + uri);Log.v(TAG, "moveMessageToFolder intoSms.MESSAGE_TYPE_QUEUED");Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_QUEUED,error);mToastHandler.post(new Runnable() {public void run() {Toast.makeText(SmsReceiverService.this,getString(R.string.message_queued),Toast.LENGTH_SHORT).show();}});} else {Log.v(TAG, "mResultCode == Other exception");if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {Log.v(TAG, "handleSmsSent msg failed uri: " + uri);}Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_FAILED,error);MessagingNotification.notifySendFailed(getApplicationContext(),true);if (sendNextMsg) {sendFirstQueuedMessage();}}}分享到:

短信发送流程:系统短信(SMS)发送流程相关推荐

  1. 解忧云SMS短信服务平台系统 短信发送系统源码 全解密随时可以二开无后门

    解忧云SMS短信服务平台系统 短信发送系统 全解密完美版 经过一系列修复现在程序已经可以完全使用. 并且是全解密随时可以二开.无后门. 一些bug已经完全修复 安装教程 数据库配置文件路径 .env ...

  2. 解忧云SMS短信服务平台系统 短信发送系统 全解密完美版

    简介: 全网首发 解忧云SMS短信服务平台系统 短信发送系统 全解密完美版 经过一系列修复现在程序已经可以完全使用. 并且是全解密随时可以二开.无后门. 一些bug已经完全修复 安装教程 数据库配置文 ...

  3. android系统短信库的一些用法

    1.查询所有短信,按发件人进行分组 Cursor mCursor =managedQuery(Uri.parse("content://sms"),new String[] {&q ...

  4. 抖音短视频获客系统源码开发及搭建分享

    短视频账号矩阵系统/短视频seo霸屏系统/短视频矩阵seo系统源码/独立部署,技术团队如何围绕短视频矩阵关键词霸屏来做开发?来做到抖音seo优化达到账号排名效果,关键词起到至关重要的作用,依托于各平台 ...

  5. 抖音账号矩阵系统/短视频霸屏系统/源码部署

    短视频账号矩阵系统/短视频seo霸屏系统/短视频矩阵seo系统源码/独立部署,技术团队如何围绕短视频矩阵关键词霸屏来做开发?来做到抖音seo优化达到账号排名效果,关键词起到至关重要的作用,依托于各平台 ...

  6. 流程系统的设计与实现

    流程系统的设计与实现 The Design and Implementation of Process system 详细论文 摘要 在计算机还没有普及的时候,很多工作流程都是手工传递纸质表格,逐级审 ...

  7. 安卓短信功能全解:调用系统短信功能发送短信、彩信,使用SmsManager发送短信,并监听发送短信的投递情况,使用广播接收器监听接收的短信。

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓短信功能全解:调用系统短信功能发送短信.彩信,使用SmsManager发送短信,并监听发送短信的投递情况,使用广播接收器监听接收的短信. 首先需要 ...

  8. 医院HIS系统短信发送模板

    医疗信息系统HIS短信接口解决方案 为数字化医院系统提供可靠的短信通知服务 同医院信息化系统整合,为预约挂号.网络问诊.体检报告通知.不良事件预警.内部网络办公等场景提供短信通知能力.提供免安装的在线 ...

  9. 系统监控:linux命令行-飞信客户端发送免费报警短信

    linux命令行下用Fetion飞信发送免费短信 一.最新版本2009 通过linux命令行来发送短信的方法,觉得甚是好用,适用运维监控.这里向大家推荐的是飞信机器人的软件,支持linux.命令行下的 ...

最新文章

  1. easyuefi只能在基于uefi启动的_苹果电脑怎么从u盘启动|苹果笔记本按哪个键选u盘启动...
  2. 手把手视频:万能开源Hawk抓取动态网站
  3. WinForm界面开发之布局控件WeifenLuo.WinFormsUI.Docking的使用
  4. 理解 Dubbo 服务引用
  5. 投影仪是计算机的基本配置6,关于网络投影仪的六个问题
  6. python导出数据找不到csv_python – 将数据从neo4j导出到csv而不是json
  7. java连接hbase时出现....is accessible from more than one module:
  8. 概率论经典问题 —— 三个事件 A、B、C 独立 ≠ 三个事件两两独立
  9. Access数据库的查询
  10. 天勤数据结构代码——递归
  11. 入门机器学习(西瓜书+南瓜书)神经网络总结(python代码实现)
  12. html 点击按钮刷新验证码,HTML点击刷新验证码
  13. Large-scale Video Classification with Convolutional Neural Networks
  14. Android 实现水波纹效果
  15. Python四种读取数据文件的方法
  16. 批量删除多个 PDF 文档空白页
  17. P5692 手牵手走向明天
  18. 支付宝网站支付在微信浏览器中跳转问题(亲测,附源码)
  19. shell命令查阅端口信息_Linux服务器管理Shell经典命令
  20. HTML5 video视频制作,控制按钮

热门文章

  1. JAVA删除字符串固定下标的字串
  2. TI DM6437 EDMA3使用总结
  3. CFA一级学习笔记--权益(五)--行为金融学
  4. Linux 嵌入式开发 网络编程: day4
  5. 永续合约 perpetual swap
  6. 用链表,栈,队列实现简单的停车场项目
  7. 卡尔曼滤波的5个公式及每个参数的含义
  8. C++使用Hadoop
  9. 基于TCP/IP协议的物联网安卓应用开发基础教程(Android Studio开发)
  10. 蔬菜处理生产系统(PLC课程设计)【本文为原创,全部源文件可供下载,谢绝转载】