如何以编程方式“重启”Android 应用程序?

Posted

技术标签:

【中文标题】如何以编程方式“重启”Android 应用程序?【英文标题】:How do I programmatically "restart" an Android app? 【发布时间】:2011-09-30 08:46:59 【问题描述】:

首先,我知道不应该真正杀死/重新启动 android 上的应用程序。在我的用例中,我想在服务器向客户端发送一条特定信息的特定情况下将我的应用程序恢复出厂设置。

用户只能使用一个应用程序实例登录服务器(即不允许使用多个设备)。如果另一个实例获得了“登录”锁定,那么该用户的所有其他实例都必须删除他们的数据(恢复出厂设置),以保持一致性。

可以强制获取锁,因为用户可能会删除应用程序并重新安装它,这会导致不同的 instance-id 并且用户将无法再释放锁。因此可以强制获取锁。

由于这种强制的可能性,我们需要始终检查一个具体的实例,它有锁。这是在(几乎)对服务器的每个请求上完成的。服务器可能会发送“错误锁定 ID”。如果检测到这种情况,客户端应用程序必须删除所有内容。


这就是用例。

我有一个 Activity A 启动登录 Activity L 或应用程序的主 Activity B 取决于 sharedPrefs 值。在启动 L 或 B 后,它会自行关闭,以便只有 L 或 B 正在运行。所以在用户已经登录的情况下,B 正在运行。

B 启动 C。C 为 IntentService D 调用 startService。这导致了这个堆栈:

(A) > B > C > D

从D的onHandleIntent方法,一个事件被发送到ResultReceiverR。

R 现在通过向用户提供一个对话框来处理该事件,用户可以在该对话框中选择将应用程序恢复出厂设置(删除数据库、sharedPrefs 等)

恢复出厂设置后,我想重新启动应用程序(关闭所有活动),然后再次启动 A,然后启动登录 Activity L 并自行完成:

(A) > L

Dialog 的 onClick 方法如下所示:

@Override
public void onClick(DialogInterface dialog, int which) 

    // Will call onCancelListener
    MyApplication.factoryReset(); // (Deletes the database, clears sharedPrefs, etc.)
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);

这就是MyApp 类:

public class MyApp extends Application 
    private static Context context;

    @Override
    public void onCreate() 
        super.onCreate();
        context = getApplicationContext();
    

    public static Context getContext() 
        return context;
    

    public static void factoryReset() 
        // ...
    

问题是如果我使用FLAG_ACTIVITY_NEW_TASK,活动 B 和 C 仍在运行。如果我在登录 Activity 上点击返回按钮,我会看到 C,但我想返回主屏幕。

如果我没有设置 FLAG_ACTIVITY_NEW_TASK 我会得到错误:

07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

我不能使用活动的Context,因为ServiceIntent D 也可能从AlarmManager 启动的后台任务中调用。

那么我该如何解决这个活动堆栈变成 (A) > L 的问题?

【问题讨论】:

【参考方案1】:

您可以使用PendingIntent 设置将来启动您的启动活动,然后关闭您的应用程序

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

【讨论】:

这对我来说非常有效!我刚刚使用了 android.os.Process.killProcess(android.os.Process.myPid());通过 System.exit(); 在 4.3 和 4.4 设备(我测试过的所有设备)上,这似乎会终止当前活动,然后在旧活动之上启动一个新活动。我有 2 个活动深度(主要 -> 首选项)。按返回会将我带到旧应用程序,返回一屏。 在我的例子中, System.exit(0) 没有工作,因为事务正在回滚。相反,我使用了 activity.finish();它工作得很好。 @Qulin,伙计们!你不能是认真的!这个例子更像是方向而不是现实生活中的例子。您必须使用启动活动名称、意图 ID 和退出机制来修改此 sn-p,无论您使用什么。不要盲目复制粘贴。 由于对后台活动的新限制developer.android.com/preview/privacy/…,这不再适用于 Android Q【参考方案2】:

您可以简单地调用:

public static void triggerRebirth(Context context, Intent nextIntent) 
    Intent intent = new Intent(context, YourClass.class);
    intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra(KEY_RESTART_INTENT, nextIntent);
    context.startActivity(intent);
    if (context instanceof Activity) 
      ((Activity) context).finish();
    

    Runtime.getRuntime().exit(0);

