SMS送信-SMS送信プロセス-アプリケーション層



Sms Sending Sms Sending Process Application Layer



2019 Unicorn Enterprise Heavy Gold Recruitment Python Engineer Standard >>> hot3.png

SMS送信プロセスアプリケーション層分析

1、関係するクラス

[プレーン] プレーンビュー コピー
  1. com.android.mms.ui.ComposeMessageActivity
  2. com.android.mms.data.WorkingMessage
  3. com.android.mms.transaction.MessageSender
  4. com.android.mms.transaction.SmsMessageSender
  5. com.android.mms.transaction.SmsSingleRecipientSender
  6. com.android.mms.transaction.SmsReceiverService
  7. com.android.mms.transaction.SmsReceiver
2、タイミング図 説明:UIインターフェースからテキストメッセージを送信するための中間層のSmsMangerメソッドまで、おおよそのタイミングは次のようになります。参照コードはandroid2.3です

3、プロセス分析

3.1ComposeMessageActivityの作業

このクラスは、以下に示すように、SMSを編集し、ユーザーと対話するUIです。




ユーザーが編集を終了したら、送信ボタンをクリックしてメッセージの内容を送信できます。 sendbuttonをクリックすると、ボタンの対応するリスナーがトリガーされます。 ComposeMessageActivityはOnClickListenerインターフェースを実装しているため、最終的にonclickメソッドに呼び出されます。



1)onClick分析

このメソッドは2つのことを行います。

最初に、isPreparedForSendingメソッドが呼び出され、現在のショートメッセージを送信する準備ができているかどうかが判別されます。基本は、ショートメッセージの受信者が許可された上限を超えているかどうか、受信者がいるかどうか、ショートメッセージにコンテンツや添付ファイル、テーマなどがあり、ユーザーが何も送信できないかどうかです。 。テキストメッセージは送信されません。



次に、上記のチェックは、confirmSendMessageIfNeededメソッドを呼び出すことによって送信プロセスを開始します。もちろん、このメソッドは正常に送信されません。また、このメソッドは、要件を満たすまで一連のチェックも実行します。

二)確認SendMessageIfNeeded分析

このメソッドの論理呼び出しを以下に示します。

3)sendMessageメソッドの分析上の図は、最後にsendMessageに移動する必要があることを示しています。このメソッドが何をするか見てみましょう。コードを見ると、最も重要な作業は次のとおりです。SMSをWorkingMessageに送信する作業を引き渡す、mWorkingMessage.send(mDebugRecipients)その他の作業は、補助的な操作を行うことだけです。概要:この時点までテキストメッセージを送信する作業は、WorkingMessageに渡され、その後ComposeMessageActivityの主な仕事は、デュアルカードの処理です。

3.2WorkingMessageの簡単な分析

1)send()分析このメソッドは5つのことを行います。1つは、受信者リストが空かどうかを確認することです。ここでは特定の分析は行いません。 2つ目は、SMSコンテンツを8バイトから7バイトに変換することです。3つ目は、現在のMMSが送信されているかどうかを判断することです。現在SMSメッセージを送信しているため、MMS送信プロセスを実行できません。第4に、SMSの署名をSMSのコンテンツに追加します。 5つは、preSendSmsWorker()メソッドを呼び出すことです。 2)preSendSmsWorker分析1つはインターフェイスをリセットし、インターフェイス上のすべてのコンポーネントをクリアすることです。2つ目はsendSmsWorkerメソッドを呼び出すことです。3つ目はドラフトを削除することです。 3)sendSmsWorker()によって実行される作業SmsMessageSenderのsendMessage()メソッドを呼び出します

3.3SmsMessageSender分析

1)sendMessage()

このメソッドは、queueMessage()メソッドを呼び出して、処理のために送信されたタスクをスローします。

