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


75

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

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

Answers:


156

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

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

3
对我有帮助。谢谢。我曾经那样使用,“尝试{ e){e.printStackTrace();}
tknv 2011年

这种方法的一个问题。新的活动的onCreate在旧的活动堆栈获得onDestroy之前被调用
AAverin 2014年

1
@AAverin:如何在onCreate之前调用onDestroy?
oligofren 2014年

7
不起作用,仅在启动活动中恢复,应用程序类未重置

2
使用as作为标志Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK,这很好用,也可以清除活动堆栈。
Lalit Fauzdar

30

标为“答案”的解决方案有效,但有一个缺点对我来说很关键。使用FLAG_ACTIVITY_CLEAR_TOP,您的目标活动将在您的旧活动堆栈收到onDestroy之前被调用onCreate。在清除onDestroy中的一些必要内容时,我不得不进行工作。

这是为我工作的解决方案:

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


1
为什么不直接调用Activityfinish()方法System.exit呢?医生说:“当您完成活动并应将其关闭时,请调用它。”
oligofren 2014年

1
我只是意识到这是由于该方法是静态的,因此无法调用任何非静态方法,例如finish。我只是使它成为restart非静态的,而是替换了System.exit调用。
oligofren 2014年

1
经过测试,我发现使用finish()会使我的应用在启动时挂起,而System.exit可以正常运行...
oligofren 2014年

3
同意以前的评论。我已使用PendingIntent.FLAG_CANCEL_CURRENT而不是Intent.FLAG_ACTIVITY_CLEAR_TOP删除警告
Alexeev Valeriy

15

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


1
是的,我尝试了一下,但是当我再次单击该图标时,它似乎调用了Resume而不是onCreate ... ...这意味着我得到的屏幕没有任何我的方法开始
Sephy 2010年

2
或以Intent.FLAG_ACTIVITY_CLEAR_TASK编程方式将标志添加到Intent。
Davideas,2015年


3

FLAG_ACTIVITY_CLEAR_TOP是否可以做您需要做的事情?

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

3

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

这几乎可行,但效果不完全。

由于我有基本的活动,因此我添加了一个终止广播,该广播关闭了我所有正在运行的活动。

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

我所有的活动都是从这一堂课开始的,所以

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

重新启动应用程序。在genymotion v10,v16,v21和Nexus 5和v22上进行了测试。

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


3

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

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

的值是mPendingIntentId什么意思?看起来是一个特别神奇的数字-只是一个任意整数吗?
aaaidan

它只是一个任意数字,您可以使用任何随机整数。这是PendingIntent类中的消息号。
Beatrice Lin

2

Marc的答案非常有效,但在我的主要活动具有launchTop of singleTop的情况下除外。一旦运行了此意图,然后导航到新的“活动”并按设备上的“主页”按钮,然后从应用程序图标再次启动我的应用程序,我最终创建了主活动的新实例,而我的前一个活动位于后台。

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

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

具有这样的归位机制:

    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和手机上都有效,并且让我可以在不添加主要活动的另一个实例的情况下正确重置应用程序。



1

这为我工作:

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

0

您应该检查这个问题:

以编程方式重启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);
}

-1

经过认真的思考和测试,我终于有了正确的方法来调用我的活动,以在应用程序带有主页按钮时重新创建:

android:clearTaskOnLaunch

在清单中

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

这样就可以了...(比将其放入onResume时要好,后者在每次启动应用程序时都会调用,即使是第一次启动,也会导致两次显示)


2
听起来不好 您只需要该clearTaskOnLaunch属性。首先,您如何启动应用程序?直接使用ADT工具从Eclipse?如果是这样,则存在一个错误,这意味着无法从Eclipse正确启动应用程序。此后已修复。
Christopher Orr 2010年

是的,直接来自日食。但是我只用clearTaskOnLaunch尝试过,我无法让它工作...
Sephy 2010年

嗨,如何添加onRestart()方法。你可以给一个片段谢谢?

4
伙计们,请不要叫onCreate()onRestart()。这些(创建和重新启动)是两个不同的事件。如果要让他们执行相同的代码,请执行:void myOnCreate() { ... } void onCreate(){myOnCreate();} void onRestart() {myOnCreate();}
18446744073709551615 2012年

1
@Fraggles因为它使您的代码无法维护。通常当函数onRestart()调用super.onRestart()时是正确的。但是,如果您从onRestart()调用onCreate()那么这个理智的假设对您的项目将是错误的。例如,当您意识到在所有活动中都需要某些功能时,通常可以正确地定义类ActivityWithSomething并更改扩展活动项目中所有活动的活动扩展为ActivityWithSomething
18446744073709551615
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.