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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2470870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:58:23  来源:igfitidea点击:

Force application to restart on first activity

android

提问by Sephy

For an unknown reason, I can't get my application leaving properly so that when I push the home button and the app icon again, I resume where I was in the app. I would like to force the application to restart on the first Activity.

由于未知原因,我无法让我的应用程序正常退出,因此当我再次按下主页按钮和应用程序图标时,我会恢复到我在应用程序中的位置。我想强制应用程序在第一个活动上重新启动。

I suppose this has something to do with onDestroy() or maybe onPause() but I don't know what to do.

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

回答by Marc

Here is an example to restart your app in a generic way by using the PackageManager:

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

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

回答by AAverin

The solution marked as 'answer' works but has one disadvantage that was critical for me. 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.

标记为“答案”的解决方案有效,但有一个对我来说至关重要的缺点。使用 FLAG_ACTIVITY_CLEAR_TOP,您的目标活动将在旧活动堆栈接收 onDestroy 之前调用 onCreate。虽然我一直在清除 onDestroy 中的一些必要内容,但我不得不解决。

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

The idea is to fire a PendingIntent via AlarmManager that will be invoked a bit later, giving old activity stack some time to clear up.

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

回答by jqpubliq

if you want to always start at the root you want to set android:clearTaskOnLaunchto true on your root activity

如果您想始终从根开始,您想在根活动中将android:clearTaskOnLaunch设置为 true

回答by Rishi Gautam

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

Use this property in manifest file in starting class (first activity).

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

回答by DariusL

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

FLAG_ACTIVITY_CLEAR_TOP对我不起作用,因为我必须支持 2.3.3。我的第一个解决方案是:

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

This almost works, but not quite.

这几乎有效,但不完全有效。

Since I have a base Activity, I added a kill broadcast that closes all my running activities.

因为我有一个基本活动,所以我添加了一个终止广播来关闭我所有正在运行的活动。

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.

重新启动应用程序。在 genymotion v10、v16、v21 和带有 v22 的 Nexus 5 上测试。

Edit: this does not remove an activity if it is destroyed at the time of sending the intent. I'm still looking for a solution.

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

回答by Bert

Does FLAG_ACTIVITY_CLEAR_TOP do what you need to do?

FLAG_ACTIVITY_CLEAR_TOP 做你需要做的吗?

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

回答by Mike Venzke

Marc's answer works great, except in my case where my main activity has a launchMode of singleTop. Once I run this intent and then navigate to new Activities and press the home button on the device, then launch my app again from the app icon, I end up creating a new instance of the main Activity, with my previous activity on the back stack.

Marc 的回答非常有效,除了在我的主要活动的 launchMode 为 singleTop 的情况下。一旦我运行这个意图,然后导航到新的活动并按下设备上的主页按钮,然后从应用程序图标再次启动我的应用程序,我最终创建了一个主活动的新实例,我之前的活动在后堆栈中.

According to this questionit's because the intents don't match. Looking at adb dumpsys activity, I see that from my standard android launcher, the package is null, whereas when I do as Marc suggests, the intent package is the name of my package. This difference causes them to not match and to start a new instance when the app icon is tapped again and the main activity isn't on top.

根据这个问题,这是因为意图不匹配。看着adb dumpsys activity,我从我的标准 android 启动器中看到,包为空,而当我按照 Marc 的建议进行操作时,意图包是我的包的名称。这种差异导致它们不匹配并在再次点击应用程序图标并且主要活动不在顶部时启动新实例。

However, on other launchers, like on Kindle, the package isset on the launcher intent, so I needed a generic way to handle launchers. I added static methods like such:

但是,在其他启动器(例如 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;
        }
    }
}

with a go home mechanism like this:

使用这样的回家机制:

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

then in the main activity defined in my manifest, I added this line:

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

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

this works for me on kindle and my phone, and lets me properly reset the app w/o adding another instance of the main activity.

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

回答by Beatrice Lin

The following code is work for me, it can restart full app perfectly!

以下代码对我有用,它可以完美地重新启动完整的应用程序!

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

回答by mol

You can use Jake Wharton's lib ProcessPhoenixin order to restart your application process.

您可以使用 Jake Wharton 的 lib ProcessPhoenix来重新启动您的应用程序进程。

回答by Veljko Milisavljevi?

this worked for me:

这对我有用:

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