强制应用程序重新启动第一个活动

由于一个未知的原因,我不能让我的应用程序正常离开,所以当我再次按下主页button和应用程序图标时,我恢复了在应用程序中的位置。 我想强制应用程序在第一个活动重新启动。

我想这与onDestroy()或onPause()有关,但我不知道该怎么做。

以下是使用PackageManager以通用方式重新启动应用程序的示例:

Intent i = getBaseContext().getPackageManager() .getLaunchIntentForPackage( getBaseContext().getPackageName() ); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i); 

标有“答案”的解决scheme有效,但有一个缺点对我至关重要。 使用FLAG_ACTIVITY_CLEAR_TOP,您的目标活动将在您的旧活动堆栈收到onDestroy之前调用onCreate。 虽然我已经在onDestroy中清除了一些必要的东西,但我不得不努力工作。

这是为我工作的解决scheme:

 public static void restart(Context context, int delay) { if (delay == 0) { delay = 1; } Log.e("", "restarting app"); Intent restartIntent = context.getPackageManager() .getLaunchIntentForPackage(context.getPackageName() ); PendingIntent intent = PendingIntent.getActivity( context, 0, restartIntent, Intent.FLAG_ACTIVITY_CLEAR_TOP); AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); manager.set(AlarmManager.RTC, System.currentTimeMillis() + delay, intent); System.exit(2); } 

这个想法是通过AlarmManager触发一个PendingIntent,稍后会调用它,给旧的活动堆栈一些时间来清理。

如果你想始终从根目录开始,你要设置android:clearTaskOnLaunch为你的根活动的true

 android:clearTaskOnLaunch="true" android:launchMode="singleTask" 

在启动类(第一个活动)的清单文件中使用此属性。

FLAG_ACTIVITY_CLEAR_TOP是否做你需要做的事情?

 Intent i = new Intent(getBaseContext(), YourActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i); 

马克的答案很好,除了我的主要活动有一个singleTop的launchMode。 一旦我运行这个意图,然后导航到新的活动,并按设备上的主页button,然后从应用程序图标再次启动我的应用程序,我最终创build一个新的主要活动的实例,与我以前的活动在后面的堆栈。

根据这个问题,这是因为意图不匹配。 看看adb dumpsys activity ,我看到从我的标准android启动程序,包是空的,而当我这样做,马克build议,intent包是我的包的名称。 这种差异导致它们不匹配,并且当再次点击应用图标并且主要活动不在最上面时开始新的实例。

然而,在其他的发射器上,就像在Kindle上一样,这个包在发射器的意图上设置的,所以我需要一个通用的方式来处理发射器。 我添加了这样的静态方法:

 static boolean mIsLaunchIntentPackageNull = true; public static boolean isLaunchIntent(Intent i) { if (Intent.ACTION_MAIN.equals(i.getAction()) && i.getCategories() != null && i.getCategories().contains(Intent.CATEGORY_LAUNCHER)) { return true; } return false; } public static void handleLaunchIntent(Intent i) { if (isLaunchIntent(i)) { if (i.getPackage() != null) { mIsLaunchIntentPackageNull = false; } else { mIsLaunchIntentPackageNull = true; } } } 

像这样的回家机制:

  Intent intentHome = appContext.getPackageManager() .getLaunchIntentForPackage( appContext.getPackageName()); intentHome.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // need to match launcher intent exactly to avoid duplicate activities in stack if (mIsLaunchIntentPackageNull) { intentHome.setPackage(null); } appContext.startActivity(intentHome); 

那么在我的清单中定义的主要活动中,我添加了这一行:

 public void onCreate(Bundle savedInstanceState) { [class from above].handleLaunchIntent(getIntent()); 

这对kindle和我的手机适用于我,并让我正确地重置应用程序而不添加主要活动的另一个实例。

FLAG_ACTIVITY_CLEAR_TOP不适合我,因为我必须支持2.3.3。 我第一个解决scheme是:

 Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); intent.addFlags(Build.VERSION.SDK_INT >= 11 ? Intent.FLAG_ACTIVITY_CLEAR_TASK : Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(intent); 

这几乎起作用,但不完全。

由于我有一个基本的Activity,所以我添加了一个closures所有正在运行的活动的kill广播。

 public abstract class BaseActivity extends AppCompatActivity { private static final String ACTION_KILL = "BaseActivity.action.kill"; private static final IntentFilter FILTER_KILL; static { FILTER_KILL = new IntentFilter(); FILTER_KILL.addAction(ACTION_KILL); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); registerReceiver(killReceiver, FILTER_KILL); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(killReceiver); } private final BroadcastReceiver killReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { finish(); } }; public void killApp(){ sendBroadcast(new Intent(ACTION_KILL)); } } 

我所有的活动都是从这个class开始的

 ((BaseActivity)getActivity()).killApp(); startActivity(new Intent(getActivity(), StartActivity.class)); 

重新启动应用程序。 testinggenymotion v10,v16,v21和Nexus 5与v22。

编辑:这不会删除一个活动,如果它在发送意图时被销毁。 我仍然在寻找一个解决scheme。

下面的代码是为我工作,它可以完全重新启动完整的应用程序!

 Intent mStartActivity = new Intent(context, StartActivity.class); int mPendingIntentId = 123456; PendingIntent mPendingIntent = PendingIntent.getActivity(context,mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent); System.exit(0); 

这对我工作:

 Intent mStartActivity = new Intent(ctx.getApplicationContext(), ActivityMain.class); mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mStartActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) mStartActivity.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK int mPendingIntentId = 123456; PendingIntent mPendingIntent = PendingIntent.getActivity(ctx, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, mPendingIntent); ActivityManager manager = (ActivityManager) ctx.getApplicationContext().getSystemService(ctx.getApplicationContext().ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> activityes = ((ActivityManager)manager).getRunningAppProcesses(); ((Activity)ctx).moveTaskToBack(true); manager.killBackgroundProcesses("com.yourpackagename"); System.exit(0); 

经过艰苦的思考和testing后,我最终得到了正确的方式来调用我的活动来重新创build应用程序的主页button时:

 android:clearTaskOnLaunch 

在清单中

 @Override public void onRestart(){ onCreate(); } 

这样做的技巧…(比每次启动应用程序时都要调用的onResume更好,即使是第一次,也会导致双重显示)