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 ...
随机推荐
- px、pt、em、rem 的区别
px(pixel) 像素,是屏幕上显示数据的最基本的点,表示相对大小(不同分辨率上px显示不同) pt(point) 印刷行业常用的单位(磅),等于1/72英寸,表示绝对长度 em em是相对长度单位 ...
- ajax请求获取实时数据
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- Core Animation 文档翻译 (第八篇)—提高动画的性能
前言 核心动画是提高基于APP动画帧率的好方式,但是核心动画的使用不代表性能的提升的保证.尤其在OSX,当使用核心动画时,我们仍需选择最有效的方式.和所有的性能相关的问题一样,我们应该使用工具时时的评 ...
- etcd集群部署
etcd是用于共享配置和服务发现的分布式KV存储系统,随着CoreOS和Kubernetes等项目在开源社区日益火热,它们都用到了etcd组件作为一个高可用.强一致性的服务发现存储仓库.操作系统版本: ...
- typedef介绍
1.typedef是什么? typedef是C中的类似于extern/static的一个关键字,用于为一种类型引入一个新的名字.并不会分配内存. 2.typedef常见用法? 1) typedef i ...
- css居中方法与双飞翼布局
居中 类型 方法 对应属性 水平 垂直 水平&垂直 1.父元素使用外边距自动 2.子元素显示行内块级元素,写入内容,父元素设置文本居中 3.给父元素开启非绝对和固定定位作为子元素开启绝对定位的 ...
- ipset批量配置iptables
简介: ipset是iptables的扩展,允许你创建匹配整个地址sets(地址集合)的规则.而不像普通的iptables链是线性的存储和过滤,ip集合存储在带索引的数据结构中,这种集合比较大也可以进 ...
- 基于queryperf 和 perftcpdns 的DNS压力测试
最近在AWS上安装了PPTP VPN 做代理,手机, pad 也可以无缝FQ,甚是开心.最近工作不太忙,研究一下缓存加速的调优.系统已经安装的nscd文件级的缓存和dnsmasq,cpu级的dns缓存 ...
- 让互联网更快:新一代QUIC协议在腾讯的技术实践分享
本文来自腾讯资深研发工程师罗成在InfoQ的技术分享. 1.前言 如果:你的 App,在不需要任何修改的情况下就能提升 15% 以上的访问速度,特别是弱网络的时候能够提升 20% 以上的访问速度. 如 ...
- 又是一个愚蠢的错误,皆因.xml而起
论java中的.xml到底有多坑?! 感觉自己都快哭了,再一次被.xml给坑了一下,这次坑的太狠了,一下子导致自己浪费了昨天一下午,一晚上,今天一上午和半个下午呀,中间的过程真的是乏善可陈呀,各 ...