关于Android TaskAffinity的那些事儿

简介:

正常情况下,如果应用已经启动,并将应用切到后台,在通知栏中调起页面时,该应用的Task首先会被调起,然后会将我们的Activity显示在这个Task的顶端。手机百度的通知栏里面有一个快速搜索栏,无论什么情况下,点击之后都会直接弹出搜索页面,透明背景后显示的是桌面。怎么来实现这个功能呢?这就要提到我们的主角TaskAffinity了。

什么是affinity?

  affinity是指Activity的归属,Activity与Task的吸附关系,也就是该Activity属于哪个Task。一般情况下在同一个应用中,启动的Activity都在同一个Task中,它们在该Task中度过自己的生命。每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于应用的包名。我们可以通过在元素中增加taskAffinity属性来为某一个Activity指定单独的affinity。这个属性的值是一个字符串,可以指定为任意字符串,但是必须至少包含一个”.”,否则会报错。

affinity在什么场合应用呢?

1.根据affinity重新为Activity选择宿主task(与allowTaskReparenting属性配合使用)

  allowTaskReparenting用来标记Activity能否从启动的Task移动到taskAffinity指定的Task,当把Activity的allowTaskReparenting属性设置成true时,Activity就拥有了一个转移所在Task的能力。具体点来说,就是一个Activity现在是处于某个Task当中的,但是它与另外一个Task具有相同的affinity值,那么当另外这个任务切换到前台的时候,该Activity就可以转移到现在的这个任务当中。allowTaskReparenting默认是继承至application中的allowTaskReparenting=false,如果为true,则表示可以更换;false表示不可以。 
举一个形象点的例子,比如有一个天气预报程序,它有一个用于显示天气信息的Activity,allowTaskReparenting属性设置成true,这个Activity和天气预报程序的所有其它Activity具体相同的affinity值。这个时候,你自己的应用程序通过Intent去启动了这个用于显示天气信息的Activity,那么此时这个Activity应该是和你的应用程序是在同一个任务当中的。但是当把天气预报程序切换到前台的时候,这个Activity会被转移到天气预报程序的任务当中,并显示出来。如果将你自己的应用切换到前台,发现你自己应用Task里的那个Activity消失了。

2.启动一个Activity过程中Intent使用了FLAG_ACTIVITY_NEW_TASK标记,根据affinity查找或创建一个新的具有对应affinity的task。

  当调用startActivity()方法来启动一个Activity时,默认是将它放入到当前的任务当中。但是,如果在Intent中加入了FLAG_ACTIVITY_NEW_TASK flag的话,情况就会变的复杂起来。首先,系统会去检查这个Activity的affinity是否与当前Task的affinity相同。如果相同的话就会把它放入到当前Task当中,如果不同则会先去检查是否已经有一个名字与该Activity的affinity相同的Task,如果有,这个Task将被调到前台,同时这个Activity将显示在这个Task的顶端;如果没有的话,系统将会尝试为这个Activity创建一个新的Task。需要注意的是,如果一个Activity在manifest文件中声明的启动模式是”singleTask”,那么他被启动的时候,行为模式会和前面提到的指定FLAG_ACTIVITY_NEW_TASK一样。 
那么,有了上面的知识,我们应该可以实现开头提到的功能了。

功能的实现

  首先,在mainifest中配置我们的Activity,

       <activity
        android:name="com.test.TestActivity"
        android:configChanges="orientation|keyboard|keyboardHidden"
        android:exported="true"
        android:taskAffinity="com.test.TestActivity"
        android:screenOrientation="portrait"/>

  然后增加通知栏的逻辑

  NotificationManager mNotifManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
  Notification notification = new Notification();
  notification.icon = R.drawable.icon;
  notification.flags = Notification.FLAG_ONGOING_EVENT;
  notification.flags = Notification.FLAG_AUTO_CANCEL;
  notification.flags = Notification.FLAG_NO_CLEAR;
  RemoteViews mContentView = new RemoteViews(mContext.getPackageName(), 
  R.layout.notification_test);
  notification.contentView = mContentView;

  Intent intent = new Intent();
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  intent.setClass(mContext, TestActivity.class);
  PendingIntent pendingIntent =PendingIntent.getActivity(mContext, 0, intent, 
  PendingIntent.FLAG_UPDATE_CURRENT);                     
     notification.contentView.setOnClickPendingIntent(R.id.rl_notification, 
  pendingIntent);

  mNotifManager.notify(NOTIFYID, notification);

  现在我们可以实现开头提到的那种效果了。但是,我发现最近任务中会有两个我们应用的图标,看起来像是启动了两个我们的应用,非常奇怪,而实际上是因为我们的应用启动了两个Task。我们可以通过在manifest此Activity的属性中增加Android:excludeFromRecents=”true”。这属性用于设置由该Activity所启动的任务是否应该被排除在最近使用的应用程序列表之外。也就是说,当这个Activity是一个新任务的根节点时,这个属性决定了这个任务是否会显示在用户最近使用的应用程序列表中。如果设置为true,则这个任务会被排除在列表之外,为false,则表示会包含在最近使用的应用列表中。默认值是false。

场景验证

  前提:将页面背景设置为半透明。 
1、未使用affinity 
如果应用没有启动,点击通知栏,当前Activity被调起,透明背景后显示为桌面。 
如果应用已经启动,点击通知栏,应用的Task调到前台,当前Activy显示在该Task的顶端。 
2、使用affinity 
无论应用是否已经启动,点击通知栏,当前Activity都会被调起,透明背景后显示为桌面。 
两种情况下,看最近任务栏,都只显示一个应用图标。 
这样就实现了我们想要的效果。


    本文转自 一点点征服   博客园博客,原文链接http://www.cnblogs.com/ldq2016/p/6953106.html:,如需转载请自行联系原作者



相关文章
|
Android开发 开发者
【Android 应用开发】Activity 任务亲和性 taskAffinity 设置 ( taskAffinity 属性 )
【Android 应用开发】Activity 任务亲和性 taskAffinity 设置 ( taskAffinity 属性 )
359 0
|
7天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
12天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
14天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
16天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。
|
14天前
|
存储 API 开发工具
探索安卓开发:从基础到进阶
【10月更文挑战第37天】在这篇文章中,我们将一起探索安卓开发的奥秘。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和建议。我们将从安卓开发的基础开始,逐步深入到更复杂的主题,如自定义组件、性能优化等。最后,我们将通过一个代码示例来展示如何实现一个简单的安卓应用。让我们一起开始吧!
|
15天前
|
存储 XML JSON
探索安卓开发:从新手到专家的旅程
【10月更文挑战第36天】在这篇文章中,我们将一起踏上一段激动人心的旅程,从零基础开始,逐步深入安卓开发的奥秘。无论你是编程新手,还是希望扩展技能的老手,这里都有适合你的知识宝藏等待发掘。通过实际的代码示例和深入浅出的解释,我们将解锁安卓开发的关键技能,让你能够构建自己的应用程序,甚至贡献于开源社区。准备好了吗?让我们开始吧!
25 2
|
16天前
|
Android开发
布谷语音软件开发:android端语音软件搭建开发教程
语音软件搭建android端语音软件开发教程!
下一篇
无影云桌面