关于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 属性 )
318 0
|
15天前
|
Java 数据库 Android开发
【专栏】Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
|
10天前
|
存储 安全 Android开发
安卓应用开发:构建一个高效的用户登录系统
【5月更文挑战第3天】在移动应用开发中,用户登录系统的设计与实现是至关重要的一环。对于安卓平台而言,一个高效、安全且用户体验友好的登录系统能够显著提升应用的用户留存率和市场竞争力。本文将探讨在安卓平台上实现用户登录系统的最佳实践,包括对最新身份验证技术的应用、安全性考量以及性能优化策略。
|
12天前
|
前端开发 Android开发 iOS开发
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
【4月更文挑战第30天】Flutter 框架实现跨平台移动应用,通过一致的 UI 渲染(Skia 引擎)、热重载功能和响应式框架提高开发效率和用户体验。然而,Android 和 iOS 的系统差异、渲染机制及编译过程影响性能。性能对比显示,iOS 可能因硬件优化提供更流畅体验,而 Android 更具灵活性和广泛硬件支持。开发者可采用代码、资源优化和特定平台优化策略,利用性能分析工具提升应用性能。
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
|
13天前
|
监控 Java Android开发
安卓应用开发:打造高效用户界面的五大策略
【4月更文挑战第29天】 在安卓应用开发的世界中,构建一个既美观又高效的用户界面(UI)对于吸引和保留用户至关重要。本文将深入探讨五种策略,这些策略可以帮助开发者优化安卓应用的UI性能。我们将从布局优化讲起,逐步过渡到绘制优化、内存管理、异步处理以及最终的用户交互细节调整。通过这些实践技巧,你将能够为用户提供流畅而直观的体验,确保你的应用在竞争激烈的市场中脱颖而出。
|
2天前
|
Java Android开发
Android开发--Intent-filter属性详解
Android开发--Intent-filter属性详解
|
2天前
|
物联网 Java 开发工具
安卓应用开发:打造未来移动生活
【5月更文挑战第10天】 随着科技的飞速发展,智能手机已成为我们日常生活中不可或缺的一部分。作为智能手机市场的两大巨头,安卓和iOS分别占据了一定的市场份额。在这篇文章中,我们将重点关注安卓应用开发,探讨如何利用先进的技术和创新思维,为用户打造更加便捷、智能的移动生活。文章将涵盖安卓应用开发的基本概念、关键技术、以及未来发展趋势等方面的内容。
|
4天前
|
Java API 开发工具
java与Android开发入门指南
java与Android开发入门指南
11 0