在程序中可以通过如下的方式得到: Intent mainIntent = new Intent("com.teleca.robin.Hello", null); mainIntent.addCategory("android.intent.category.DEFAULT"); List apps; apps = getPackageManager().queryIntentActivities(mainIntent, 0); if(apps==null) System.out.println("no acitivity is find"); for(int i=0;i { ActivityInfo a=apps.get(i).activityInfo; System.out.println(a.name+" taskAffinity:"+a.taskAffinity); } 定义在不同应用程序中的Activity可以共享同一个affinity,或者定义在同一个应用程序中的Activity设置不同的affinity。 Affinity在两种环境下工作:Intent对象包含FLAG_ACTIVITY_NEW_TASK标志,和Activity的allowTaskReparenting特性设置为“true”。 核心的Intent Flag FLAG_ACTIVITY_NEW_TASK: 一个Activity一般通过调用startActivity()启动并加入到Task中。它同调用者一样,进入同一个Task。 然而,如果传递给startActivity()的Intent对象中包含FLAG_ACTIVITY_NEW_TASK时,系统会搜索一个新的Task来容纳新的Activity。 通常,如标志的名字所示,是一个新的Task。然而,并不是必须是。如果已经存在一个Task与新Activity的affinity相同,这个Activity就会加入到那个Task中。如果不是,启动一个新的Task。 如果启动它的acitve和新Activity的affinity相同,那么新Activity的会进入启动它的acitve所在的Task. 核心的特性: allowTaskReparenting: 如果一个Activity的allowTaskReparenting特性设置为“true”,它就能从启动的Task中移到有着相同affinity的Task(这个Task进入到前台的时候)。 例如,在一个旅游的程序中定义了一个可以报告选择城市的天气情况的Activity。它和同一个应用程序的其它Activity一样,有着相同的Affinity(默认的Affinity),并且它允许重新宿主。 你的Activity中的一个启动了天气预报Activity,因此,它初始化到和你Activity相同的Task中。 如果旅游应用程序当前没被启动,那么下次它被启动时,天气预报那个Activity将会被显示(即在旅游应用程序的Task中被显示)。 如果从用户的角度出发,一个.apk文件包含多个“应用”的话,你可能希望为关联的Activity设置不同的affinity。 Launch Mode 这里4种不同的启动模式可以设置到元素的launchMode特性上: standard(默认模式) singleTop singleTask singleInstance 注意1:对于singleTask,如果新的Activity和旧的Activity的affinity一样时,这时它相当于FLAG_ACTIVITY_NEW_TASK。 注意2:对于singleTask和singleInstance的affinity最好不要和别的task的affinity相冲突。 这些模式有以下四点区别: 1, 哪个Task将容纳响应Intent的Activity。 对于“standard”和“singleTop”来说,除非Intent对象包含FLAG_ACTIVITY_NEW_TASK,那么新的Activity在是产生Intent的那个Task中(并调用startActivity())。 对比而言,“singleTask”和“singleInstance”指示Activity总是一个Task的根。 系统会重新创建一个Task,并把新的Activity加入其中,它们不会加入到另一个Task中。 2, 是否有多个Activity的实例。“standard”和“singleTop”可以实例化多次。它们可以属于多个Task,一个特定的Task可以有相同Activity的多个实例。 对比而言,“singleTask”和“singleInstance”只能有一个实例。不可能在多个task中同时存在有该Activity的多个实例。 也不可能在一个task中存在有该Activity的多个实例。因为这些Activity只能位于Task的底部, 3,是否可以在同一个Task中拥有其它的Activity。“singleInstance”Activity保持单身,在它的Task中它是仅有的Activity。 如果它启动另一个Activity,那个Activity将会放入到不同的Task中,而不管它的启动模式——好像FLAG_ACTIVITY_NEW_TASK在Intent中一样。 对于其它方面,,“singleInstance”等同于“singleTask”。其它三个模式允许多个Activity加入到这个Task中。 “singleTask”Activity总是位于Task的底部,但它可以启动其它的Activity并放入到它的Task中。 “standard”和“singleTop”的Activity可以出现在stack的任何地方。 4, 是否一个新的实例启动来处理新的Intent。对于默认的“standard”来说,都是创建一个新的实例来响应新的Intent。每个实例处理一个Intent。 对于“singleTop”来说,如果它位于目标Task的顶端,那么,已经存在的实例就可以重复使用来处理这个新的Intent。 如果它不在顶端,那么它就不能重复使用。替代的,新的实例将创建来响应新的Intent,并进入到stack中。 例
如,假设一个Task的Activity stack中包含根Activity A和其它Activity B,C,D,并且D位于顶端,因
此,stack是A-B-C-D。有一个Intent来了,它要启动D类型的Activity。如果D有默认的“standard”启动模式,那么一个新
的实例将被启动并且stack变成A-B-C-D-D。 然而,如果D的启动模式“singleTop”,已经存在的实例将去处理新来的Intent(因为它正好处在stack的顶端),并且stack依旧是A-B-C-D。 换句话说,如果来临的Intent是冲着B类型的,那么,B类型的实例将被创建启动而不管B的模式是“standard”或“singleTop”(因为B不处在stack的顶端), 因此,stack将会是A-B-C-D-B。 之前提到的,设备上不会出现超过一个实例的“singleTask”或“singleInstance”Activity,因此,那个实例都将去处理所有新来的Intent。 “singleInstance”Activity总是位于stack的顶端(因为它是task中唯一的Activity),因此,它总是处于能处理Intent的位置。然而,“singleTask”Activity可能有或没有其它Activity处于它的上方。 如果有,它就不处于能处理Intent的位置,那么,这个Intent将被丢弃。(即使Intent被丢弃了,它的到来会引发那个Task进入到前台,在那里,它会继续保留。) 当一个存在的Activity请求去处理一个新的Intent时,Intent对象将传到该Activity的onNewIntent()的方法中。(原来启动Activity的Intent对象可以通过调用getIntent()得到。) 注意:当一个新的实例创建来处理新的Intent时,用户可以按下BACK键返回到之前的状态(前一个Activity)。 但一个存在的实例来处理新的Intent时,用户不能按下BACK键返回到新Intent到来之前当前Activity的状态,它也是返回前一个Activity。 stack的清除 如果用户离开Task很长一段时间,系统会清除Task中的所有Activity,除根Activity外。当用户再次返回到这个Task时,和用户离开时不一样,仅仅只是初始化Activity呈现。 这样做的意图是,经过一些时间后,用户可能已经忘记之前正在做的事情,并且打算回到Task开始些新的时期。 注意1:弹出任务管理器不算离开Task 这是默认情况。下面一些Activity特性可以用于控制这一行为并且修改它: alwaysRetainTaskState: 如果Task的根Activity的这个特性设置为“true”时,上面描述的默认行为不会发生。Task保留所有的Activity,即便是经过很长一段时间。 clearTaskOnLaunch: 如
果Task的根Activity的这个特性设置为“true”时,当用户离开Task并返回时,stack会清除直到根Activity。换句话说,它是
alwaysRetainTaskState的另一个极端。用户总是回到Task的初始化状态,即便是一个短暂的离开。 finishOnTaskLaunch: 这个特性和clearTaskOnLaunch相似,但它针对单个Activity,不是整个Task。它能使除了根Activity之外的任何Activity消失。 当它设置为“true”时,这个Activity仅在当前会话期间保持为Task的部分。如果用户离开并再次返回到这个Task,它就不再显示了。 注意:对于clearTaskOnLaunch和finishOnTaskLaunch所谓的清除总是在该task被再次启动时执行的。 这里还有其它的方式可以强制Activity从stack中移除。如果Intent对象中包含FLAG_ACTIVITY_CLEAR_TOP标志,并且目标Task中已经有一个这个类型Activity的实例, 而且这个实例应该处理这个Intent,那么,位于其上的Activity都将移除,这样,这个Activity就能在stack的顶端并响应这个Intent。 如果这个Activity的启动模式设定为“standard”,它也会从stack中清除,然后新的实例启动来响应这个Intent。 这是因为当启动模式设定为“standard“时,总是会创建一个新的实例来响应新的Intent。 FLAG_ACTIVITY_CLEAR_TOP经常与FLAG_ACTIVITY_NEW_TASK结合起来使用。当一起使用时,这些标志可以定位其它Task中已经存在的Activity,并且把它置于可以响应Intent的位置。 启动Task 如果一个Activity的Intent Filter的action为“android.intent.action.MAIN”、category为“android.intent.category.LAUNCHER”时, 它就可以作为一个Task的入口点。有这种类型的Filter会在导致这个Activity在应用程序启动栏显示一个图标和标签,给用户提供一个方式可以启动这个Task和在任何时候可以再次回到这个Task。 第二个能力很重要:用户一定可以离开一个Task,然后可以再次回到它。 基于这个原因,两个启动模式,“singleTask”和“singleInstance”应该只在有MAIN和LAUNCHER的Activity上使用。 例如,假设这个Filter没有的话:一个Intent启动了一个“singleTask”Activity,初始化一个新的Task,然后用户花费了一些时间在它上面。然后,用户按下HOME键。现在,这个Task处于后台并且被HOME画面遮盖。 由于它不能在应用程序启动栏显示,用户就没有办法可以返回它。 注意1:弹出任务管理器不算离开Task。 注意2:应用程序启动的只是个Task,如果“singleTask”和“singleInstance”的Activity这个ntent Filter的话,自然不能在离开后返回到它。 在面对FLAG_ACTIVITY_NEW_TASK时,也有相似的困难。如果这个标志导致一个Activity启动了一个新的Task,并且用户按下HOME键离开它,这里必须有方法可以再次回到它。 一些机能(如Notification Manager)总是在外部的Task中启动Activity,而不是作为自己的一部分,因此,它总是把FLAG_ACTIVITY_NEW_TASK标志放入Intent,然后传递给startActivity()。 如果你的Activity可能会被外部的机能(可能使用这个标志)调用,注意用户可以额外的方式可以返回到启动的Task。 如果你不想用户回到某个Activity,可以把元素的finishOnTaskLaunch设置为“true”。 非Activity Context启动Activity 对于Context的startActivity方法,如果不是在其子类(Activity)中调用,那么必须对Intent加上FLAG_ACTIVITY_NEW_TASK。 具体可以参照Context中对startActivity方法的说明: public void startActivity (Intent intent) Launch a new activity. You will not receive any information about when the activity exits. Note that if this method is being called from outside of an Activity Context, then the Intent must include the FLAG_ACTIVITY_NEW_TASK launch flag. This is because, without being started from an existing Activity, there is no existing task in which to place the new activity and thus it needs to be placed in its own separate task. This method throws ActivityNotFoundException if there was no Activity found to run the given Intent. Parameters intent The description of the activity to start.