在ProcessPhoenix 库中使用


作为替代方案:

这是@Oleg Koshkin 答案的一些改进版本。

如果您真的想重新启动您的活动,包括终止当前进程,请尝试以下代码。将它放在 HelperClass 或您需要的地方。

public static void doRestart(Context c) 
        try 
            //check if the context is given
            if (c != null) 
                //fetch the packagemanager so we can get the default launch activity 
                // (you can replace this intent with any other activity if you want
                PackageManager pm = c.getPackageManager();
                //check if we got the PackageManager
                if (pm != null) 
                    //create the intent with the default start activity for your application
                    Intent mStartActivity = pm.getLaunchIntentForPackage(
                            c.getPackageName()
                    );
                    if (mStartActivity != null) 
                        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        //create a pending intent so the application is restarted after System.exit(0) was called. 
                        // We use an AlarmManager to call this intent in 100ms
                        int mPendingIntentId = 223344;
                        PendingIntent mPendingIntent = PendingIntent
                                .getActivity(c, mPendingIntentId, mStartActivity,
                                        PendingIntent.FLAG_CANCEL_CURRENT);
                        AlarmManager mgr = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
                        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
                        //kill the application
                        System.exit(0);
                     else 
                        Log.e(TAG, "Was not able to restart application, mStartActivity null");
                    
                 else 
                    Log.e(TAG, "Was not able to restart application, PM null");
                
             else 
                Log.e(TAG, "Was not able to restart application, Context null");
            
         catch (Exception ex) 
            Log.e(TAG, "Was not able to restart application");
        
    

这也将重新初始化 jni 类和所有静态实例。

【讨论】:

这个解决方案很好,但它会延迟几秒钟直到它重新启动您的应用程序,即使您减少了 100 Millis。但是,Jack Wharton 的这个库 ProcessPhoenix 做得更好更快,但不值得在应用程序中只为这个函数添加库。 @blueware 我已经更新了我的答案并添加了在 ProcessPhonix 中使用的代码 @mikepenz,这个家伙“Ilya_Gazman”做得更好,而且没有使用这样的库。 @blueware - 除了 Ilya 的解决方案不会重新启动进程,因此静态数据或加载的 NDK 库将无法正确重新初始化。 如果我的应用程序关闭并且没有重新启动怎么办?我尝试了各种方法,应用程序无法重新启动。有时确实如此,但它会在几分之一秒内再次关闭。而且我在 Android Studio 的 logcat 中看不到任何错误...任何想法可能是什么问题?【参考方案3】:

我稍微修改了 Ilya_Gazman 的答案以使用新的 API(从 API 26 开始不推荐使用 IntentCompat)。 Runtime.getRuntime().exit(0) 似乎比 System.exit(0) 好。

 public static void triggerRebirth(Context context) 
    PackageManager packageManager = context.getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
    ComponentName componentName = intent.getComponent();
    Intent mainIntent = Intent.makeRestartActivityTask(componentName);
    context.startActivity(mainIntent);
    Runtime.getRuntime().exit(0);

【讨论】:

