我如何以编程方式“重新启动"?一个安卓应用? [英] How do I programmatically "restart" an Android app?
问题描述
首先,我知道人们不应该真的杀死/重新启动 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 piece of 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 anymore. Therefore it is possible to forcibly get the lock.
由于这种强制可能性,我们需要始终检查一个具体实例是否具有锁.这是在(几乎)每个对服务器的请求上完成的.服务器可能会发送错误的锁定 ID".如果检测到,客户端应用程序必须删除所有内容.
Because of that force-possibility, we need to always check in a 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 或应用程序的主 Activity
B.启动 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
调用 startService
D.结果是这个堆栈:
B starts C. C calls startService
for the IntentService
D. That results in this stack:
(A) >乙>C>
(A) > B > C > D
从 D 的 onHandleIntent 方法,一个事件被发送到一个 ResultReceiver R.
From the onHandleIntent method of D, an event is sent 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) >
对话框的 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 a 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);
这篇关于我如何以编程方式“重新启动"?一个安卓应用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!