Android应用Home键后Launcher重复启动问题
通过系统方式(系统安装器)安装应用,点击“打开”按钮,进入应用主界面,按home键后,点击应用图标进入,应用会出现重新启动。当完全退出应用后,再通过启动图标进入应用,便不会出现重复启动问题。目前测试大部分Android机型均会出现此类问题。
重现方式
- 系统安装器安装APK(含覆盖安装),成功后点击“打开”按钮,进入应用。
- 应用正常启动为AAActivity,然后进入主页面MainActivity,此时进入二级页面A或三级页面B。
- 按home键,将程序置于后台。
- 在launcher上打开APP。
- 程序重新启动,先AAActivity后MainActivity。
定位了问题重现方式,发现只是系统安装器安装后,会出现重复启动问题。因此检查安装器打开应用与launcher打开应用的不同,为此在首次启动页面AAActivity打印action,category,flags,TaskId,Pid信息。重复上述过程。
1.当通过安装器打开APP时,log信息如下:
AAActivity:
getAction:android.intent.action.MAIN
getCategories:android.intent.category.LAUNCHER
getFlags:Intent.FLAG_ACTIVITY_NEW_TASK
TaskId:308,Pid:5445
2.按home键,launcher上打开APP,log信息如下:
AAActivity:
getAction:android.intent.action.MAIN
getCategories:android.intent.category.LAUNCHER
getFlags:Intent.FLAG_ACTIVITY_NEW_TASK,Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
TaskId:308,Pid:5445
3.多次重复按home键,重复打开APP,log信息与2中相同,因此可以判断此时新建的AAActivity是压入之前的任务栈中。
4.完全退出应用程序,即销毁原有任务栈,launcher上打开APP,log信息如下:
AAActivity:
getAction:android.intent.action.MAIN
getCategories:android.intent.category.LAUNCHER
getFlags:Intent.FLAG_ACTIVITY_NEW_TASK,Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
TaskId:309,Pid:7150
结论
通过以上log信息可以确定以下结论:
1)AAActivity用安装器打开应用flag为FLAG_ACTIVITY_NEW_TASK,launcher打开应用比系统安装器多了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED。
2)用FLAG_ACTIVITY_NEW_TASK创建的任务栈,再用FLAG_ACTIVITY_RESET_TASK_IF_NEEDED(launcher方式)打开,会在AAActivity多了FLAG_ACTIVITY_BROUGHT_TO_FRONT。
3)异常重复启动过程中,新建AAActivity的TaskId与Pid一致,可确定还是在原有任务栈中创建Activity,打开多次MainActivity(standard启动模式)会在原有任务栈中叠加。
解决方法
在启动页(AAActivity)中通过isTaskRoot(Return whether this activity is the root of a task. The root is the first activity in a task.)方法来进行判断:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isTaskRoot()) {
finish();
return;
}
}
判断逻辑为:判断启动页是否为当前任务栈的根Activity,如果不是根Activity则finish掉。语意上来讲,一个任务栈的根Activity应是启动页,这样也符合正常的应用场景;如果不是根Activity,那么说明出现了异常启动,应当将该启动页销毁掉,显示原有任务栈。
而此判断方法也是基于以上结论(3)来解决的,还有一种判断方式是基于结论(2),在AAActivity中判断是否含有FLAG_ACTIVITY_BROUGHT_TO_FRONT标志:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
finish();
return;
}
}
先来看下API中对FLAG_ACTIVITY_BROUGHT_TO_FRONT标志位的解释:
/**
* This flag is not normally set by application code, but set for you by
* the system as described in the
* {@link android.R.styleable#AndroidManifestActivity_launchMode
* launchMode} documentation for the singleTask mode.
*/
public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0x00400000;
此标志位是singleTask 启动模式下,由系统进行设定的。但在测试过程中的AAActivity为standard启动模式,也会添加该标志位?关于这一点官方也没有一个明确的关于该标志位的说明。因FLAG_ACTIVITY_BROUGHT_TO_FRONT使用的未知性,以及AAActivity启动模式特殊性,最终还是选取用isTaskRoot()来进行判断。
1.AAActivity中如果实现了finish() 和 onDestroy()方法,要保证这两个方法无空对象操作以及注销未注册的Service等类似操作。因为二次打开AAActivity在onCreate()方法中便finish()掉,可能涉及一些变量未初始化操作等。
2.finish() 和 onDestroy()方法中不能调用System.exit(0);否则二次打开AAActivity杀掉进程时也会将之前任务栈活动杀掉。
3.如果MainActivity为singleTask 启动模式(也符合一般应用场景),那么就会出现异常启动情况下新AAActivity打开原MainActivity并将MainActivity之上的其他Activity clear掉,因此展现给用户的就是再次点击launcher,会先进AAActivity,再进入保留原有活动的MainActivity。
4.launcher打开应用比系统安装器多了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,证明添加了该标志位的栈,不会存在重复启动问题,这也符合API中该标志位如果存在一个已经存在的栈则会复用原栈的说明。
Android应用Home键后Launcher重复启动问题的更多相关文章
- Android使用Home键后应用程序重启的问题
正常情况应该是在点击 home 按键后,程序在后台暂停运行,点击 后退键 才会退出应用的,但是今天遇到个问题,点击 home 键后,重新再打开应用却每次都返回应用启动页面,有些莫名其妙,一番googl ...
- [Android]从Launcher开始启动App流程源码分析
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5017056.html 从Launcher开始启动App流程源码 ...
- Android按下home键后重新打开app进入主activity的问题
问题阐述: 当我们写一款App的时候,势必会有这种情况:用户已经进行了多级的操作,现返回栈中已存在多个activity,那么这个时候我们想回到最初的activity难道要一层层的返回吗,对用户来说 无 ...
- Android实现点击通知栏后,先启动应用再打开目标Activity ,极光推送等推送的也可以参考一下(转)
我因为项目中集成了极光推送,推送的通知栏点开需要确定进入哪个界面就参考了这边文章,感谢作者的无私. 标签: 情况简述 在开发Android app的过程中,遇到这样一个需求:app中启动一个Servi ...
- Android更改桌面应用程序launcher的两种方式
http://blog.csdn.net/mdx20072419/article/details/9632779/ launcher,也就是android的桌面应用程序.下图是我正在使用的魅族手机的l ...
- 【转】Android Service被关闭后自动重启,解决被异常kill 服务
http://www.kaifajie.cn/android/10182-2.html 每次调用startService(Intent)的时候,都会调用该Service对象的onStartComman ...
- 我的Android进阶之旅------>关于使用Android Studio替换App的launcher图标之后仍然显示默认的ic_launcher图标的解决方法
前言 最近做了一个App,之前开发该App的时候一直以来都是默认的launcher图标启动的, 今天美工换了一个App的launcher 图标,因此在Android Studio中将默认的lanche ...
- 【Maven】Eclipse安装Maven插件后导致Eclipse启动出错
本文纯属复制粘贴:具体请参照原文: Eclipse安装Maven插件后,Eclipse启动问题:Maven Integration for Eclipse JDK Warning. 解决方法: 1. ...
- Android四大组件及activity的四大启动模式
Android四大组件 1. 广播接收者的两种类型: (1)系统广播接收者,就是继承BroadcastReceiver这个类,然后还要在清单文件中注册,注册之后给他一个action.当系统发生了这个a ...
随机推荐
- Jetson TX2安装tensorflow(原创)
Jetson TX2安装tensorflow 大致分为两步: 一.划分虚拟内存 原因:Jetson TX2自带8G内存这个内存空间在安装tensorflow编译过程中会出现内存溢出引发的安装进程奔溃 ...
- c# 程序结构
最近工作中需要用到c#,所以从今天开始博客不定期更新c#学习笔记 c#程序结构大体分为, 命名空间 类 Main 方法 命名空间 相当于一个仓库 通过 using 引入命名空间 比如 using ...
- CentOS6.9编译安装nginx1.4.7
1.系统安装开发包组和zlib-devel,关闭iptables [root@bogon ~]# yum groupinstall -y "Development Tools" [ ...
- 前段篇:HTML
<!DOCTYPE html> 文件开头统一的标准! HTML包含了两部分: head与body 固定的格式. 一.head部分: head部分分为两部分:meta标签与非meta标签: ...
- Cookie、session和localStorage、以及sessionStorage之间的区别
一.Cookie.session和localStorage的区别 cookie的内容主要包括:名字.值.过期时间.路径和域.路径与域一起构成cookie的作用范围.若不设置时间,则表示这个cookie ...
- 关于ES6 用箭头函数后的 this 指向问题
最近写完小程序后, 开始学习React, 因为有编译器, 就直接用ES6 新语法了, 中间自然离不开 () => { console.log('箭头函数的this是指向哪的问题')}; var ...
- javaweb下载文件模板
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax ...
- Halcon一日一练:图像分辨率与像素
1.图像像素: 像素是指由图像的小方格即所谓的像素(pixel)组成的,这些小方块都有一个明确的位置和被分配的色彩数值,而这些一小方格的颜色和位置就决定该图像所呈现出来的样子.像素是构成图像的基本单元 ...
- 启动MySql提示:The server quit without updating PID file(…)失败
1.可能是/usr/local/mysql/data/rekfan.pid文件没有写的权限解决方法 :给予权限,执行 "chown -R mysql:mysql /var/data" ...
- easyui+ajax获取同表关联的数据
easyui是我们常用的前端框架之一,easyui的使用使得前端页面更加美观.为了能够使用combobox,ajax必须同步. 该小程序是使用ssm框架,对数据库的数据进行查询,所以url对应着map ...