13

着信 SMS をリッスンする BroadcastReceiver があります。メッセージが特定の送信者からのものである場合、BroadcastReceiver は次のコードでアプリを起動します。

final Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.putExtra("smsChallenge", smsText);
activityIntent.putExtra("smsSenderNumber", senderMobilNumber);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(activityIntent);

アプリの MainActivity (つまり)で、次のコードを使用して、インテントからonCreate()値を抽出し、抽出後に削除します。smsChallenge

Bundle extras = getIntent().getExtras();
if (extras != null) {
    smsChallenge = extras.getString("smsChallenge");
    extras.remove("smsChallenge");
}

したがって、私のアプリは SMS から開始され、正常に動作します...しかし、[戻る] ボタンを押してアプリケーションを再起動することを選択した場合 (つまり、Taskmanager を介して)、値smsChallengeはまだ bundle にありextrasます。つまり、再起動したアプリは、新しい SMS が原因で再起動したと考えていますが、これは正しくありません...

[戻る] ボタンを使用してアプリを再起動したときに、バンドルからキー値を削除しても機能しないように見える理由はありますか?

4

7 に答える 7

8

インテントにアクセスするまでに、最近のアプリを介して後で起動するために、OS がすでにインテントを保存しているため、この動作を修正できないと思います。

  1. 最近のアプリから削除するフラグを追加することもできますが、その方法ではアプリは最近のアプリに表示されません。
  2. MainActivity で処理された最後の SMS を永続ストレージに追加し、onCreate でこのチェックを行い、既に処理された SMS のインテントを破棄します。
  3. 最終的な解決策は、インテントでデータをまったく送信しないことです。たとえば、「保留中」の永続ストレージに保存します。MainActivity が開始したら、保留中のものをチェックし、この保留中の項目をクリアします。

永続ストレージは、たとえば SharedPreferences です。

2を使用することをお勧めしますが、受信した SMS をカウントし、そのカウンターを SMS の ID として使用する必要があります。SMS の識別子として、SMS の内容と送信者に依存しないでください。

于 2014-02-21T12:52:29.470 に答える
3

「インテントは常に、アクティビティを起動するために使用される元のインテントであり、それ以上のものではありません。これは不変です。」ダイアン・ハックボーン

この問題を回避するには、まずマニフェストでアクティビティの launchMode を singleTop として宣言してください。

次に、次のから、 onSaveInstanceState を使用して、エクストラの一部を「無効化」したという事実を記録してみてください。次に onCreate で、その 'Bundle savedInstanceState' パラメータを調べます。null でない場合は、以前に onSaveInstanceState で返したバンドルです。このバンドルから、これらのエクストラを無視するかどうかを決定できます。

編集:あなたの場合、共有設定を使用すると、アクティビティが破棄されても状態を維持できます。

public YourActivity extends Activity {

 private boolean extrasClearedOut;
 private SharedPreferences mPrefs;
 private static String EXTRA_CLEAR_OUT = "extras_cleared_out";

 public void onCreate(Bundle savedInstanceState) {
     mPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());

     extrasClearedOut = mPrefs.getBoolean(EXTRA_CLEAR_OUT, false);

     if (savedInstanceState != null && savedInstanceState.getBoolean(EXTRA_CLEAR_OUT, false))  {
         extrasClearedOut = true;
     }

     Intent intent = getIntent();
     if (extrasClearedOut) {
       // ignore the extras in the intent.

     }

     else {
       // Read and use the extras in the intent.
     }
 }

 protected void onNewIntent (Intent intent)  {
    super.onNewIntent(intent);
    setIntent(intent);

    if (extrasClearedOut) {
       // ignore the extras in the intent.
    }
    else {
       // Read and use the extras in the intent.
    }
 }

 public void someMethod(...) {
    extrasClearedOut = true;
 }

 protected void onSaveInstanceState (Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(EXTRA_CLEAR_OUT, extrasClearedOut);
 }

 public void onDestroy()
 {
    final Editor edit = mPrefs.edit();
    edit.putBoolean(EXTRA_CLEAR_OUT, extrasClearedOut);
    edit.commit();
 }

}

これがあなたの質問に対する別の実用的な解決策です

于 2014-02-27T00:07:30.017 に答える
1

私はあなたが望む行動のために活動の意図を明示的に設定する必要があると思います。getIntent()なぜコピーを返しているように見えるのかわかりません。

のドキュメントからActivity.setIntent()

getIntent()によって返されるインテントを変更します。これは、与えられた意図への参照を保持します。コピーしません。多くの場合、onNewIntent(Intent)と組み合わせて使用​​されます。

http://developer.android.com/reference/android/app/Activity.html#setIntent(android.content.Intent

于 2012-04-04T17:33:29.603 に答える
0
private void removeExtraFromBundle(String key){
    Bundle bundle = getArguments();
    if(bundle != null){
        String value = null;
        value = bundle.getString(key);
        if(value != null){
            bundle.remove(key);
        }
    }
}

上記のコードは、バンドル オブジェクトから特定のキーを削除するのに役立ちます。

于 2013-05-14T08:24:25.853 に答える
0

nonce私のアドバイスは、ランダムな文字列など、いくつかのインテントに 3 番目のエクストラを追加することです。

final Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.putExtra("smsChallenge", smsText);
activityIntent.putExtra("smsSenderNumber", senderMobilNumber);
activityIntent.putExtra("nonce", UUID.randomUUID().toString);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(activityIntent);

次に、前にこのノンスを取得したかどうかを確認しますonCreate()

public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent = getIntent();
    smsChallenge = intent.getStringExtra("smsChallenge", null);
    String nonce = intent.getStringExtra("nonce", null);
    if (nonce == null) {
      // should not happen, but do something sane here
    }
    SharedPreferences sp = PreferenceManager.getDefaultPreferences(this);
    if (nonce.equals(sp.getString("nonce", null)) {
      // app was restarted
    } else {
      // app was started from a shiny fresh intent
      sp.edit().putString("nonce", nonce).commit();
    }
}

ただし、向きの変更なども呼び出していることに注意してonCreate()ください。savedInstanceStateしかし、 isかどうかを確認することで、非常に簡単に回避できますnull

于 2014-02-23T12:14:51.383 に答える