首页 > 代码库 > AndroidManifest详解之Application(有图更好懂)

AndroidManifest详解之Application(有图更好懂)

能够包含的标签:
  1.     <activity>
  2.     <activity-alias>
  3.     <service>
  4.     <receiver>
  5.     <provider>
  6. <uses-library>

常用的属性:

android:process

默认情况下,Android为每个应用程序创建一个单独的进程,所有组件运行在该进程中,这个默认进程的名字通常与该应用程序的包名相同。比如

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.lt.mytest" >
那么该程序默认的进程名为com.lt.mytest

设置该属性可以使得本应用程序与其它应用程序共享相同的进程,仅仅当这两个应用程序也共享一个拥有相同签名的UserId。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:sharedUserId="android.uid.phone" >
与其它应用程序共享的一个Linux User Id的名字。
默认情况下,Android为每个应用程序分配一个唯一的User Id。然而,如果有多个应用程序都将该属性设置为一个相同的值,那么它们将共享相同的Id。如果这些应用程序再被设置成运行在一个相同的进程,它们便可以彼此访问对方的数据。

android:allowbackup
是否将程序加入到系统的备份和恢复架构中。

android:taskAffinity
Activity的归属,也就是Activity应该在哪个Task中,Activity与Task的吸附关系。默认如果没有设置taskAffinity,则taskAffinity跟包名是一样的
taskAffinity 和 FLAG_ACTIVITY_NEW_TASK可用来决定activity启动时是否需要新建一个task。我们分四种情况看一下这两个标志对启动activity的影响:(前提:从MainActivity中启动ActivityA)
1)、两个标志都不设置
2)、有FLAG_ACTIVITY_NEW_TASK  
3)、无FLAG_ACTIVITY_NEW_TASK有taskAffinity (不同于MainActivity)
4)、有FLAG_ACTIVITY_NEW_TASK有taskAffinity
注意上面的标志都是针对于启动的ActivityA,FLAG_ACTIVITY_NEW_TASK  是在启动ActivityA的Intent中设置的,taskAffinity 是在AndroidManifest中ActivityA中设置,另外注意这里两个actiity的启动模式都设置为standard
1、先看第一中情况:

主要代码:

<activity android:name=".ActivityA"    
			android:launchMode="standard"  
			android:label="@string/title_activityA">    
  <intent-filter>    
	  <action android:name="com.leaves.ipanel.ActivityA"/>    
	  <category android:name="android.intent.category.DEFAULT"/>    
  </intent-filter>    
</activity>  
MainActivity启动activity  
public void onClick(View arg0) {  
	// TODO Auto-generated method stub  
	Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
	Intent intent = new Intent("com.leaves.ipanel.ActivityA");      

	startActivity(intent);   
} 
启动A之后的堆栈: 



2、有FLAG_ACTIVITY_NEW_TASK 
我们添加FLAG_ACTIVITY_NEW_TASK  

public void onClick(View arg0) {  
	// TODO Auto-generated method stub  
	Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
	Intent intent = new Intent("com.leaves.ipanel.ActivityA");      
	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
	startActivity(intent);   
}  
启动A之后的堆栈:

3、无FLAG_ACTIVITY_NEW_TASK有taskAffinity (不同于MainActivity)

<activity android:name=".ActivityA"    
            android:launchMode="standard"  
            android:taskAffinity="com.leaves.test.ActivityA"  
          android:label="@string/title_activityA">    
       <intent-filter>    
           <action android:name="com.leaves.ipanel.ActivityA"/>    
           <category android:name="android.intent.category.DEFAULT"/>    
       </intent-filter>    
</activity> 
    public void onClick(View arg0) {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
        Intent intent = new Intent("com.leaves.ipanel.ActivityA");      
          
        startActivity(intent);   
    }  
查看一下启动A之后的堆栈:


4、有FLAG_ACTIVITY_NEW_TASK有taskAffinity

把FLAG_ACTIVITY_NEW_TASK添加上去    

public void onClick(View arg0) {  
	// TODO Auto-generated method stub  
	Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
	Intent intent = new Intent("com.leaves.ipanel.ActivityA");      
	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
	startActivity(intent);   
} 


查看一下启动A之后的堆栈:

上面我们测试的两个Activity是在同一个应用中,如果他们在不同的应用中呢,例如ActivityA跟MainActivity不在一个apk中,其实情况还是一样的.因为默认如果没有设置taskAffinity,则taskAffinity跟包名是一样的。若不考虑android:allowTaskReparenting,如果ActivityA跟MainActivity不在一个apk中,当没有FLAG_ACTIVITY_NEW_TASK时,则两者应该是在同一个task,但是如果有FLAG_ACTIVITY_NEW_TASK,则两者应该会在不同的task中。

android:allowTaskReparenting

主要作用是activity的迁移,即从一个task迁移到另一个task,这个迁移跟activity的taskAffinity有关,必须是将该activity从旧的 taskAffinity迁移到新的taskAffinity中.只有设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标识才会用到该属性。从home上启动的程序都会设置该Flag,会进行task reset.

下面举个例子,有两个apk

apk1中含有个Activity:MainActivityA和ActivityB, ActivityB设置了allowTaskReparenting为false.
apk2中含有两一个activity:MainActivityB,MainActivityB点击的时候会启动ActivityB

首先我们启动apk2,进入MainActivityB,点击MainActivityB会进入ActivityB, 按home键,再从Home键启动apk1,用dumpsys工具得到这个时候的堆栈:



图中蓝色线框部分表示对应的Activity所属的task

可以看到,然从Home启动apk1的时候带有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,但在任务重置的过程中什么事也没有做。
我们把ActivityB的allowTaskReparenting改为true,这个时候前面的步骤一样,当我们从Home启动apk1时,我们惊奇的发现,启动的竟然是ActivityB,可以看到此时的堆栈:


这是由于重置任务的时候把它迁移到了新启动的task中。分析android源码中的resetTaskIfNeededLocked函数时就会明白这个是怎么回事了。

android:exported
这个属性用于指示该服务是否能够被其他应用程序组件调用或跟它交互。如果设置为true,则能够被调用或交互,否则不能。设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。
它的默认值依赖与该服务所包含的过滤器。没有过滤器则意味着该服务只能通过指定明确的类名来调用,这样就是说该服务只能在应用程序的内部使用(因为其他外部使用者不会知道该服务的类名),因此这种情况下,这个属性的默认值是false。另一方面,如果至少包含了一个过滤器,则意味着该服务可以给外部的其他应用提供服务,因此默认值是true。
这个属性不是限制把服务暴露给其他应用程序的唯一方法。还可以使用权限来限制能够跟该服务交互的外部实体。