需求描述

在应用Application1中存在A、B两个activity,当在应用启动了A、B activity,点击Recent键,如何让A、B两个activity都显示在Recent界面(最近任务)?


需求分析

根据Android SDK介绍,Recent中是管理最近的任务(Task);熟悉Activity的可以知道Activity是隶属于某个Task的,不熟悉Activity的可以阅读下面的帖子:

http://blog.csdn.net/ff20081528/article/details/17219951#comments

那么了解了Activity的一些知识后,我们就可以推断出要让A、B在Recent中显示出来,必须将A、B处于不同的Task中;那么需要设置A、B的launchMode为singleInstance;

跟”singleTask”一样.除了系统不能再启动其它activity到拥有这个activity实例的任务中.activity永远是任务的唯一;任何由这个activity启动的其它activity都在另一个任务中打开.也就可以说singleInstance必然会开辟出一个新的Task。


Demo示例

MainActivity.java:

  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  2. Button btn1;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. btn1 = (Button) findViewById(R.id.button);
  8. btn1.setOnClickListener(this);
  9. }
  10. @Override
  11. public void onClick(View view) {
  12. switch (view.getId()){
  13. case R.id.button:
  14. Intent intent1 = new Intent(this,ActivityA.class);
  15. intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  16. startActivity(intent1);
  17. break;
  18. }
  19. }
  20. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

ActivityA,java

  1. public class ActivityA extends AppCompatActivity {
  2. Button btn2;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_activity);
  7. Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  8. setSupportActionBar(toolbar);
  9. FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
  10. fab.setOnClickListener(new View.OnClickListener() {
  11. @Override
  12. public void onClick(View view) {
  13. Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
  14. .setAction("Action", null).show();
  15. }
  16. });
  17. btn2 = (Button) findViewById(R.id.button2);
  18. btn2.setOnClickListener(new View.OnClickListener() {
  19. @Override
  20. public void onClick(View view) {
  21. Intent intent2;
  22. intent2 = new Intent(ActivityA.this,ActivityB.class);
  23. startActivity(intent2);
  24. }
  25. });
  26. }
  27. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Manifest.xml

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2. package="lanchmode.sunrise.com.lanchmode">
  3. <application
  4. android:allowBackup="true"
  5. android:icon="@mipmap/ic_launcher"
  6. android:label="@string/app_name"
  7. android:roundIcon="@mipmap/ic_launcher_round"
  8. android:supportsRtl="true"
  9. android:theme="@style/AppTheme">
  10. <activity android:name=".MainActivity">
  11. <intent-filter>
  12. <action android:name="android.intent.action.MAIN" />
  13. <category android:name="android.intent.category.LAUNCHER" />
  14. </intent-filter>
  15. </activity>
  16. <activity
  17. android:name=".ActivityA"
  18. android:label="@string/title_activity_activity"
  19. android:launchMode="singleInstance"
  20. android:theme="@style/AppTheme.NoActionBar" />
  21. <activity
  22. android:name=".ActivityB"
  23. android:label="@string/title_activity_b"
  24. android:launchMode="singleInstance"
  25. android:theme="@style/AppTheme.NoActionBar" />
  26. </application>
  27. </manifest>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

