Android是如何使用AndroidManifest.xml的?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android是如何使用AndroidManifest.xml的?相关的知识,希望对你有一定的参考价值。

就好比broadcast,不需要启动程序就能接受广播,依靠的就是AndroidManifest.xml中的intent-filter,想问下,AndroidManifest.xml文件是在程序安装的时候就写进了系统的某个配置文件中,还是每次开机读取一次所有应用的AndroidManifest.xml文件?
第二种情况不太可能,如果是第一种情况,那Android把AndroidManifest.xml下的配置读取到哪了?是/data/dalvik-cache目录不?又是如何调用的?

一、关于AndroidManifest.xml

AndroidManifest.xml 是每个android程序中必须的文件。它位于整个项目的根目录,描述了package中暴露的组件(activities, services, 等等),他们各自的实现类,各种能被处理的数据和启动位置。 除了能声明程序中的Activities, ContentProviders, Services, 和Intent Receivers,还能指定permissions和instrumentation(安全控制和测试)

二、AndroidManifest.xml结构

<?xmlversion="1.0"encoding="utf-8"?>
<manifest>
    <application>
       <activity>
           <intent-filter>
               <action/>
               <category/>
           </intent-filter>
      </activity>
       <activity-alias>
           <intent-filter></intent-filter>
           <meta-data/>
      </activity-alias>
       <service>
           <intent-filter></intent-filter>
           <meta-data/>
       </service>
       <receiver>
           <intent-filter></intent-filter>
           <meta-data/>
       </receiver>
       <provider>
           <grant-uri-permission/>
           <meta-data/>
       </provider>
       <uses-library/>
    </application>
    <uses-permission/>
    <permission/>
    <permission-tree/>
    <permission-group/>
    <instrumentation/>
    <uses-sdk/>
    <uses-configuration/> 
    <uses-feature/> 
    <supports-screens/>
</manifest>

三、各个节点的详细介绍

 上面就是整个am(androidManifest).xml的结构,下面以外向内开始阐述~~

1、第一层(<Manifest>):(属性)

<manifest  xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.woody.test"
          android:sharedUserId="string"
          android:sharedUserLabel="string resource"
          android:versionCode="integer"
          android:versionName="string"
          android:installLocation=["auto" | "internalOnly" | "preferExternal"] >
</manifest>

A、xmlns:android

定义android命名空间,一般为http://schemas.android.com/apk/res/android,这样使得Android中各种标准属性能在文件中使用,提供了大部分元素中的数据。


B、package

指定本应用内java主程序包的包名,它也是一个应用进程的默认名称


C、sharedUserId

表明数据权限,因为默认情况下,Android给每个APK分配一个唯一的UserID,所以是默认禁止不同APK访问共享数据的。若要共享数据,第一可以采用Share Preference方法,第二种就可以采用sharedUserId了,将不同APK的sharedUserId都设为一样,则这些APK之间就可以互相共享数据了。详见:http://wallage.blog.163.com/blog/static/17389624201011010539408/

D、sharedUserLabel

一个共享的用户名,它只有在设置了sharedUserId属性的前提下才会有意义


E、versionCode

是给设备程序识别版本(升级)用的必须是一个interger值代表app更新过多少次,比如第一版一般为1,之后若要更新版本就设置为2,3等等。。。


F、versionName

这个名称是给用户看的,你可以将你的APP版本号设置为1.1版,后续更新版本设置为1.2、2.0版本等等。。。


G、installLocation

安装参数,是Android2.2中的一个新特性,installLocation有三个值可以选择:internalOnly、auto、preferExternal

选择preferExternal,系统会优先考虑将APK安装到SD卡上(当然最终用户可以选择为内部ROM存储上,如果SD存储已满,也会安装到内部存储上)

选择auto,系统将会根据存储空间自己去适应

选择internalOnly是指必须安装到内部才能运行

(注:需要进行后台类监控的APP最好安装在内部,而一些较大的游戏APP最好安装在SD卡上。现默认为安装在内部,如果把APP安装在SD卡上,首先得设置你的level为8,并且要配置android:installLocation这个参数的属性为preferExternal)


