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

时间:2010-03-18 15:10:41

标签: android

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

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

12 个答案:

答案 0 :(得分:142)

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

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

答案 1 :(得分:28)

标记为“回答”的解决方案有效,但有一个对我来说至关重要的缺点。 使用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,稍后会调用它,给旧活动堆栈一些时间来清理。

答案 2 :(得分:14)

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

答案 3 :(得分:9)

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

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

答案 4 :(得分:3)

FLAG_ACTIVITY_CLEAR_TOP能做你需要做的吗?

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

答案 5 :(得分: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和带有v22的Nexus 5上进行了测试。

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

答案 6 :(得分:2)

Marc的答案很有效,除了我的主要活动有一个launchTode的launchTode。一旦我运行这个意图然后导航到新的活动并按下设备上的主页按钮,然后从应用程序图标再次启动我的应用程序,我最终创建一个主要活动的新实例,我以前的活动在后台堆栈

根据this question,因为意图不匹配。看看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和我的手机,让我正确地重置应用程序,而无需添加主要活动的另一个实例。

答案 7 :(得分:2)

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

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

答案 8 :(得分:2)

您可以使用Jake Wharton的lib ProcessPhoenix重新启动申请流程。

答案 9 :(得分: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);

答案 10 :(得分:0)

您应该查看此问题:

Restarting Android app programmatically

方法是:

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

答案 11 :(得分:-1)

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

android:clearTaskOnLaunch
清单中的

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

这就是诀窍......(比每当你启动应用程序时调用onResume更好,甚至是第一次,导致双显示)