android 重复启动,Android应用Launcher重复启动问题

Bug表现

操作一:

F_step1、使用Installer安装App,安装后选择打开app,应用进入闪屏页Activity,然后跳转到主页MianActivity;

F_step2、在主页Activity时按下了Home键,回到桌面;

F_step3、再点击app的icon图标,App并没有直接进入主页,而是先进入了闪屏页;

操作二:

S_step1、点击应用图标,应用进入闪屏页Activity,然后跳转到主页MainActivity;

S_step2、在主页Activity时按下了Home键,回到桌面;

S_step3、再点击app的icon图标,App并直接进入主页;

很明显,操作一出现了Bug。

原因查找

操作一为何会出现这种情况?现在对这个过程进行跟踪定位:

执行F_step1

进入Welcome页面,此时WelcomeActivity生命周期正常,看看Task中的情况:

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

在栈顶的Activity是welcome;

接下来,进入到主要页面MainActivity

整个生命周期走得毫无毛病,该怎么走怎么走,Task栈顶Activity是MainActivity;

执行F_step2:

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

执行之后程序退到后台,Task栈顶和之前的一样是MainActivity;

执行F_step3:

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

App再次启动了WelcomeActivity,并没有恢复退出时Task栈顶的Activit.

接下来看看操作二的过程:

......

结果,按home键推出后,再点击图标进入App,应用直接恢复了退出时栈顶的Activity,并没有重新启动WelcomeActivity;

为何会这样?

原因探究

接下来,在WelcomeActivity中打印getIntent()和Task的信息;

从Installer打开App:

(1)打开应用:

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

(2)按home键退出,再点击图标打开App

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

从lancher打开App:

(1)打开应用:

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

62ee47a659f1?tdsourcetag=s_pcqq_aiomsg

(2)按home键退出,再点击图标打开App:

因为WelcomeActivity并没有重新启动,所以没有打印Log信息。

两者的区别:

(1)从launcher启动,Flags比从Installer启动多了一个FLAG_ ACTIVITY_ RESET_ TASK_ IF_ NEEDED,添加此Flag的Task不会存在重复启动问题,保证Task的唯一性;

(2)从Installer安装后打开应用,再按Home键退出后再进入,会多出一个FLAG_ ACTIVITY_ BROUGHT_ TO_ FRONT;

由此可以看出,会发生重复启动是installer初次启动时并没有FLAG_ ACTIVITY_ RESET_ TASK_ IF _NEEDED;

值得注意的是,执行操作一,新建的WelcomeActivity的TaskId和Pid始终没有发生改变,也就是说该Activity还是在原有的进程和任务栈中打开;

解决方案:

问题找到了,那就对症下药。将以下代码到onCreate()方法中:

if (!this.isTaskRoot() && getIntent() != null) {

String action = getIntent().getAction();

if (getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {

finish();

return;

}

} else {

setContentView(R.layout.activity_welcome);

goMainActivity();

}

这段代码是使用isTaskRoot()进行判断,判断当前Activity是否为根Activity,即应用启动的第一个Activity。如果不是,说明是重新实例化出来的,则finish()掉当前Activity,显示原有的Task;

使用以上方法有个值得注意的地方:

若Activity实现了finish() 和 onDestroy()方法,在方法中要保证无空对象操作等等,以免造成异常崩溃;

到此该问题已经得到解决,然而...为何操作一会没有FLAG_ ACTIVITY_ RESET_ TASK_ IF_ NEEDED呢?

原因继续探究

mLaunchIntent = getPackageManager().getLaunchIntentForPackage(

mAppInfo.packageName);

@Override

public Intent getLaunchIntentForPackage(String packageName) {

// First see if the package has an INFO activity; the existence of

// such an activity is implied to be the desired front-door for the

// overall package (such as if it has multiple launcher entries).

Intent intentToResolve = new Intent(Intent.ACTION_MAIN);

intentToResolve.addCategory(Intent.CATEGORY_INFO);

intentToResolve.setPackage(packageName);

List ris = queryIntentActivities(intentToResolve, 0);

// Otherwise, try to find a main launcher activity.

if (ris == null || ris.size() <= 0) {

// reuse the intent instance

intentToResolve.removeCategory(Intent.CATEGORY_INFO);

intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);

intentToResolve.setPackage(packageName);

ris = queryIntentActivities(intentToResolve, 0);

}

if (ris == null || ris.size() <= 0) {

return null;

}

Intent intent = new Intent(intentToResolve);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setClassName(ris.get(0).activityInfo.packageName,

ris.get(0).activityInfo.name);

return intent;

}

从代码中可以看到,installer启动只设置了Intent.FLAG_ ACTIVITY NEW TASK;

public static Intent makeLaunchIntent(LauncherActivityInfo info) {

return new Intent(Intent.ACTION_MAIN)

.addCategory(Intent.CATEGORY_LAUNCHER)

.setComponent(info.getComponentName())

.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

}

launcher中是有设置FLAG_ ACTIVITY_ RESET_ TASK_ IF_ NEEDED和FLAG_ ACTIVITY_ NEW_ TASK;

所以,insataller安装没有设置FLAG_ ACTIVITY_ RESET_ TASK_ IF_ NEEDED。

至于为何在installer中没有设置有FLAG_ ACTIVITY_ RESET_ TASK_ IF_ NEEDED,这确实还需要研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值