2、第二层(<Application>):属性

一个AndroidManifest.xml中必须含有一个Application标签,这个标签声明了每一个应用程序的组件及其属性(如icon,label,permission等)

<application  android:allowClearUserData=["true" | "false"]
             android:allowTaskReparenting=["true" | "false"]
             android:backupAgent="string"
             android:debuggable=["true" | "false"]
             android:description="string resource"
             android:enabled=["true" | "false"]
             android:hasCode=["true" | "false"]
             android:icon="drawable resource"
             android:killAfterRestore=["true" | "false"]
             android:label="string resource"
             android:manageSpaceActivity="string"
             android:name="string"
             android:permission="string"
             android:persistent=["true" | "false"]
             android:process="string"
             android:restoreAnyVersion=["true" | "false"]
             android:taskAffinity="string"
             android:theme="resource or theme" >
</application>

A、android:allowClearUserData('true' or 'false')

用户是否能选择自行清除数据,默认为true,程序管理器包含一个选择允许用户清除数据。当为true时,用户可自己清理用户数据,反之亦然


B、android:allowTaskReparenting('true' or 'false')

是否允许activity更换从属的任务,比如从短信息任务切换到浏览器任务


C、android:backupAgent

这也是Android2.2中的一个新特性,设置该APP的备份,属性值应该是一个完整的类名,如com.project.TestCase,此属性并没有默认值,并且类名必须得指定(就是个备份工具,将数据备份到云端的操作)


D、android:debuggable

这个从字面上就可以看出是什么作用的,当设置为true时,表明该APP在手机上可以被调试。默认为false,在false的情况下调试该APP,就会报以下错误:

Device XXX requires that applications explicitely declare themselves as debuggable in their manifest.

 Application XXX does not have the attribute 'debuggable' set to TRUE in its manifest and cannot be debugged.


E、android:description/android:label

此两个属性都是为许可提供的,均为字符串资源,当用户去看许可列表(android:label)或者某个许可的详细信息(android:description)时,这些字符串资源就可以显示给用户。label应当尽量简短,之需要告知用户该许可是在保护什么功能就行。而description可以用于具体描述获取该许可的程序可以做哪些事情,实际上让用户可以知道如果他们同意程序获取该权限的话,该程序可以做什么。我们通常用两句话来描述许可,第一句描述该许可,第二句警告用户如果批准该权限会可能有什么不好的事情发生


F、android:enabled

Android系统是否能够实例化该应用程序的组件,如果为true,每个组件的enabled属性决定那个组件是否可以被 enabled。如果为false,它覆盖组件指定的值;所有组件都是disabled。


G、android:hasCode('true' or 'false')

表示此APP是否包含任何的代码,默认为true,若为false,则系统在运行组件时,不会去尝试加载任何的APP代码

一个应用程序自身不会含有任何的代码,除非内置组件类,比如Activity类,此类使用了AliasActivity类,当然这是个罕见的现象

(在Android2.3可以用标准C来开发应用程序,可在androidManifest.xml中将此属性设置为false,因为这个APP本身已经不含有任何的JAVA代码了)

H、android:icon

这个很简单,就是声明整个APP的图标,图片一般都放在drawable文件夹下

I、android:killAfterRestore

J、android:manageSpaceActivity

K、android:name

为应用程序所实现的Application子类的全名。当应用程序进程开始时,该类在所有应用程序组件之前被实例化。

若该类(比方androidMain类)是在声明的package下,则可以直接声明android:name="androidMain",但此类是在package下面的子包的话,就必须声明为全路径或android:name="package名称.子包名成.androidMain"

L、android:permission

设置许可名,这个属性若在<application>上定义的话,是一个给应用程序的所有组件设置许可的便捷方式,当然它是被各组件设置的许可名所覆盖的

M、android:presistent