二)queueMessage() それには2つの責任があります。 1つは、データベースに送信するショートメッセージを保存することです。 [プレーン] プレーンビュー コピー
  1. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext)
  2. boolean requestDeliveryReport = prefs.getBoolean(
  3. MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE、
  4. DEFAULT_DELIVERY_REPORT_MODE)
  5. for(int i = 0 i
  6. {を試してください
  7. log( 'sub =' + mSubscriptionでデータベースを更新)
  8. Sms.addMessageToUri(mContext.getContentResolver()、
  9. Uri.parse( 'content:// sms / queued')、mDests [i]、
  10. mMessageText、null、mTimestamp、
  11. true / *読み取り* /、
  12. requestDeliveryReport、
  13. mThreadId、mSubscription)
  14. } catch(SQLiteException e){
  15. SqliteWrapper.checkSQLiteException(mContext、e)
  16. }
  17. }
2つ目は、ブロードキャスト方式を使用することを除いて、タスクを他の人に転送することです。
[プレーン] プレーンビュー コピー
  1. //メッセージを送信するようにSmsReceiverServiceに通知します
  2. インテントインテント=新しいインテント(SmsReceiverService.ACTION_SEND_MESSAGE、null、mContext、SmsReceiver.class)
  3. intent.putExtra(SUBSCRIPTION、mSubscription)
  4. mContext.sendBroadcast(インテント)
概要:このクラスは非常に重要な仕事をしました。データベースに送信するSMSを保存してから、SmsReceiverにブロードキャスト通知を送信します。

3.4SmsReceiverからSmsReceiverServiceへ

実際、この男はSmsReceiverの秘書ではありません。取得後すぐにSmsReceiverServiceサービスに転送されます。 「これは私のためではありません、私は配達宅配便です。」 SmsReceiverの役割は次のように呼ばれます。メソッドはタイミング図を参照できます

3.5 SmsReceiverService

長い間話し合った後、ようやく仕事に就きました。もちろんサービスなので、独自の宣言期間機能を経ます。まず、onCrateです。このメソッドは近年初期化され、次にonStartCommand()で初期化され、メソッドは実行されません。 ServiceHandlerにメッセージを送るだけで、人々は貢献するために自分たちの努力をしたようです。 1)ServiceHandlerはリクエストの送信を処理します [プレーン] プレーンビュー コピー
  1. @オーバーライド
  2. public void handleMessage(Message msg){
  3. int serviceId = msg.arg1
  4. インテントインテント=(インテント)msg.obj
  5. if(intent!= null){
  6. 文字列action = intent.getAction()
  7. int error = intent.getIntExtra( 'errorCode'、0)
  8. if(SMS_RECEIVED_ACTION.equals(action)){
  9. handleSmsReceived(intent、error)
  10. } else if(SMS_CB_RECEIVED_ACTION.equals(action)){
  11. handleCbSmsReceived(intent、error)
  12. } else if(ACTION_BOOT_COMPLETED.equals(action)){
  13. handleBootCompleted()
  14. } else if(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)){
  15. handleServiceStateChanged(intent)
  16. } else if(ACTION_SEND_MESSAGE.endsWith(action)){
  17. handleSendMessage(intent)
  18. }
  19. }
  20. //注:stopSelf()を直接呼び出す必要があるため、直接呼び出さないでください。
  21. // AlertReceiverによって取得されたウェイクロックが解放されていることを確認します。
  22. SmsReceiver.finishStartingService(SmsReceiverService.this、serviceId)
  23. }
  24. }
ここでは、送信を受信した後、handleSendMessageメソッドが使用されます。2)handleSendMessage()の分析:1。デュアルカードを使用できるかどうかを判断します。現在のカードを取得してsendFirstQueuedMessage(int sub)を呼び出す場合2.デュアルカードが使用できない場合は、sendFirstQueuedMessage()メソッドを直接呼び出します注:これは呼び出される2つの異なるメソッドであり、パラメーターを確認できますが、実際、パラメーターのないsendFirstQueuedMessage()関数は最終的にsendFirstQueuedMessage(int sub)によって呼び出されます。sendFirstQueuedMessage(int sub)の最後の呼び出しと同等にするために、このメソッド3)sendFirstQueuedMessage(int sub)最初にデータベースからテキストメッセージを削除し、次にSmsSingleRecipientSenderのSendMessage()メソッドを呼び出して送信します。概要:長い間不在で、最終的に送信を開始しなかったことがわかります。

3.6 SmsSingleRecipientSender