直接来自the docs:“调用 System.exit(n) 实际上等同于调用: Runtime.getRuntime().exit(n)”。在内部,System.exit() 只是转身打电话给Runtime.getRuntime().exit()。没有什么比其中一个“更好”了(除非一个人关心打字的多少或一个额外的方法调用层)。 何时何地调用上述方法? @Makvin 你决定在哪里调用它。我的情况是语言更改后重新启动应用程序。 @TedHopp 对每个答案都评论为“不好”,您有任何可行的解决方案吗?不讽刺,真的需要重新创建一个应用程序而不留下任何痕迹;从静态变量到类实例。 @FARID - 任何涉及调用Runtime.getRuntime().exit(0)(或System.exit(0))的解决方案都可能有效。我的一些“不好”的 cmets 是为了回答(例如 Ilya Gazman 的那个,后来经过编辑以包含这样一个电话。【参考方案4】:

Jake Wharton 最近发布了他的 ProcessPhoenix 库,它以可靠的方式做到了这一点。你基本上只需要打电话:

ProcessPhoenix.triggerRebirth(context);

该库会自动完成调用活动,杀死应用程序进程,然后重新启动默认应用程序活动。

【讨论】:

这似乎有效,但我遇到了崩溃(被报告)。不确定这是否理想。 我从来没有遇到过这个库的任何问题,但请随时在github.com/JakeWharton/ProcessPhoenix/issues报告错误 啊,我撤回了我的评论,因为我没有足够仔细地查看消息。我的默认启动活动缺少意图过滤器。可能值得注意的是所需的确切意图过滤器。 这是迄今为止最好的解决方案。 @Shambhu 您必须将标签 <category android:name="android.intent.category.DEFAULT" /> 添加到应用清单中的默认活动 中。【参考方案5】:

IntentCompat.makeMainSelectorActivity - 最后测试于 11/2020

应用程序将通过启动器活动恢复,旧进程将被终止。

从 Api 15 开始工作。

public static void restart(Context context)
    Intent mainIntent = IntentCompat.makeMainSelectorActivity(Intent.ACTION_MAIN, Intent.CATEGORY_LAUNCHER);
    mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.getApplicationContext().startActivity(mainIntent);
    System.exit(0);

【讨论】:

这会重新启动任务,但不会重新启动进程,甚至不会重新启动 Application 对象。因此,任何static 数据、在创建Application 期间初始化的数据或 jni 类都保持其当前状态并且不会重新初始化。 @TedHopp 哦,我错过了那部分。我添加了 System.exit(0);但我不确定它是否会 100% 起作用。我稍后会测试它 不使用开源库的最佳解决方案。举起手来,感谢您提供这个答案,+1 不幸的是,IntentCompat.makeRestartActivityTask is now deprecated。如果您inspect the source code,则只需添加标志Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK 查看下面的答案以获得完整的最新功能:***.com/a/46848226/1069083【参考方案6】:

我的解决方案不会重新启动进程/应用程序。它只允许应用程序“重新启动”家庭活动(并关闭所有其他活动)。对用户来说,这看起来像是重新启动,但过程是一样的。我认为在某些情况下人们想要达到这种效果,所以我把它留在这里仅供参考。

public void restart()
    Intent intent = new Intent(this, YourHomeActivity.class);
    this.startActivity(intent);
    this.finishAffinity();

【讨论】:

你太棒了兄弟:D 尝试了所有答案。但只有您的代码有效。谢谢【参考方案7】:

有一个非常好的技巧。我的问题是一些非常老的 C++ jni 库泄露了资源。在某个时候,它停止了运作。用户尝试退出应用程序并再次启动它 - 没有结果,因为完成活动与完成(或终止)进程不同。 (顺便说一句,用户可以转到正在运行的应用程序列表并从那里停止它——这会起作用,但用户只是不知道如何终止应用程序。)

如果您想观察此功能的效果,请将static 变量添加到您的活动中,并在每次按下按钮时增加它。如果您退出应用程序活动,然后再次调用应用程序,此静态变量将保持其值。 (如果应用程序真的退出了,该变量将被赋予初始值。)

(我不得不评论为什么我不想修复这个错误。这个库是几十年前写的,从那以后就泄露了资源。管理层认为它总是有效。提供修复而不是解决方法的成本...我想,你明白了。)

现在,我如何将 jni 共享(又名动态,.so)库重置为初始状态? 我选择重新启动应用程序作为一个新进程。

诀窍在于 System.exit() 关闭当前活动,Android 重新创建应用程序,减少一个活动。

所以代码是:

/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity 
    // Do not forget to add it to AndroidManifest.xml
    // <activity android:name="your.package.name.MagicAppRestart"/>
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        System.exit(0);
    
    public static void doRestart(Activity anyActivity) 
        anyActivity.startActivity(new Intent(anyActivity.getApplicationContext(), MagicAppRestart.class));
    

调用Activity只是执行代码MagicAppRestart.doRestart(this);,调用Activity的onPause()被执行,然后重新创建流程。并且不要忘记在 AndroidManifest.xml 中提及此活动

这种方法的优点是没有延迟。

UPD:它在 Android 2.x 中有效,但在 Android 4 中有所改变。

【讨论】:

我使用了activity.startActivity(i); System.exit(0);天才解决方案 此解决方案会为我关闭应用程序,但不会重新启动。至少在 Android 4.3 上。 在三星 Galaxy Mega android 4.2.2 上会导致无限循环重启。所以应用程序不会重新启动。 @Gunhan 1) 如果将System.exit(0) 替换为android.os.Process.killProcess(android.os.Process.myPid()); 会发生什么? 2)无限循环很可能意味着他们在重新启动应用程序时不会删除最顶层的活动。原则上,你可以添加一个静态布尔变量,在调用重新启动活动之前将其设置为 true,在重新启动后将其设置为 false。因此,Activity 可以查明重启是否已经发生(如果已经发生,只需 finish())。 OTOH,您的报告意味着该技巧并非在所有设备上都相同。 @Gunham 如果您正在启动导致重新启动的相同活动,那么它将在任何设备上无限循环。【参考方案8】:

