Google Playストアアプリの"Open"ボタン(以前はAndroid Market)と呼ばれていました)を使用して起動すると、アプリケーションのバグに遭遇しました。 Playストアから起動する場合は、電話機のアイコンのアプリケーションメニューから起動するのとは異なるIntent
を使用するようです。これにより、同じアクティビティの複数のコピーが起動され、互いに競合します。
たとえばアプリがアクティビティA-B-Cで構成されている場合、この問題はA-B-C-Aのスタックにつながる可能性があります。
この問題を解決するためにすべてのアクティビティでAndroid:launchMode="singleTask"
を使用しようとしましたが、HOMEボタンを押すたびにアクティビティスタックをルートにクリアするという望ましくない副作用があります。
予想される動作は次のとおりです A-B-C-> HOME->アプリが復元されたら、A-B-C-> HOME-> A-B-Cが必要です
ホームボタンを使用するときにルートアクティビティにリセットせずに、同じタイプの複数のアクティビティを起動しないようにする良い方法はありますか?
これを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;
}
}
これが失敗する理由と、このバグをプログラムで再現してテストスイートに組み込む方法を説明するだけです。
EclipseまたはMarket Appからアプリを起動すると、意図フラグFLAG_ACTIVITY_NEW_TASKで起動します。
ランチャー(ホーム)から起動する場合、フラグを使用します: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()回避策を組み込んでいない場合、これは問題を再現します。自動テストでこれを使用して、このバグが二度と発生しないことを確認します。
お役に立てれば!
singleTop起動モードを試しましたか?
http://developer.Android.com/guide/topics/manifest/activity-element.html の説明の一部を次に示します。
...「singleTop」アクティビティの新しいインスタンスを作成して、新しいインテントを処理することもできます。ただし、ターゲットタスクのスタックの最上部に既にアクティビティの既存のインスタンスがある場合、そのインスタンスは(onNewIntent()呼び出しで)新しいインテントを受け取ります。新しいインスタンスは作成されません。他の状況-たとえば、「singleTop」アクティビティの既存のインスタンスがターゲットタスクにあるがスタックの最上部にない場合、またはスタックの最上部にあるがターゲットタスクにない場合-新しいインスタンスが作成され、スタックにプッシュされます。
おそらく この問題 ?または、同じバグの他の形?
受け入れられた答え( Duane Homick )は未処理のケースがあると思います:
さまざまな追加機能があります(その結果、アプリが重複します)。
これらのケースとステータスバーの通知を処理している私が生きている解決策(通知の場合はSDK_INT> = 11)があります。
マニフェスト:
<activity
Android:name="com.acme.activity.LauncherActivity"
Android:noHistory="true">
<intent-filter>
<action Android:name="Android.intent.action.MAIN" />
<category Android:name="Android.intent.category.LAUNCHER" />
<category Android:name="Android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service Android:name="com.acme.service.LauncherIntentService" />
ランチャーアクティビティ:
public static Integer lastLaunchTag = null;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInflater = LayoutInflater.from(this);
View mainView = null;
mainView = mInflater.inflate(R.layout.act_launcher, null); // empty layout
setContentView(mainView);
if (getIntent() == null || getIntent().getExtras() == null || !getIntent().getExtras().containsKey(Consts.EXTRA_ACTIVITY_LAUNCH_FIX)) {
Intent serviceIntent = new Intent(this, LauncherIntentService.class);
if (getIntent() != null && getIntent().getExtras() != null) {
serviceIntent.putExtras(getIntent().getExtras());
}
lastLaunchTag = (int) (Math.random()*100000);
serviceIntent.putExtra(Consts.EXTRA_ACTIVITY_LAUNCH_TAG, Integer.valueOf(lastLaunchTag));
startService(serviceIntent);
finish();
return;
}
Intent intent = new Intent(this, SigninActivity.class);
if (getIntent() != null && getIntent().getExtras() != null) {
intent.putExtras(getIntent().getExtras());
}
startActivity(intent);
}
サービス:
@Override
protected void onHandleIntent(final Intent intent) {
Bundle extras = intent.getExtras();
Integer lastLaunchTag = extras.getInt(Consts.EXTRA_ACTIVITY_LAUNCH_TAG);
try {
Long timeStart = new Date().getTime();
while (new Date().getTime() - timeStart < 100) {
Thread.currentThread().sleep(25);
if (!lastLaunchTag.equals(LauncherActivity.lastLaunchTag)) {
break;
}
}
Thread.currentThread().sleep(25);
launch(intent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch(Intent intent) {
Intent launchIintent = new Intent(LauncherIntentService.this, LauncherActivity.class);
launchIintent.addCategory(Intent.CATEGORY_LAUNCHER);
launchIintent.setAction(Intent.ACTION_MAIN);
launchIintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
launchIintent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
if (intent != null && intent.getExtras() != null) {
launchIintent.putExtras(intent.getExtras());
}
launchIintent.putExtra(Consts.EXTRA_ACTIVITY_LAUNCH_FIX, true);
startActivity(launchIintent);
}
通知:
ComponentName actCN = new ComponentName(context.getPackageName(), LauncherActivity.class.getName());
Intent contentIntent = new Intent(context, LauncherActivity.class);
contentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 11) {
contentIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // if you need to recreate activity stack
}
contentIntent.addCategory(Intent.CATEGORY_LAUNCHER);
contentIntent.setAction(Intent.ACTION_MAIN);
contentIntent.putExtra(Consts.EXTRA_CUSTOM_DATA, true);
この質問はXamarin Androidとは何の関係もありませんが、他のどこにも見られなかったので何かを投稿したかったのです。
Xamarinでこれを修正するには、Android @DuaneHomickのコードを使用して、MainActivity.OnCreate()
に追加しました。Xamarinとの違いは、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
に設定しました。残念ながら、これが他のものにどのような影響を与えるかはわかりません。
この解決策を試してください:Application
クラスを作成し、そこで定義します:
_public static boolean IS_APP_RUNNING = false;
_
次に、setContentView(...)
の前のonCreate
での最初の(ランチャー)アクティビティでこれを追加します。
_if (Controller.IS_APP_RUNNING == false)
{
Controller.IS_APP_RUNNING = true;
setContentView(...)
//Your onCreate code...
}
else
finish();
_
追伸Controller
は私のApplication
クラスです。
この問題もありました
Android:configChanges="mcc|mnc"
-携帯電話に接続している場合は、 http://developer.Android.com/guide/topics/manifest/activity-element.html#config を参照してください。システムまたはプッシュオープンなど。