运行程序,然后使用adb shell dumpsys activity activities命令查看activity的栈的信息:

  1. Running activities (most recent first):
  2. TaskRecord{b1c230d #265 A=lanchmode.sunrise.com.lanchmode U=0 StackId=1 sz=1}
  3. Run #3: ActivityRecord{638abae u0 lanchmode.sunrise.com.lanchmode/.ActivityB t265}
  4. TaskRecord{7b648d3 #264 A=lanchmode.sunrise.com.lanchmode U=0 StackId=1 sz=1}
  5. Run #2: ActivityRecord{65e4f8b u0 lanchmode.sunrise.com.lanchmode/.ActivityA t264}
  6. TaskRecord{8ff7c10 #263 A=lanchmode.sunrise.com.lanchmode U=0 StackId=1 sz=1}
  7. Run #1: ActivityRecord{5a771a1 u0 lanchmode.sunrise.com.lanchmode/.MainActivity t263}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

可以看出A、B及主activity都处于不同的Task中,那么我们点击Recent看下,是否已经实现了我们需求了呢: 

结果很是失望,只有最后启动的B在最近任务中。


需求出现问题解决

不同的Activity已经处于不同的Task了,为什么还是在最近任务中没有分别显示呢?是因为在同一个应用中(但是Recent的描述就是管理最近任务,任务就是Task啊)?通过查看activity的属性,发现了taskAffinity这个属性;

  • taskAffinity表示当前activity具有亲和力的一个任务(翻译不是很准确,原句为The task that the activity has an affinity for.),大致可以这样理解,这个 taskAffinity表示一个任务,这个任务就是当前activity所在的任务。
  • 在概念上,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务。

  • 一个任务的affinity决定于这个任务的根activity(root activity)的taskAffinity。

  • 这个属性决定两件事:当activity被re-parent时,它可以被re-paren哪个任务中;当activity以FLAG_ACTIVITY_NEW_TASK标志启动时,它会被启动到哪个任务中。(这个比较 难以理解,请结合中的属性allowTaskReparenting和Intent中的标志 FLAG_ACTIVITY_NEW_TASK加以理解)

  • 默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名。我们可以通过设置不同的taskAffinity属性给应用中的activity分组,也可以把不同的 应用中的activity的taskAffinity设置成相同的值。

  • 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task。

那么就是就使用taskAffinity设置A、B的亲和力:

  1. <activity
  2. android:name=".ActivityA"
  3. android:label="@string/title_activity_activity"
  4. android:launchMode="singleInstance"
  5. android:taskAffinity="com.sunrise.A"
  6. android:theme="@style/AppTheme.NoActionBar" />
  7. <activity
  8. android:name=".ActivityB"
  9. android:label="@string/title_activity_b"
  10. android:taskAffinity="com.sunrise.B"
  11. android:launchMode="singleInstance"
  12. android:theme="@style/AppTheme.NoActionBar" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

然后再运行程序,首先查看栈情况:

Running activities (most recent first): 
TaskRecord{b1c230d #265 A=lanchmode.sunrise.com.lanchmode U=0 StackId=1 sz=1} 
Run #3: ActivityRecord{638abae u0 lanchmode.sunrise.com.lanchmode/.ActivityB t265} 
TaskRecord{7b648d3 #264 A=lanchmode.sunrise.com.lanchmode U=0 StackId=1 sz=1} 
Run #2: ActivityRecord{65e4f8b u0 lanchmode.sunrise.com.lanchmode/.ActivityA t264} 
TaskRecord{8ff7c10 #263 A=lanchmode.sunrise.com.lanchmode U=0 StackId=1 sz=1} 
Run #1: ActivityRecord{5a771a1 u0 lanchmode.sunrise.com.lanchmode/.MainActivity t263}

栈的情况没有变化,然后再点击Recent,运行如下图 

结果是OK了!!!


总结

如果需要将同一个APP的不同Activity在Recent中显示,需满足如下两点:

    1. LaunchMode设置为singleInstance。
    2. 设置android:taskAffinity参数。

如何将同一个APP中的不同activity在Recent(最近任务)中显示?的更多相关文章

  1. Android中在不同activity中进行自定义广播的解析

    相信有不少人和我一样曾经尝试过在同一个项目中的两个activity进行广播,发现怎么都实现不了.我也是困惑了好久才发现,这么搞本来就是不行的.首先在同一个项目下不同的activity之间广播没有意义, ...

  2. Android中突发情况Activity数据的保存和恢复

    Android中突发情况Activity数据的保存和恢复 写在前面:在我们的APP使用的过程中,总有可能出现各种手滑.被压在后台.甚至突然被杀死的情况.所以对APP中一些临时数据或关键持久型数据,就需 ...

  3. ActionBar官方教程(6)把图标变成一个返回到上级的按钮,同一个app间,不同app间,不同fragment间

    Navigating Up with the App Icon Enabling the app icon as an Up button allows the user to navigate yo ...

  4. android开发中关于继承activity类中方法的调用

    android开发中关于继承activity类中的函数,不能在其他类中调用其方法. MainActivity.java package com.example.testmain; import and ...

  5. 在Activity,Service,Window中监听Home键和返回键的一些思考,如何把事件传递出来的做法!

    在Activity,Service,Window中监听Home键和返回键的一些思考,如何把事件传递出来的做法! 其实像按键的监听,我相信很多人都很熟练了,我肯定也不会说这些基础的东西,所以,前期,还是 ...

  6. Appium+Python自动化 3 -获取 app 包名和 activity

    方法一: ①手机通过USB连接电脑 ②打开手机上被测app ③在电脑上 dos命令窗口,输入命令 adb shell dumpsys window w | findstr \/ | findstr n ...

  7. 如何判断是否为同一个App,Ionic3如何修改包名

    如何判断是否同一个App 使用Ionic3创建了两个项目demo1.demo2,然后使用同一个JDK,生成了两个不同的keystore证书. 结果在手机端安装的时候,先安装demo1,没有任何替换的提 ...

  8. Django 多数据库联用(同一个APP的models里不同class用不同数据库)

    很多网站有多数据库联用的文章,如自强学堂http://code.ziqiangxuetang.com/django/django-multi-database.html 大都只讲解如何让不同的app对 ...

  9. Android 程序中得到root activity的引用

    今天写anroid时,想获得一个root activity的引用. ios中这个很简单, [UIApplication sharedApplication].keyWindow 得到window对象, ...

随机推荐

  1. 11th 如果重新来过

    如果重新来过,我想我不会再因任何阻碍而选择中途放弃了.为了追求完美,结果做不到自己想要的程度,就备感挫败感,于是乎就求全责备,无法继续进行下去,即便你一直原地踏步,其实也就相当于是放弃了,跟不做没有什 ...

  2. 操作系统学习(一)、80x86保护模式内存管理

    整理的不好,凑合着看吧 目录 1.内存及寻址 2.地址变换 3.分段机制 4.分页机制 5.保护 6.去到底部 一.内存及寻址 返回目录 二.地址变换 80X86 从 逻辑地址 到 物理地址 的转换: ...

  3. 一本通1632【 例 2】[NOIP2012]同余方程

    1632:[ 例 2][NOIP2012]同余方程 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 求关于 x 的同余方程 ax≡1(mod b) 的最小正整 ...

  4. 51Nod 1287 加农炮 (线段树)

    1287 加农炮  题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 一个长度为M的正整数数组A,表示从左向右的地形高度 ...

  5. 【刷题】洛谷 P4320 道路相遇

    题目描述 在 H 国的小 w 决定到从城市 \(u\) 到城市 \(v\) 旅行,但是此时小 c 由于各种原因不在城市 \(u\),但是小 c 决定到在中途与小 w 相遇 由于 H 国道路的原因,小 ...

  6. 解题:SCOI 2007 蜥蜴

    题面 拆点跑最大流 所有能跑出去的点连向汇点,容量为inf 原点连向所有初始有蜥蜴的点,容量为1 每根柱子拆成两个点“入口”和“出口”,入口向出口连容量为高度的边,出口向别的有高度的柱子的入口连容量为 ...

  7. ByteBuffer的allocate与allocateDirect2013-01-11

    在Java中当我们要对数据进行更底层的操作时,通常是操作数据的字节(byte)形式,这时常常会用到ByteBuffer这样一个类.ByteBuffer提供了两种静态实例方式:   public sta ...

  8. Java: ByteBuffer在多线程中使用需要注意

    昨天我改写一个文件缓存方面程序时,用ByteBuffer替换以前用的byte[],在测试的时候抛出异常. 以前的相关代码: class A { byte[] data; ....... public  ...

  9. MySQL的replace方法

    mysql中replace函数直接替换mysql数据库中某字段中的特定字符串,不再需要自己写函数去替换,用起来非常的方便,mysql 替换函数replace()Update `table_name` ...

  10. Google Email 帐户泄露

    最初爆出来的网站是:https://forum.btcsec.com/index.php?/topic/9426-gmail-meniai-parol/,是一个俄罗斯论坛,然后..就流传开来了... ...