5

最近、送信された SMS の状態を確認する方法について質問したところ、BroadcastReceiversSMS の送信/配信されたブロードキャストをリッスンするための 2 つの「匿名内部」(用語が間違っている場合は修正してください) を登録したコード スニペットが返されました。これらの受信者は、アプリケーションが送信したばかりの SMS に関するデータを受信することのみを要求されたので、永続的にリッスンする必要はありませんでした。

すぐに「まあ、使い終わったら登録解除しなきゃ」と思ったのですが、これでよろしいでしょうか?登録解除コードが含まれていなかったので、投稿者にこれを尋ねましたが、返事がありませんでした。コードは、多数の Android 開発サイトに表示されているため、私が望むことを行うためのかなり標準的な方法のようです。ここにあります:

//---sends an SMS message to another device---
private void sendSMS(String phoneNumber, String message)
{        
    String SENT = "SMS_SENT";
    String DELIVERED = "SMS_DELIVERED";

    PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
        new Intent(SENT), 0);

    PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
        new Intent(DELIVERED), 0);

    //---when the SMS has been sent---
    registerReceiver(new BroadcastReceiver(){
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode())
            {
                case Activity.RESULT_OK:
                    Toast.makeText(getBaseContext(), "SMS sent", 
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                    Toast.makeText(getBaseContext(), "Generic failure", 
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_NO_SERVICE:
                    Toast.makeText(getBaseContext(), "No service", 
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_NULL_PDU:
                    Toast.makeText(getBaseContext(), "Null PDU", 
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_RADIO_OFF:
                    Toast.makeText(getBaseContext(), "Radio off", 
                            Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }, new IntentFilter(SENT));

    //---when the SMS has been delivered---
    registerReceiver(new BroadcastReceiver(){
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode())
            {
                case Activity.RESULT_OK:
                    Toast.makeText(getBaseContext(), "SMS delivered", 
                            Toast.LENGTH_SHORT).show();
                    break;
                case Activity.RESULT_CANCELED:
                    Toast.makeText(getBaseContext(), "SMS not delivered", 
                            Toast.LENGTH_SHORT).show();
                    break;                        
            }
        }
    }, new IntentFilter(DELIVERED));        

    SmsManager sms = SmsManager.getDefault();
    sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);

コードは正常に動作します。

さらに、アプリの外部で発生する SMS 送信/配信イベントの通知を受けません。たとえば、これらが登録された後に SMS を送信できますが、メッセージBroadcastReceiversは表示されません。Toast

だから、私は2つの質問があります:

  1. これらの登録を解除する必要がありBroadcastReceiversますか?
  2. そうでない場合、なぜですか?
4

4 に答える 4

1

インスタンスに保存するだけBroadcastReceiverで、登録を解除できます;-)

この行を次のように変更するだけです。

registerReceiver(new BroadcastReceiver(){

に:

BroadcastReceiver smsReceiver=new BroadcastReceiver(){...}
registerReceiver(smsReceiver);

後で実行できます:

unregisterReceiver(smsReceiver);

smsReceiverクラスメンバーとして保存することを忘れないでください。

于 2012-06-06T17:28:29.563 に答える
1

さらに、アプリの外部で発生する SMS 送信/配信イベントの通知を受けません。

受信者を動的に登録しています。他のアプリケーションからのインテントをリッスンする場合は、受信者をマニフェスト ファイルに登録する必要があります。そうすれば、常にアクティブになります。また、登録を解除する必要はありません。

于 2012-11-27T11:30:06.220 に答える
0

登録を解除する必要があります。そうしないと、おそらくクラッシュします。私はそれについてかなり確信しています。しかし、クラッシュしていないと言うなら、それを調べる必要があります:)

Androidは、登録解除を忘れたと思うからです。登録を解除することを期待しています。"注: Activity.onResume() 実装でレシーバーを登録する場合は、Activity.onPause() で登録を解除する必要があります。(一時停止するとインテントを受信しないため、不要なシステム オーバーヘッドが削減されます)。しないでください。 Activity.onSaveInstanceState() で登録解除します。これは、ユーザーが履歴スタックに戻った場合に呼び出されないためです。" <===== ドキュメントから

于 2012-06-06T17:27:18.683 に答える
0

したがって、あなたが正しく書いたことを理解していれば、は呼び出しBroadcastReceiver内にのみ存在するように見えるため、またはインテントに登録されていても、それらを受信できない可能性があります。また、レシーバーの使用が終了したら、常にレシーバーの登録を解除したいと考えています。デバッガーがレシーバーのリークについて警告するのを見てきました。sendSMS()SENTDELIVERED

sent_broadcast_receiver同様のクラスパラメーターがあり、登録しているレシーバーへの参照が含まれているとdelivered_broadcast_receiver、オブジェクトが永続化し、完了後に登録を解除できるようになると、よりうまく機能します。

編集:どのオブジェクトもBroadcastReceiversを保持し、インテントが返されるまで持続する必要がSENTありますDELIVERED。または、インテント(PendingIntentsであるため)は、必要に応じて起動できるものに向ける必要があります。

于 2012-06-06T17:35:22.827 に答える