Android APK应用安装原理(2)-查找APK并自动安装

Android每次启动的时候会自动安装位于特定目录下的APK,这个过程会在packageManagerService这个类的构造方法中进行,这里会创建多个目录用于预查找:

[java]   view plain copy
  1. public PackageManagerService(Context context, boolean factoryTest) {  
  2.   
  3. ...  
  4.   
  5. mFrameworkDir = new File(Environment.getRootDirectory(), "framework"); // system/framework  
  6.   
  7. mSystemAppDir = new File(Environment.getRootDirectory(), "app"); // system/app  
  8.   
  9. mAppInstallDir = new File(dataDir, "app"); // data/app  
  10.   
  11. mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); // data/app-private  
  12.   
  13. mAppDataDir = new File(dataDir, "data"); // data/data  
  14.   
  15. ...  
  16.   
  17. }  


它会在这5个地方寻找APK并通过Installer这个类来安装,通过
[java]   view plain copy
  1. synchronized (mInstallLock) {  
  2.    synchronized (mPackages) {  
  3.      ......  
  4.    }  
  5. }  
可以看出,同时只能对一个应用进行安装或者删除,且对一个应用做一个操作的时候就不能对同一个应用做另外一个操作
同时可写的目录就会添加AppObserver 用于监听目录下的变化并调用removePackageLI或者scanPackageLI方法,前者用于删除应用,后者用于安装,这里说的安装仅仅只是将解析过的manifest以一些数据结构的形式保存在packageManagerService中,也就是保存在了内存中并常驻内存,以后系统或者非系统的应用发出的任何意图都会在这里查找匹配的组件。

而真正意义上的安装是安装器 Lnstaller这个类在处理的,你可以讲一个APK文件的后缀改为.RAR 然后解压,会看到里面有里面有一个AndroidManifest.xml,classes.dex,assets
,META-INF和res,而真正的安装是把这些除了manifest之外的东西放到android系统的相应的目录中去,其中classes.dex相当于dailvk虚拟机上的可执行文件,assets是放的一些不会被变异的原始资源,res里是一些DEX要用到的资源,META-INF是描述APK的元数据



而Installer完整安装的原理又是什么呢?  com.android.server.Installer这个类其实是通过 ADB命令来安装的,相当于 adb install xx.xx.xx  :

[java]   view plain copy
  1. public int install(String name, int uid, int gid) {  
  2.         StringBuilder builder = new StringBuilder("install");  
  3.         builder.append(' ');  
  4.         builder.append(name);  
  5.         builder.append(' ');  
  6.         builder.append(uid);  
  7.         builder.append(' ');  
  8.         builder.append(gid);  
  9.         return execute(builder.toString());  
  10.     }  

execute的实现又是
[java]   view plain copy
  1. private int execute(String cmd) {  
  2.         String res = transaction(cmd);  
  3.         try {  
  4.             return Integer.parseInt(res);  
  5.         } catch (NumberFormatException ex) {  
  6.             return -1;  
  7.         }  
  8.     }  

transaction又是通过writeCommand(cmd)这个方法实现的

[java]   view plain copy
  1. private boolean writeCommand(String _cmd) {  
  2.         byte[] cmd = _cmd.getBytes();  
  3.         int len = cmd.length;  
  4.         if ((len < 1) || (len > 1024)) return false;  
  5.         buf[0] = (byte) (len & 0xff);  
  6.         buf[1] = (byte) ((len >> 8) & 0xff);  
  7.         try {  
  8.             mOut.write(buf, 02);  
  9.             mOut.write(cmd, 0, len);  
  10.         } catch (IOException ex) {  
  11.             Slog.e(TAG,"write error");  
  12.             disconnect();  
  13.             return false;  
  14.         }  
  15.         return true;  
  16.     }  

这里的mOut 是通过LocalSocket这个类获得的runtime运行时环境的流,往流里写东西然后刷新进去 就相当于在窗口下输入 各种指令了,所以真正安装的更底层的步骤就只有看adb这个命令的C/C++的源码了~

好了基本的安装步骤和原理就是这样的啦~!

你可能感兴趣的:(android)