该应用程序是否应该在任何时候都保持运行状态,默认为false。因为应用程序通常不应该设置本标识,持续模式仅仅应该设置给某些系统应用程序才是有意义的。

N、android:process

应用程序运行的进程名,它的默认值为<manifest>元素里设置的包名,当然每个组件都可以通过设置该属性来覆盖默认值。如果你想两个应用程序共用一个进程的话,你可以设置他们的android:process相同,但前提条件是他们共享一个用户ID及被赋予了相同证书的时候

O、android:restoreAnyVersion

同样也是android2.2的一个新特性,用来表明应用是否准备尝试恢复所有的备份,甚至该备份是比当前设备上更要新的版本,默认是false

P、android:taskAffinity

拥有相同的affinity的Activity理论上属于相同的Task,应用程序默认的affinity的名字是<manifest>元素中设定的package名


Q、android:theme

是一个资源的风格,它定义了一个默认的主题风格给所有的activity,当然也可以在自己的theme里面去设置它,有点类似style。



不过现在在android stuido 上面 版本控制已经使用Gradle了。

参考技术A 每次有BroadCast发出来时,都会遍历你所有的APK,解析 AndroidManifest.xml中的intent-filter。
比如,当一个BroadCast能够被多个APK接收时,能够立马弹出多选框让你选择由哪个APK启动。
参考技术B Manifest主要功能:APP名称 图标 版本号 代码执行 权限 主题
所以activity执行时都要要在里面走一遍
执行打电话发短信等特殊权限时需要在里面添加权限

Android 如何静默安装app

Android 要想静默安装app,必须是系统应用或者具有Root权限,否则根本不可能实现静默安装。

本文假设你的app是系统应用(有系统签名,或者放在系统/system/app 或 /system/priv-app分区),则可以进行以下安装:

注意:静默安装还需要在你的AndroidManifest.xml中添加权限声明。该权限默认赋予系统应用,第三方应用即使声明了,也拿不到该权限! [html] view plain copy
  1. <!-- 静默安装 -->  
  2. <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

1. 有提示的安装(所有第三方应用都可以)

[java] view plain copy
  1. Intent intent = new Intent(Intent.ACTION_VIEW);  
  2. intent.setDataAndType(Uri.parse("file://" + apkFilePath), "application/vnd.android.package-archive");  
  3. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  4. mContext.startActivity(intent);  
这是调用系统的AppInstaller,提示用户安装升级。

2. 静默安装:利用ProcessBuilder

[java] view plain copy
  1. /** 
  2.  * install slient 
  3.  * 
  4.  * @param filePath 
  5.  * @return 0 means normal, 1 means file not exist, 2 means other exception error 
  6.  */  
  7. public static int installSilent(String filePath)   
  8.     File file = new File(filePath);  
  9.     if (filePath == null || filePath.length() == 0 || file == null || file.length() <= 0 || !file.exists() || !file.isFile())   
  10.         return 1;  
  11.       
  12.   
  13.     String[] args =  "pm""install""-r", filePath ;  
  14.     ProcessBuilder processBuilder = new ProcessBuilder(args);  
  15.     Process process = null;  
  16.     BufferedReader successResult = null;  
  17.     BufferedReader errorResult = null;  
  18.     StringBuilder successMsg = new StringBuilder();  
  19.     StringBuilder errorMsg = new StringBuilder();  
  20.     int result;  
  21.     try   
  22.         process = processBuilder.start();  
  23.         successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));  
  24.         errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));  
  25.         String s;  
  26.         while ((s = successResult.readLine()) != null)   
  27.             successMsg.append(s);  
  28.           
  29.         while ((s = errorResult.readLine()) != null)   
  30.             errorMsg.append(s);  
  31.           
  32.      catch (IOException e)   
  33.         e.printStackTrace();  
  34.      catch (Exception e)   
  35.         e.printStackTrace();  
  36.      finally   
  37.         try   
  38.             if (successResult != null)   
  39.                 successResult.close();  
  40.               
  41.             if (errorResult != null)   
  42.                 errorResult.close();  
  43.               
  44.          catch (IOException e)   
  45.             e.printStackTrace();  
  46.           
  47.         if (process != null)   
  48.             process.destroy();  
  49.           
  50.       
  51.   
  52.     // TODO should add memory is not enough here  
  53.     if (successMsg.toString().contains("Success") || successMsg.toString().contains("success"))   
  54.         result = 0;  
  55.      else   
  56.         result = 2;  
  57.       
  58.     Log.d("test-test""successMsg:" + successMsg + ", ErrorMsg:" + errorMsg);  
  59.     return result;  
  60.   
