Android-在安装完成界面,点击打开应用程序。在应用程序点击home键,再从桌面打开程序导致产生多个实例或者说程序被重复打开。(转)...

  原文出处:http://blog.csdn.net/etong_123/article/details/22897731

  

   问题标题都已经写明了,就是在普通的安装apk完成之后,会遇到的一种情况。基本上在程序的AndroidManifest.xml里面没有对Activity的属性做特殊处理都会出现这种情况,具体现象可以自己写个demo安装看看。

               原理:

       为了了解问题产生的原因,首先,我们先来讲一下Android的任务栈的机制:

       任务栈就是用来存放应用程序的Activity的地方,Android默认在打开应用程序的时候给每个应用单独分配一个任务栈,用来管理应用程序Activity间的跳转,返回。每个Activity都可以配置一个属性叫taskAffinity,每个Activity默认的taskAffinity是以应用程序的包名命名的,为什么要提到这个呢,这个点后面会讲到,接下去看。

       一般来说,每个应用都单独跑在自己的任务栈上,但是我们也可以让两个应用程序跑在同一个任务栈里面。我们可以从一个应用程序里面启动跳转到另一个应用程序里面。跳转的代码一般有两种写法:

      代码1:从程序1跳转到程序2之后,两个应用程序是跑在同一个任务栈里面的。

1      Intent intent=new Intent("android.intent.action.MAIN");
2         intent.setComponent(new ComponentName("com.et.demo","com.et.demo.TestActivity"));
3         startActivity(intent);

   代码2:从程序1跳转到程序2之后,两个应用程序是跑在各自的任务栈里面的。

1      Intent intent=new Intent("android.intent.action.MAIN");
2         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3         intent.setComponent(new ComponentName("com.et.demo","com.et.demo.TestActivity"));
4         startActivity(intent);

   关键点在于Intent.FLAG_ACTIVITY_NEW_TASK 这个 Flags上,设置了新建Task来存放要打开的应用程序。这样两个应用就跑在各自的任务栈里。

      问题就出在这里了,我看了下源码。Launcher的启动方式就是调用的时候加了Intent.FLAG_ACTIVITY_NEW_TASK,而在安装完成的“打开”按钮是没有加这句话,直接调用startActivity(详细情况你们可以去看源码)。

      Intent.FLAG_ACTIVITY_NEW_TASK 这个属性设置之后,系统会先在内存中查找该应用程序的Task是否已存在,如果内存中已有,直接调用该任务栈显示栈顶的Activity,否则新建任务栈。(好吧,这部分其实是我猜的   — _ — ,因为startActivity的源码还没有看完。 )

      顺带提一下,安装界面其实也是个Activity(虽然4.0的系统很多都是一个Dialog的样式),我们调用安装的代码也是要加上NEW_TASK的,也就是说安装完成后由于安装的打开按钮没有加NEW_TASK,所以被打开应用是跑在Install的Task上面的,导致我们home键返回桌面之后,点击应用程序会重新开启一个新的实例。

     但是这里还是有个疑点,根据实验结果得出的结论,当我们的应用程序跑在Install的Task上面的时候,点击桌面图标,系统并不会开启新的Task去启动这个应用(表明的确是有判断该应用的Task是否存在决定是否要创建),而是直接在Install的Task上打开应用程序的首页(FirstActivity),搞不懂Android为什么要这么做。

 

    不过,解决方案已经出炉了,所以秉着先解决问题的原则,我们先上解决方案。(呵呵,这是什么原则!)     

    

       解决方法:

      接下来呢,各位童鞋,我们来学习一个词,叫“曲线救国”。好吧,方法的确是有点曲线,但是效果不错,上菜。

       思路:

     1、先在你的应用程序里新建一个Activity,将它设置为首页(你懂de),让它跑在独立的Task上面。

     2、将这个Activity作为跳转页面,新建Task(代码2)跳转到你的程序“真正”的首页上(你又懂de),销毁掉这个Activity,连带它的Task。

     3、这样你的程序就跑在了自己独立的Task上面了,就不会出现打开多个实例的问题了。

     实现:

      新建FirstActivity,在manifest配置属性(最重要的部分

  

 1 <activity
 2             android:name="com.example.opentest.FirstActivity"
 3             android:configChanges="keyboardHidden|orientation|fontScale"
 4             android:label="@string/title_activity_first"
 5             android:excludeFromRecents="true"
 6             android:taskAffinity="com.example.opentest.first"
 7             android:windowSoftInputMode="adjustPan" >
 8             <intent-filter>
 9                 <action android:name="android.intent.action.MAIN" />
10 
11                 <category android:name="android.intent.category.LAUNCHER" />
12             </intent-filter>
13             <intent-filter>
14                 <action android:name="android.intent.action.CREATE_SHORTCUT" />
15             </intent-filter>
16         </activity>

     我的程序包名是com.example.opentest,这里我们将FirstActivity的属性设置一下

       android:taskAffinity="com.example.opentest.first"

       这样是为了让它自己跑在独立的Task上。(你自己好好反省一下吧,哼)。

       而另一个重要的属性:

       android:excludeFromRecents="true"

       作用是隐藏Task(即让你的Task不出现在长按home出现的界面里)。

     然后在FirstActivity代码中:

1         Intent intent=new Intent(this, MainActivity.class);
2         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3         startActivity(intent);
4                finish();

   android:windowIsTranslucent:Activity背景透明。

     android:windowAnimationStyle你可以指定你的Activity的加载动画。

     然后在manifest里将FirstActivity的theme指定一下就可以了。这样出来的效果就好很多了。虽然解决方法有点取巧,但是效果还不错。

     总结一下,虽然问题不是很常见,解决方法也不是特别难,但是对于一个软件来说,第一次打开的时候出现程序问题肯定会给用户一个很不好的印象。目前很多app(像百度视频,hao123浏览器什么的)都还有存在这个问题,上网找了一下,发现都没有解决方案,既然解决了就跟大家分享一下。

     最后,完整的demo已放出,各位看官觉得好的请点赞。

   下载地址:http://download.csdn.net/detail/etong_123/7148307

转载于:https://www.cnblogs.com/Syun0929/p/3647185.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值