sendMessage()の説明:1つはSMSのコンテンツを分割することです。2つ目はSMSをOUTBOXのデータベーステーブルに保存することです。3つ目は分割されたSMSを個別に送信することです。4つ目は、呼び出されたSMSMangerクラスのsendMultipartTextMessage()が送信されます。送信された特定の操作は中間層に転送されます。具体的なコードは次のとおりです。 [プレーン] プレーンビュー コピー
  1. if(mMessageText == null){
  2. //空のメッセージを送信しようとしないでください。宛先は、
  3. // 1。
  4. 新しいMmsException( 'メッセージ本文がヌルであるか、複数の宛先があります。')をスローします。
  5. }
  6. SmsManager smsManager = SmsManager.getDefault()
  7. ArrayListメッセージ= null
  8. if((MmsConfig.getEmailGateway()!= null)&&
  9. (Mms.isEmailAddress(mDest)|| MessageUtils.isAlias(mDest))){
  10. 文字列msgText
  11. msgText = mDest + '' + mMessageText
  12. mDest = MmsConfig.getEmailGateway()
  13. メッセージ= smsManager.divideMessage(msgText)
  14. } そうしないと {
  15. メッセージ= smsManager.divideMessage(mMessageText)
  16. //宛先番号からスペースを削除します(例: '801 555 1212'-> '8015551212')
  17. mDest = mDest.replaceAll( ''、 '')
  18. }
  19. int messageCount = messages.size()
  20. if(messageCount == 0){
  21. //空のメッセージを送信しようとしないでください。
  22. 新しいMmsException( 'SmsMessageSender.sendMessage:divideMessageが返されました' +
  23. '空のメッセージ。元のメッセージは '' + mMessageText + '' ')
  24. }
  25. ブール値の移動= Sms.moveMessageToFolder(mContext、mUri、Sms.MESSAGE_TYPE_OUTBOX、0)
  26. if(!moved){
  27. 新しいMmsException( 'SmsMessageSender.sendMessage:メッセージを移動できませんでした' +
  28. '送信トレイへ:' + mUri)
  29. }
  30. ArrayList deliveryIntents = new ArrayList(messageCount)
  31. ArrayList sentIntents = new ArrayList(messageCount)
  32. for(int i = 0 i
  33. if(mRequestDeliveryReport){
  34. // TODO:修正:必要はないはずです
  35. //このインテントでクラスを指定します。それをやって
  36. //カスタマイズ性を不必要に制限します。
  37. deliveryIntents.add(PendingIntent.getBroadcast(
  38. mContext、0、
  39. 新しいインテント(
  40. MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION、
  41. ムリ、
  42. mContext、
  43. MessageStatusReceiver.class)、
  44. 0))
  45. }
  46. インテントインテント=新しいインテント(SmsReceiverService.MESSAGE_SENT_ACTION、
  47. ムリ、
  48. mContext、
  49. SmsReceiver.class)
  50. int requestCode = 0
  51. if(i == messageCount -1){
  52. //別の保留中のインテントになるようにrequestCodeを変更する
  53. //最後のフラグメントに対して作成されます
  54. // EXTRA_MESSAGE_SENT_SEND_NEXTをtrueに設定します。
  55. requestCode = 1
  56. intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT、true)
  57. intent.putExtra(SUBSCRIPTION、mSubscription)
  58. }
  59. sentIntents.add(PendingIntent.getBroadcast(mContext、requestCode、intent、0))
  60. }
  61. {を試してください
  62. smsManager.sendMultipartTextMessage(mDest、mServiceCenter、messages、sentIntents、
  63. deliveryIntents、mSubscription)
  64. } catch(Exception ex){
  65. 新しいMmsException( 'SmsMessageSender.sendMessage:catched' + ex +をスローします
  66. 'SmsManager.sendTextMessage()から')
  67. }
  68. if(Log.isLoggable(LogTag.TRANSACTION、Log.VERBOSE)){
  69. log( 'sendMessage:address =' + mDest + '、threadId =' + mThreadId +
  70. '、uri =' + mUri + '、msgs.count =' + messageCount)
  71. }

転載:https://my.oschina.net/u/211005/blog/108999