3. 静默安装:利用Runtime.getRuntime().exec() [java] view plain copy
  1. private static final String TAG = "test-test";  
  2.   
  3. private static final int TIME_OUT = 60 * 1000;  
  4.   
  5. private static String[] SH_PATH =   
  6.         "/system/bin/sh",  
  7.         "/system/xbin/sh",  
  8.         "/system/sbin/sh"  
  9. ;  
  10.   
  11. public static boolean executeInstallCommand(String filePath)   
  12.     String command = “pm install -r ” + filePath;  
  13.     Process process = null;  
  14.     DataOutputStream os = null;  
  15.     StringBuilder successMsg = new StringBuilder();  
  16.     StringBuilder errorMsg = new StringBuilder();  
  17.     BufferedReader successResult = null;  
  18.     BufferedReader errorResult = null;  
  19.     try   
  20.         process = runWithEnv(getSuPath(), null);  
  21.         if (process == null)   
  22.             return false;  
  23.           
  24.   
  25.         successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));  
  26.         errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));  
  27.   
  28.         os = new DataOutputStream(process.getOutputStream());  
  29.         os.writeBytes(command + "\\n");  
  30.         os.writeBytes("echo \\"rc:\\" $?\\n");  
  31.         os.writeBytes("exit\\n");  
  32.         os.flush();  
  33.   
  34.         String s;  
  35.         while ((s = successResult.readLine()) != null)   
  36.             successMsg.append(s);  
  37.           
  38.         while ((s = errorResult.readLine()) != null)   
  39.             errorMsg.append(s);  
  40.           
  41.   
  42.         // Handle a requested timeout, or just use waitFor() otherwise.  
  43.         if (TIME_OUT > 0)   
  44.             long finish = System.currentTimeMillis() + TIME_OUT;  
  45.             while (true)   
  46.                 Thread.sleep(300);  
  47.                 if (!isProcessAlive(process))   
  48.                     break;  
  49.                   
  50.   
  51.                 if (System.currentTimeMillis() > finish)   
  52.                     Log.w(TAG, "Process doesn't seem to stop on it's own, assuming it's hanging");  
  53.                     // Note: 'finally' will call destroy(), but you might still see zombies.  
  54.                     return true;  
  55.                   
  56.               
  57.          else   
  58.             process.waitFor();  
  59.           
  60.   
  61.         // In order to consider this a success, we require to things: a) a proper exit value, and ...  
  62.         if (process.exitValue() != 0)   
  63.             return false;  
  64.           
  65.   
  66.         return true;  
  67.   
  68.      catch (FileNotFoundException e)   
  69.         Log.w(TAG, "Failed to run command, " + e.getMessage());  
  70.         return false;  
  71.      catch (IOException e)   
  72.         Log.w(TAG, "Failed to run command, " + e.getMessage());  
  73.         return false;  
  74.      catch (InterruptedException e)   
  75.         Log.w(TAG, "Failed to run command, " + e.getMessage());  
  76.         return false;  
  77.      finally   
  78.         if (os != null)   
  79.             try   
  80.                 os.close();  
  81.              catch (IOException e)   
  82.                 throw new RuntimeException(e);  
  83.               
  84.           
  85.   
  86.         try   
  87.             if (successResult != null)   
  88.                 successResult.close();  
  89.               
  90.             if (errorResult != null)   
  91.                 errorResult.close();  
  92.               
  93.          catch (IOException e)   
  94.             e.printStackTrace();  
  95.           
  96.   
  97.         if (process != null)   
  98.             try   
  99.                 // Yes, this really is the way to check if the process is still running.  
  100.                 process.exitValue();  
  101.              catch (IllegalThreadStateException e)   
  102.                 process.destroy();  
  103.               
  104.           
  105.       
  106.   
  107.   
  108. private static Process runWithEnv(String command, String[] customEnv) throws IOException   
  109.     List<String> envList = new ArrayList<String>();  
  110.     Map<String, String> environment = System.getenv();  
  111.     if (environment != null)   
  112.         for (Map.Entry<String, String> entry : environment.entrySet())   
  113.             envList.add(entry.getKey() + "=" + entry.getValue());  
  114.           
  115.       
  116.   
  117.     if (customEnv != null)   
  118.         for (String value : customEnv)   
  119.             envList.add(value);  
  120.           
  121.       
  122.   
  123.     String[] arrayEnv = null;  
  124.     if (envList.size() > 0)   
  125.         arrayEnv = new String[envList.size()];  
  126.         for (int i = 0; i < envList.size(); i++)   
  127.             arrayEnv[i] = envList.get(i);  
  128.           
  129.       
  130.   
  131.     Process process = Runtime.getRuntime().exec(command, arrayEnv);  
  132.     return process;  
  133.   
  134.   
  135. /** 
  136.  * Check whether a process is still alive. We use this as a naive way to implement timeouts. 
  137.  */  
  138. private static boolean isProcessAlive(Process p)   
  139.     try   
  140.         p.exitValue();  
  141.         return false;  
  142.      catch (IllegalThreadStateException e)   
  143.         return true;  
  144.       
  145.   
  146.   
  147. /** Get the SU file path if it exist */  
  148. private static String getSuPath()   
  149.     for (String p : SH_PATH)   
  150.         File sh = new File(p);  
  151.         if (sh.exists())   
  152.             return p;  
  153.           
  154.       
  155.     return "su";  
  156.   
