如何以编程方式“重新启动"一个Android应用程序? [英] How do I programmatically "restart" an Android app?

查看:88
本文介绍了如何以编程方式“重新启动"一个Android应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我知道不应真正终止/重启Android上的应用程序.在我的用例中,我想在服务器将特定信息发送到客户端的特定情况下,将应用程序恢复出厂设置.

Firstly, I know that one should not really kill/restart an application on Android. In my use case I want to factory-reset my application in a specific case where a server sends a specific information to the client.

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

The user can only be logged in on the server with ONE instance of the application (i.e. multiple devices are not allowed). If another instance gets that "logged-in"-lock then all other instances of that user have to delete their data (factory-reset), to maintain consistency.

有可能强行获得锁,因为用户可能会删除该应用并重新安装它,这将导致产生不同的实例ID,并且用户将无法再释放该锁.因此可以强行获得锁.

It is possible to forcibly get the lock, because the user might delete the app and reinstall it which would result in a different instance-id and the user would not be able to free the lock any more. Therefore it is possible to forcibly get the lock.

由于这种可能性,我们需要始终在具体实例中检查它是否具有锁.这几乎是在对服务器的每个请求上完成的.服务器可能会发送错误的锁ID".如果检测到该错误,则客户端应用程序必须删除所有内容.

Because of that force-possibility we need to always check in an concrete instance that it has the lock. That is done on (almost) each request to the server. The server might send a "wrong-lock-id". If that is detected, the client application must delete everything.

那是用例.

我有一个Activity A,它根据sharedPrefs值启动登录Activity L或应用程序的主ActivityB.启动L或B后,它会自行关闭,因此只有L或B在运行.因此,如果用户已经登录,则B现在正在运行.

I have an Activity A that starts the Login Activity L or the app's main Activity B depending on a sharedPrefs value. After starting L or B it closes itself so that only L or B is running. So in the case that the user is logged in already B is running now.

B启动C.C为IntentService D调用startService.这将导致此堆栈:

B starts C. C calls startService for the IntentService D. That results in this stack:

(A)> B> C> D

(A) > B > C > D

从D的onHandleIntent方法将事件发送到 ResultReceiver R.

From the onHandleIntent method of D an event is send to a ResultReceiver R.

R现在通过为用户提供一个对话框来处理该事件,在该对话框中,他可以选择工厂重置应用程序(删除数据库,sharedPrefs等)

R now handles that event by providing the user a dialog where he can choose to factory-reset the application (delete the database, sharedPrefs, etc.)

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

After the factory-reset I want to restart the application (to close all activities) and only start A again which then launches the login Activity L and finishes itself:

(A)> L

对话框的onClick方法如下:

The Dialog's onClick-method looks like this:

@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,但是我想返回主屏幕.

The problem is if I use the FLAG_ACTIVITY_NEW_TASK the Activities B and C are still running. If I hit the back button on the login Activity I see C, but I want to go back to the home screen.

如果我未设置FLAG_ACTIVITY_NEW_TASK,则会收到错误消息:

If I do not set the FLAG_ACTIVITY_NEW_TASK I get the error:

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启动的后台任务调用的.

I cannot use the Activities' Context, because the ServiceIntent D might also be called from an background task which is started by the AlarmManager.

那么我怎么解决这个问题,使活动堆栈变成(A)> L?

So how could I solve this to the activity stack becoming (A) > L?

推荐答案

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

You can use PendingIntent to setup launching your start activity in the future and then close your application

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应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