Celeste Engineer

Androidとか自転車とか

SMS が相手に届いたかどうか判定する

SMS や MMS と言ったメッセージのやりとりの仕組みには、Delivery Report という機能があります。SMS をおくると、キャリアが Delivery Report を送り主に返します。この Delivery Report を見ることで、SMS が相手に届いたかどうかが分かります*1

SMS や MMS をおくるには、SMSManager を使います。例えば、単純なテキストメッセージをおくるのであれば、sendTextMessage メソッドを呼び出してメッセージを送ります。 他にもいくつか用途に応じて異なるメソッドが用意されていますが、ほぼどのメソッドでも sentIntent と deliveryIntent というPendingIntent型の引数があります。

これらは、メッセージ送信中にエラーがあったかどうか、またメッセージが相手に届いたかどうかをブロードキャスト Intent としてコールバックするために使われます。 sentIntent はメッセージ送信が成功したかどうか、エラーならばどのようなエラーがあったかをブロードキャストします。電波がなかったり、PDU が空だったり、あるいはサービスに未登録だったり、様々な理由で SMS を送れない場合はこのブロードキャストが飛んできます。 一方で deliveryIntent は相手に届いたかどうかを、Delivery Report を元にブロードキャストします。

ここまでの話は公式のリファレンスにも記述してある内容ですが、実は deliveryIntent は必ずブロードキャストされるわけではありません。

これは、キャリアが Delivery Report をサポートしているかどうかによって変わります。例えば、T-Mobile や Verizon は Delivery Report をサポートしているようですが、AT&T はサポートしてないようです*2。また、場合によってはフェイクの Delivery Report を生成することもあるようで、届いていないのに届いているように見せかけるものもあるようです*3

単純に SMS を送信できたかどうかだけであれば、sentIntent のブロードキャストのみを使って判定できるので、届いたかどうかが必要なければ deliveryIntent の PendingIntent は null にしましょう。