4. 静默安装:利用反射调用API-PackageManager.installPackage()
[java] view plain copy
  1. public static void installSilentWithReflection(Context context, String filePath)   
  2.     try   
  3.         PackageManager packageManager = context.getPackageManager();  
  4.         Method method = packageManager.getClass().getDeclaredMethod("installPackage",  
  5.                 new Class[] Uri.class, IPackageInstallObserver.classint.class, String.class );  
  6.         method.setAccessible(true);  
  7.         File apkFile = new File(filePath);  
  8.         Uri apkUri = Uri.fromFile(apkFile);  
  9.   
  10.         method.invoke(packageManager, new Object[] apkUri, new IPackageInstallObserver.Stub()   
  11.             @Override  
  12.             public void packageInstalled(String pkgName, int resultCode) throws RemoteException   
  13.                 Log.d(TAG, "packageInstalled = " + pkgName + "; resultCode = " + resultCode) ;  
  14.               
  15.         , Integer.valueOf(2), "com.ali.babasecurity.yunos");  
  16.         //PackageManager.INSTALL_REPLACE_EXISTING = 2;  
  17.      catch (NoSuchMethodException e)   
  18.         e.printStackTrace();  
  19.      catch (Exception e)   
  20.         e.printStackTrace();  
  21.       
  22.   
上面用到了反射调用,IPackageInstallObserver.class这个类在android sdk里面是没有的,您需要下载 android_dependency.jar放到你工程的libs目录,这个jar提供了与PackageManager反射调用相关的类的定义。

以上是关于Android是如何使用AndroidManifest.xml的?的主要内容,如果未能解决你的问题,请参考以下文章

Android studio 创建安卓项目hello

指定 Android 库版本代码/名称

AndroidAndroid如何一进入一个activity就弹出输入法键盘

Android系统动态申请权限的机制流程总结

反应原生android,在尝试获取firebase消息设备令牌时得到FIS_AUTH_ERROR

Android简单的编写一个txt阅读器(没有处理字符编码),适用于新手学习