zoukankan      html  css  js  c++  java
  • 如何将同一个APP中的不同activity在Recent(最近任务)中显示?

    需求描述

    在应用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:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        Button btn1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btn1 = (Button) findViewById(R.id.button);
            btn1.setOnClickListener(this);
    
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.button:
                    Intent intent1 = new Intent(this,ActivityA.class);
                    intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent1);
                    break;
            }
        }
    }
    • 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

    public class ActivityA extends AppCompatActivity {
    
        Button btn2;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_activity);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
    
            btn2 = (Button) findViewById(R.id.button2);
            btn2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent2;
                    intent2 = new Intent(ActivityA.this,ActivityB.class);
                    startActivity(intent2);
                }
            });
        }
    
    }
    • 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

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="lanchmode.sunrise.com.lanchmode">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity
                android:name=".ActivityA"
                android:label="@string/title_activity_activity"
                android:launchMode="singleInstance"
                android:theme="@style/AppTheme.NoActionBar" />
            <activity
                android:name=".ActivityB"
                android:label="@string/title_activity_b"
                android:launchMode="singleInstance"
                android:theme="@style/AppTheme.NoActionBar" />
        </application>
    
    </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的栈的信息:

    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}
    
    • 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的亲和力:

            <activity
                android:name=".ActivityA"
                android:label="@string/title_activity_activity"
                android:launchMode="singleInstance"
                android:taskAffinity="com.sunrise.A"
                android:theme="@style/AppTheme.NoActionBar" />
            <activity
                android:name=".ActivityB"
                android:label="@string/title_activity_b"
                android:taskAffinity="com.sunrise.B"
                android:launchMode="singleInstance"
                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参数。
  • 相关阅读:
    java——异常(一)
    java —— 全面解析 Annotation
    多线程(一)——三种实现方式
    java ——static 关键词总结
    java —— equals 与 ==
    java——数组与内存控制
    java—— finall 关键词
    File类实现文件夹和文件复制
    java —— 内部类
    类成员——代码块
  • 原文地址:https://www.cnblogs.com/dongweiq/p/8385614.html
Copyright © 2011-2022 走看看