我发现这适用于 API 29 及更高版本 - 目的是为了杀死和重新启动应用程序,就好像用户在应用程序未运行时启动它一样。

public void restartApplication(final @NonNull Activity activity) 
   // Systems at 29/Q and later don't allow relaunch, but System.exit(0) on
   // all supported systems will relaunch ... but by killing the process, then
   // restarting the process with the back stack intact. We must make sure that
   // the launch activity is the only thing in the back stack before exiting.
   final PackageManager pm = activity.getPackageManager();
   final Intent intent = pm.getLaunchIntentForPackage(activity.getPackageName());
   activity.finishAffinity(); // Finishes all activities.
   activity.startActivity(intent);    // Start the launch activity
   System.exit(0);    // System finishes and automatically relaunches us.

当应用程序中的启动器活动具有以下内容时完成:

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

我见过 cmets 声称需要一个 DEFAULT 类别,但我没有发现这种情况。我已经确认我的应用程序中的 Application 对象是重新创建的,所以我相信该进程确实已经被杀死并重新启动。

我使用它的唯一目的是在用户启用或禁用 Firebase Crashlytics 的崩溃报告后重启应用。根据他们的文档,必须重新启动应用程序(终止并重新创建进程)才能使更改生效。

【讨论】:

如果您的单个 APK 暴露了多个启动器图标,则需要 DEFAULT 不工作。 Android 版本 11。【参考方案9】:

唯一没有触发“您的应用已意外关闭”的代码如下。它也是不需要外部库的非弃用代码。它也不需要计时器。

public static void triggerRebirth(Context context, Class myClass) 
    Intent intent = new Intent(context, myClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(intent);
    Runtime.getRuntime().exit(0);

【讨论】:

【参考方案10】:

好的,我重构了我的应用程序,我不会自动完成 A。我让它一直运行并通过onActivityResult 事件完成它。 这样我就可以使用FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_NEW_TASK 标志来获得我想要的:

public class A extends Activity 

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        super.onActivityResult(requestCode, resultCode, data);
        finish();
    

    protected void onResume() 
        super.onResume();
        // ...
        if (loggedIn) 
            startActivityForResult(new Intent(this, MainActivity.class), 0);
         else 
            startActivityForResult(new Intent(this, LoginActivity.class), 0);
        
    

ResultReceiver

@Override
public void onClick(DialogInterface dialog, int which) 
    MyApp.factoryReset();
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);

还是谢谢!

【讨论】:

这将不会重新启动应用程序,只会重新创建类。因此,类中的任何静态变量都将保留以前运行的值。【参考方案11】:
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);

【讨论】:

这将不会重新启动应用程序,只会重新创建类。因此,类中的任何静态变量都将保留以前运行的值。【参考方案12】:

完全重新启动应用程序的最佳方法是重新启动它,而不仅仅是跳转到带有FLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_NEW_TASK 的活动。所以我的解决方案是从您的应用程序甚至从另一个应用程序执行此操作,唯一的条件是知道应用程序包名称(例如:'com.example.myProject')

 public static void forceRunApp(Context context, String packageApp)
    Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageApp);
    launchIntent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(launchIntent);

appB 重新启动或启动 appA 的使用示例:

forceRunApp(mContext, "com.example.myProject.appA");

您可以检查应用程序是否正在运行:

 public static boolean isAppRunning(Context context, String packageApp)
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
    for (int i = 0; i < procInfos.size(); i++) 
        if (procInfos.get(i).processName.equals(packageApp)) 
           return true;
        
    
    return false;

注意:我知道这个答案有点离题,但它对某人真的很有帮助。

