128

Google Play ストア アプリ (以前は Android マーケットと呼ばれていました) の [開く] ボタンを使用してアプリケーションを起動すると、アプリケーションにバグが発生しました。IntentPlay ストアからの起動は、電話のアイコンのアプリケーション メニューからの起動とは異なる方法を使用しているようです。これにより、同じアクティビティの複数のコピーが起動され、互いに競合します。

たとえば、私のアプリがアクティビティ ABC で構成されている場合、この問題は ABCA のスタックにつながる可能性があります。

この問題を解決するためにすべてのアクティビティで使用android:launchMode="singleTask"してみましたが、HOME ボタンを押すたびにアクティビティ スタックがルートにクリアされるという望ましくない副作用があります。

予想される動作は次のとおりです: ABC -> HOME -> アプリが復元されると、次のものが必要です: ABC -> HOME -> ABC

HOMEボタンを使用するときにルートアクティビティにリセットせずに、同じタイプの複数のアクティビティを起動しないようにする良い方法はありますか?

4

11 に答える 11

197

これを onCreate に追加すると、準備完了です。

// Possible work around for market launches. See https://issuetracker.google.com/issues/36907463
// for more details. Essentially, the market launches the main activity on top of other activities.
// we never want this to happen. Instead, we check if we are the root and if not, we finish.
if (!isTaskRoot()) {
    final Intent intent = getIntent();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(intent.getAction())) {
        Log.w(LOG_TAG, "Main Activity is not the root.  Finishing Main Activity instead of launching.");
        finish();
        return;       
    }
}
于 2011-10-13T01:23:51.733 に答える
29

失敗する理由と、このバグをプログラムで再現してテスト スイートに組み込む方法を説明します。

  1. Eclipse または Market App からアプリを起動すると、インテント フラグ FLAG_ACTIVITY_NEW_TASK で起動します。

  2. ランチャー (ホーム) から起動するときは、次のフラグを使用します: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_BROUGHT_TO_FRONT | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED を使用し、アクション " MAIN " とカテゴリ " LAUNCHER " を使用します。

これをテスト ケースで再現する場合は、次の手順を使用します。

adb shell am start -f 0x10000000 -n com.testfairy.tests.regression.taskroot/.MainActivity 

次に、他のアクティビティに到達するために必要なことは何でもします。私の目的のために、別のアクティビティを開始するボタンを配置しました。次に、ランチャー (ホーム) に戻ります。

adb shell am start -W -c android.intent.category.HOME -a android.intent.action.MAIN

そして、これでランチャーを介して起動することをシミュレートします:

adb shell am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -f 0x10600000 -n com.testfairy.tests.regression.taskroot/.MainActivity

isTaskRoot() 回避策を組み込んでいない場合は、問題が再現されます。これを自動テストで使用して、このバグが二度と発生しないようにします。

お役に立てれば!

于 2014-04-05T15:10:58.053 に答える
10

singleTop起動モードを試しましたか?

http://developer.android.com/guide/topics/manifest/activity-element.htmlからの説明の一部を次に示します。

...「singleTop」アクティビティの新しいインスタンスを作成して、新しいインテントを処理することもできます。ただし、ターゲット タスクのスタックの最上位に既にアクティビティの既存のインスタンスがある場合、そのインスタンスは (onNewIntent() 呼び出しで) 新しいインテントを受け取ります。新しいインスタンスは作成されません。その他の状況 - たとえば、"singleTop" アクティビティの既存のインスタンスがターゲット タスクにあるがスタックの一番上にない場合、またはスタックの一番上にあるがターゲット タスクにない場合 -新しいインスタンスが作成され、スタックにプッシュされます。

于 2010-12-03T01:15:49.640 に答える
4

おそらくそれはこの問題ですか?または同じバグの他の形式ですか?

于 2011-09-28T19:31:05.583 に答える
4

質問は Xamarin Android とは何の関係もないことを認識していますが、他に見たことがないので投稿したかったのです。

