Force application to restart on first activity

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

我认为这和 Destroy ()或者 Puse ()有关,但是我不知道该怎么做。

99863 次浏览

如果您想始终从根开始,那么您需要在根活动中将 Android: clearTaskOnLaunch设置为 true

After hard thinking and testing I finally got the right way of calling my activity to recreate when the app is left with the home button :

android:clearTaskOnLaunch

在旅客名单上

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

这确实有效... (比放在 onResume 中要好,后者在每次启动应用程序时都会调用,即使是第一次,也会导致双重显示)

FLAG _ ACTIVITY _ CLEAR _ TOP 是否做您需要做的事情?

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

下面是一个使用 PackageManager 以通用方式重新启动应用程序的例子:

Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
android:clearTaskOnLaunch="true"
android:launchMode="singleTask"

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

标记为“答案”的解决方案有效,但有一个对我来说至关重要的缺点。 With FLAG_ACTIVITY_CLEAR_TOP your target activity will get onCreate called before your old activity stack receives onDestroy. While I have been clearing some necessary stuff in onDestroy I had to workaroud.

This is the solution that worked for me:

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 激发一个 PendingInent,稍后将调用它,给旧的活动堆栈一些时间来清理。

Marc 的回答非常好用,除了我的主要活动有一个 singleTop 的 launchMode。一旦我运行了这个意图,然后导航到新的 Activity,并按下设备上的 home 按钮,然后从应用程序图标再次启动我的应用程序,我最终创建了一个新的主活动实例,将我以前的活动放在后面的堆栈上。

根据 这个问题这是因为意图不匹配。看看 adb dumpsys activity,我发现从我的标准 android 启动程序来看,软件包是空的,而当我按照 Marc 的建议做时,意图软件包就是我的软件包的名称。这种差异导致它们不匹配,并在应用程序图标再次被点击且主活动不在顶部时启动一个新实例。

然而,在其他的启动程序上,比如 Kindle,包 is设置了启动程序的意图,所以我需要一个通用的方法来处理启动程序。我添加了静态方法,比如:

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 和我的手机,并让我正确地重置应用程序 w/o 添加另一个实例的主要活动。

这招对我很管用:

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);

FLAG_ACTIVITY_CLEAR_TOP didn't work for me because I had to support 2.3.3. My first solution was:

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,所以我添加了一个 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));
}
}

All of my activities extend from this class, so

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

restarts the app. Tested on genymotion v10, v16, v21 and Nexus 5 with v22.

编辑:如果活动在发送意图时被销毁,则不会删除该活动。我还在寻找解决办法。

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

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);

您可以使用 Jake Wharton 的 lib 凤凰行动来重新启动应用程序过程。

你应该检查一下这个问题:

以编程方式重启 Android 应用程序

解决办法是:

private void restartApp()
{
Intent intent = new Intent(getApplicationContext(), YourStarterActivity.class);
int mPendingIntentId = MAGICAL_NUMBER;
PendingIntent mPendingIntent = PendingIntent.getActivity(getApplicationContext(), mPendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);
}