【讨论】:

【参考方案13】:

我最好的重启应用程序的方法是使用finishAffinity(); 因为,finishAffinity(); 只能用于 JELLY BEAN 版本,所以我们可以将ActivityCompat.finishAffinity(YourCurrentActivity.this); 用于较低版本。

然后使用Intent 启动第一个活动,因此代码将如下所示:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) 
    finishAffinity();
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
 else 
    ActivityCompat.finishAffinity(YourCurrentActivity.this);
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);

希望对你有帮助。

【讨论】:

这会结束当前任务中的所有活动,但不会重新启动进程,甚至不会重新创建Application对象。因此,任何静态数据、在创建应用程序期间初始化的数据或由 jni 类初始化的数据都将保持其当前状态并且不会重新初始化。【参考方案14】:

仍在工作

 public void resetApplication() 
    Intent resetApplicationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
    if (resetApplicationIntent != null) 
        resetApplicationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    
    context.startActivity(resetApplicationIntent);
    ((Activity) context).overridePendingTransition(R.anim.fade_in, R.anim.fade_out);

【讨论】:

重启活动(和任务堆栈),但不会重启整个应用程序。具体来说,如果您有一个 Application 子类,或者如果您有带有状态数据的静态类,这些对象将不会被重新初始化。【参考方案15】:

尝试使用FLAG_ACTIVITY_CLEAR_TASK

【讨论】:

hm 为 2.1 开发:Intent.FLAG_ACTIVITY_CLEAR_TASK 无法解析 抱歉 - 自:API 级别 11 developer.android.com/reference/android/content/…【参考方案16】:

这是一个使用 PackageManager 以通用方式重启应用的示例:

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

【讨论】:

这会重新启动任务,但不会重新启动进程,甚至不会重新启动 Application 对象。因此,任何静态数据、在创建 Application 期间初始化的数据或 jni 类都保持其当前状态并且不会重新初始化。【参考方案17】:

this 答案的 Kotlin 版本:

val intent = Intent(this, YourActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
Runtime.getRuntime().exit(0)

【讨论】:

【参考方案18】:

您可以使用ActivitystartInstrumentation 方法。您需要实现空的Instrumentation 并在清单中指出。之后,您可以调用此方法重新启动您的应用程序。像这样:

try            
    InstrumentationInfo info = getPackageManager().queryInstrumentation(getPackageName(), 0).get(0);
    ComponentName component = new ComponentName(this, Class.forName(info.name));
    startInstrumentation(component, null, null);
 catch (Throwable e)              
    new RuntimeException("Failed restart with Instrumentation", e);

我动态获取 Instrumentation 类名称,但您可以对其进行硬编码。有些是这样的:

try            
    startInstrumentation(new ComponentName(this, RebootInstrumentation.class), null, null); 
 catch (Throwable e)              
    new RuntimeException("Failed restart with Instrumentation", e);

致电startInstrumentation 重新加载您的应用。阅读此方法的说明。但是如果表现得像 kill app 那样可能是不安全的。

【讨论】:

【参考方案19】:

我正在开发的应用程序必须让用户能够选择显示哪些片段(片段在运行时动态更改)。对我来说最好的解决方案是完全重启应用程序。

所以我尝试了很多解决方案,但没有一个对我有用,但是这个:

final Intent mStartActivity = new Intent(SettingsActivity.this, Splash.class);
final int mPendingIntentId = 123456;
final PendingIntent mPendingIntent = PendingIntent.getActivity(SettingsActivity.this, mPendingIntentId, mStartActivity,
                    PendingIntent.FLAG_CANCEL_CURRENT);
final AlarmManager mgr = (AlarmManager) SettingsActivity.this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
this.finishAffinity(); //notice here
Runtime.getRuntime().exit(0); //notice here

希望这会对其他人有所帮助!

【讨论】:

【参考方案20】:

使用FLAG_ACTIVITY_CLEAR_TASK和FLAG_ACTIVITY_NEW_TASK直接启动初始屏幕。

【讨论】:

【参考方案21】:
fun triggerRestart(context: Activity) 
    val intent = Intent(context, MainActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    context.startActivity(intent)
    if (context is Activity) 
        (context as Activity).finish()
    
    Runtime.getRuntime().exit(0)

【讨论】:

【参考方案22】:

我不得不添加一个Handler来延迟退出:

 mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 200, mPendingIntent);
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() 
            @Override
            public void run() 
                Runtime.getRuntime().exit(0);
            
        , 100);