Xamarin Android でこれを修正するために、@DuaneHomick のコードを使用して に追加しましたMainActivity.OnCreate()。Xamarin との違いは、 が and の後に続く必要があることXamarin.Forms.Forms.Init(this, bundle);ですLoadApplication(new App());。だから私OnCreate()は次のようになります:

protected override void OnCreate(Bundle bundle) {
    base.OnCreate(bundle);

    Xamarin.Forms.Forms.Init(this, bundle);
    LoadApplication(new App());

    if(!IsTaskRoot) {
        Intent intent = Intent;
        string action = intent.Action;
        if(intent.HasCategory(Intent.CategoryLauncher) && action != null && action.Equals(Intent.ActionMain, System.StringComparison.OrdinalIgnoreCase)) {
            System.Console.WriteLine("\nIn APP.Droid.MainActivity.OnCreate() - Finishing Activity and returning since a second MainActivity has been created.\n");
            Finish();
            return; //Not necessary if there is no code below
        }
    }
}

*編集: Android 6.0 以降、上記の解決策は特定の状況では不十分です。私も に設定LaunchModeしましたSingleTask。これにより、物事が再び正しく機能するようになりました。残念ながら、これが他のものにどのような影響を与えるかはわかりません。

于 2016-02-15T20:43:57.463 に答える
0

私は同じ問題を抱えていたので、次の解決策を使用して修正しました。

onCreateメイン アクティビティで、メソッドの先頭に次のコードを追加します。

ActivityManager manager = (ActivityManager) this.getSystemService( ACTIVITY_SERVICE );
List<RunningTaskInfo> tasks =  manager.getRunningTasks(Integer.MAX_VALUE);

for (RunningTaskInfo taskInfo : tasks) {
    if(taskInfo.baseActivity.getClassName().equals(<your package name>.<your class name>) && (taskInfo.numActivities > 1)){
        finish();
    }
}

この権限をマニフェストに追加することを忘れないでください。

< uses-permission android:name="android.permission.GET_TASKS" />

それがあなたを助けることを願っています。

于 2011-09-05T14:33:28.770 に答える
0

私もこの問題を抱えていました

  1. finish() を呼び出さないでください。ホーム アクティビティでは無限に実行されます。ホーム アクティビティは、終了時に ActivityManager によって呼び出されます。
  2. 通常、構成が変更されると (つまり、画面の回転、言語の変更、テレフォニー サービスの変更、つまり mcc mnc など)、アクティビティが再作成されます。ホーム アクティビティが実行されている場合は、再度 A を呼び出します。そのために、マニフェストに追加する必要があります android:configChanges="mcc|mnc"。セルラーへの接続があります。システムの起動時またはプッシュオープンなどの設定については、http://developer.android.com/guide/topics/manifest/activity-element.html#configを参照してください。
于 2013-08-29T08:40:01.247 に答える
0

この解決策を試してください:クラスを
作成し、そこで定義します:Application

public static boolean IS_APP_RUNNING = false;

次に、最初の (ランチャー) アクティビティのonCreatesetContentView(...)にこれを追加します。

if (Controller.IS_APP_RUNNING == false)
{
  Controller.IS_APP_RUNNING = true;
  setContentView(...)
  //Your onCreate code...
}
else
  finish();

PSControllerは私のApplicationクラスです。

于 2015-02-17T10:45:10.187 に答える
-2

同じアクティビティを開始しないようにする方法を見つけました。これは私にとってはうまくいきます

if ( !this.getClass().getSimpleName().equals("YourActivityClassName")) {
    start your activity
}
于 2015-12-29T13:39:00.060 に答える
-2

アフィニティをallowtaskreparentingに設定して、 SingleInstance起動モードを使用してみてください 。 これにより、常に新しいタスクでアクティビティが作成されますが、親の変更も許可されます。チェックdis:アフィニティ属性

于 2010-12-03T03:41:20.403 に答える