【讨论】:

你为什么要延迟杀死部分。这个答案没有根据,在更好的答案后 6 年添加。【参考方案23】:

用途:

navigateUpTo(new Intent(this, MainActivity.class));

我相信它从 API 级别 16 (4.1) 开始工作。

【讨论】:

【参考方案24】:

试试这个:

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

【讨论】:

正如这里所有其他答案已经暗示了同样的事情,这不会重新启动应用程序,只会重新创建类。因此,进程中的任何静态数据都不会被重置。【参考方案25】:

使用Process Phoenix library。您要重新启动的 Activity 名为“A”。

Java 风格

// Java
public void restart()
    ProcessPhoenix.triggerRebirth(context);

Kotlin 风味

// kotlin
fun restart() 
    ProcessPhoenix.triggerRebirth(context)

【讨论】:

这会导致调试器断开连接。 @S.V. - AFAIK,任何终止进程的解决方案(为了以干净状态重新启动),都会断开调试器。认为“症状”是这种方法真正让您重新开始的标志。【参考方案26】:

应用延迟重启

startDelay 启动延迟(以毫秒为单位)

 public static void reStartApp(Context context, long startDelay) 
    //Obtain the startup Intent of the application with the package name of the application
    Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
    PendingIntent restartIntent = PendingIntent.getActivity(context.getApplicationContext(), -1, intent, PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    if (mgr != null) 
        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + startDelay, restartIntent);
    

【讨论】:

【参考方案27】:

Mikepenz 的替代答案需要对我的情况进行一些更改。 https://***.com/a/22345538/12021422 主要归功于 Mikepenz 的答案,我可以修改。

这是对我有用的即插即用静态功能。

只需传递应用程序的上下文,此函数将处理重启。

    public static void doRestart(Context c) 
        try 
            // check if the context is given
            if (c != null) 
                // fetch the package manager so we can get the default launch activity
                // (you can replace this intent with any other activity if you want
                PackageManager pm = c.getPackageManager();
                // check if we got the PackageManager
                if (pm != null) 
                    // create the intent with the default start activity for your application
                    Intent mStartActivity = pm.getLaunchIntentForPackage(c.getPackageName());
                    if (mStartActivity != null) 
                        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        
                        c.getApplicationContext().startActivity(mStartActivity);
                        // kill the application
                        System.exit(0);
                    
                
            
         catch (Exception e) 
            e.printStackTrace();
            Log.e("restart", "Could not Restart");
        
    

【讨论】:

【参考方案28】:

嘿兄弟,如果您想通过单击按钮重新启动应用程序,请编写此代码并记住使用按钮名称更改重置,如果您将在 sn-p 中运行它,它将无法工作,因为我选择了javascript,它是java语言

reset.setOnClickListener(new View.OnClickListener() 
                        @Override
                        public void onClick(View v) 
                            finish();

                            startActivity(getIntent());
                        
                    );

【讨论】:

这会重新启动活动,但不会重新启动整个应用程序。具体来说,如果您有一个 Application 子类,或者如果您有包含状态数据的静态类,这些对象将不会被重新初始化。【参考方案29】:

在MainActivity中调用restartActivity方法:

public static void restartActivity(Activity mActivity) 
    Intent mIntent = mActivity.getIntent();
    mActivity.finish();
    mActivity.startActivity(mIntent);

【讨论】:

重启活动,而不是应用程序。【参考方案30】:

您可以像这样重新开始当前的活动:

片段:

activity?.recreate()

活动:

recreate()

【讨论】:

这根本不是 OP 想要做的。

以上是关于如何以编程方式“重启”Android 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

Android:以编程方式更改整个应用布局方向

如何在 Windows 中以编程方式强制重启/重新加载 Playback 设备?

Android:如何以编程方式向 Nonin OnyxII 9560 脉搏血氧仪发送命令以选择数据格式并显示 SpO2 和心率值

如何以编程方式退出android应用程序

如何在不使用命令的情况下以编程方式关闭/重启 linux 机器(运行时)

如何在 Android 10 中以编程方式安装任何 Android 应用