APK安装过程及原理详解

应用程序包的安装是android的特点

APK为AndroidPackage的缩写

Android应用安装有如下四种方式:

1.系统应用安装――开机时完成,没有安装界面

2.网络下载应用安装――通过market应用完成,没有安装界面

3.ADB工具安装――没有安装界面。

4.第三方应用安装――通过SD卡里的APK文件安装,有安装界面,由         packageinstaller.apk应用处理安装及卸载过程的界面。

应用安装的流程及路径 
应用安装涉及到如下几个目录:        

system/app ---------------系统自带的应用程序,获得adb root权限才能删除

data/app  ---------------用户程序安装的目录。安装时把                                                                                                      apk文件复制到此目录
data/data ---------------存放应用程序的数据
data/dalvik-cache--------将apk中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一)

安装过程:

复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。

卸载过程:

删除安装过程中在上述三个目录下创建的文件及目录。

安装应用的过程解析

一.开机安装 
PackageManagerService处理各种应用的安装,卸载,管理等工作,开机时由systemServer启动此服务

(源文件路径:android\frameworks\base\services\java\com\android\server\PackageManagerService.java)

 

PackageManagerService服务启动的流程:

1.首先扫描安装“system\framework”目录下的jar包


           

  1. // Find base frameworks (resource packages without code).   
  2.            mFrameworkInstallObserver = new AppDirObserver(  
  3.                mFrameworkDir.getPath(), OBSERVER_EVENTS, true);  
  4.            mFrameworkInstallObserver.startWatching();  
  5.            scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM  
  6.                    | PackageParser.PARSE_IS_SYSTEM_DIR,  
  7.                    scanMode | SCAN_NO_DEX, 0);  
// Find base frameworks (resource packages without code). mFrameworkInstallObserver = new AppDirObserver( mFrameworkDir.getPath(), OBSERVER_EVENTS, true); mFrameworkInstallObserver.startWatching(); scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_NO_DEX, 0);

2.扫描安装系统system/app的应用程序

          

  1. // Collect all system packages.   
  2.           mSystemAppDir = new File(Environment.getRootDirectory(), "app");  
  3.           mSystemInstallObserver = new AppDirObserver(  
  4.               mSystemAppDir.getPath(), OBSERVER_EVENTS, true);  
  5.           mSystemInstallObserver.startWatching();  
  6.           scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM  
  7.                   | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);  
// Collect all system packages. mSystemAppDir = new File(Environment.getRootDirectory(), "app"); mSystemInstallObserver = new AppDirObserver( mSystemAppDir.getPath(), OBSERVER_EVENTS, true); mSystemInstallObserver.startWatching(); scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

3.制造商的目录下/vendor/app应用包

           

  1. // Collect all vendor packages.   
  2.            mVendorAppDir = new File("/vendor/app");  
  3.            mVendorInstallObserver = new AppDirObserver(  
  4.                mVendorAppDir.getPath(), OBSERVER_EVENTS, true);  
  5.            mVendorInstallObserver.startWatching();  
  6.            scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM  
  7.                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);  
// Collect all vendor packages. mVendorAppDir = new File("/vendor/app"); mVendorInstallObserver = new AppDirObserver( mVendorAppDir.getPath(), OBSERVER_EVENTS, true); mVendorInstallObserver.startWatching(); scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

4.扫描“data\app”目录,即用户安装的第三方应用

  1. scanDirLI(mAppInstallDir, 0, scanMode, 0);  
scanDirLI(mAppInstallDir, 0, scanMode, 0);

5.扫描" data\app-private"目录,即安装DRM保护的APK文件(一个受保护的歌曲或受保 护的视频是使用 DRM 保护的文件)

  1. scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,  
  2.                     scanMode, 0);  
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode, 0);

扫描方法的代码清单

  1. private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {  
  2.         String[] files = dir.list();  
  3.         if (files == null) {  
  4.             Log.d(TAG, "No files in app dir " + dir);  
  5.             return;  
  6.         }  
  7.         if (false) {  
  8.             Log.d(TAG, "Scanning app dir " + dir);  
  9.         }  
  10.         int i;  
  11.         for (i=0; i<files.length; i++) {  
  12.             File file = new File(dir, files[i]);  
  13.             if (!isPackageFilename(files[i])) {  
  14.                 // Ignore entries which are not apk's   
  15.                 continue;  
  16.             }  
  17.             PackageParser.Package pkg = scanPackageLI(file,  
  18.                     flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);  
  19.             // Don't mess around with apps in system partition.   
  20.             if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&  
  21.                     mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {  
  22.                 // Delete the apk   
  23.                 Slog.w(TAG, "Cleaning up failed install of " + file);  
  24.                 file.delete();  
  25.             }  
  26.         }  
  27.     }  
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) { String[] files = dir.list(); if (files == null) { Log.d(TAG, "No files in app dir " + dir); return; } if (false) { Log.d(TAG, "Scanning app dir " + dir); } int i; for (i=0; i<files.length; i++) { File file = new File(dir, files[i]); if (!isPackageFilename(files[i])) { // Ignore entries which are not apk's continue; } PackageParser.Package pkg = scanPackageLI(file, flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime); // Don't mess around with apps in system partition. if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 && mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) { // Delete the apk Slog.w(TAG, "Cleaning up failed install of " + file); file.delete(); } } }

并且从该扫描方法中可以看出调用了scanPackageLI()

private PackageParser.Package scanPackageLI(File scanFile,

int parseFlags, int scanMode, long currentTime)

跟踪scanPackageLI()方法后发现,程序经过很多次的if else 的筛选,最后判定可以安装后调用了 mInstaller.install

  1. if (mInstaller != null) {  
  2.                     int ret = mInstaller.install(pkgName, useEncryptedFSDir,  pkg.applicationInfo.uid,pkg.applicationInfo.uid);  
  3.                     if(ret < 0) {  
  4.                         // Error from installer   
  5.                         mLastScanError =    PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;  
  6.                         return null;  
  7.                     }  
  8.                 }  
if (mInstaller != null) { int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,pkg.applicationInfo.uid); if(ret < 0) { // Error from installer mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return null; } }

mInstaller.install()  通过    

  LocalSocketAddress address = new LocalSocketAddress(

                "installd", LocalSocketAddress.Namespace.RESERVED);

指挥installd在C语言的文件中完成工作

PackageManagerService小节 :1)从apk, xml中载入pacakge信息, 存储到内部成员变量中, 用于后面的查找. 关键的方法是scanPackageLI().
2)各种查询操作, 包括query Intent操作.
3)install package和delete package的操作. 还有后面的关键方法是installPackageLI().

二、从网络上下载应用:

下载完成后,会自动调用Packagemanager的安装方法installPackage()

   

   /* Called when a downloaded package installation has been confirmed by the user */

    由英文注释可见PackageManagerService类的installPackage()函数为安装程序入口。

   

  1. public void installPackage(  
  2.            final Uri packageURI, final IPackageInstallObserver observer, final int flags,  
  3.            final String installerPackageName) {  
  4.        mContext.enforceCallingOrSelfPermission(  
  5.                android.Manifest.permission.INSTALL_PACKAGES, null);  
  6.        Message msg = mHandler.obtainMessage(INIT_COPY);  
  7.        msg.obj = new InstallParams(packageURI, observer, flags,  
  8.                installerPackageName);  
  9.        mHandler.sendMessage(msg);  
  10.    }  
public void installPackage( final Uri packageURI, final IPackageInstallObserver observer, final int flags, final String installerPackageName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INSTALL_PACKAGES, null); Message msg = mHandler.obtainMessage(INIT_COPY); msg.obj = new InstallParams(packageURI, observer, flags, installerPackageName); mHandler.sendMessage(msg); }

其中是通过PackageHandler的实例mhandler.sendMessage(msg)把信息发给继承Handler的类HandleMessage()方法

  1. class PackageHandler extends Handler{  
  2.                    
  3. *****************省略若干********************  
  4.          public void handleMessage(Message msg) {  
  5.             try {  
  6.                 doHandleMessage(msg);  
  7.             } finally {  
  8.                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  
  9.             }  
  10.         }  
  11.    ******************省略若干**********************  
  12.  }  
class PackageHandler extends Handler{ *****************省略若干******************** public void handleMessage(Message msg) { try { doHandleMessage(msg); } finally { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } } ******************省略若干********************** }

把信息发给doHandleMessage()方法,方法中用switch()语句进行判定传来Message

       

  1.  void doHandleMessage(Message msg) {  
  2.             switch (msg.what) {  
  3.              
  4.                 case INIT_COPY: {  
  5.                     if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");  
  6.                     HandlerParams params = (HandlerParams) msg.obj;  
  7.                     int idx = mPendingInstalls.size();  
  8.                     if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);  
  9.                     // If a bind was already initiated we dont really   
  10.                     // need to do anything. The pending install   
  11.                     // will be processed later on.   
  12.                     if (!mBound) {  
  13.                         // If this is the only one pending we might   
  14.                         // have to bind to the service again.   
  15.                         if (!connectToService()) {  
  16.                             Slog.e(TAG, "Failed to bind to media container service");  
  17.                             params.serviceError();  
  18.                             return;  
  19.                         } else {  
  20.                             // Once we bind to the service, the first   
  21.                             // pending request will be processed.   
  22.                             mPendingInstalls.add(idx, params);  
  23.                         }  
  24.                     } else {  
  25.                         mPendingInstalls.add(idx, params);  
  26.                         // Already bound to the service. Just make   
  27.                         // sure we trigger off processing the first request.   
  28.                         if (idx == 0) {  
  29.                             mHandler.sendEmptyMessage(MCS_BOUND);  
  30.                         }  
  31.                     }  
  32.                     break;  
  33.                 }  
  34.                 case MCS_BOUND: {  
  35.                     if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");  
  36.                     if (msg.obj != null) {  
  37.                         mContainerService = (IMediaContainerService) msg.obj;  
  38.                     }  
  39.                     if (mContainerService == null) {  
  40.                         // Something seriously wrong. Bail out   
  41.                         Slog.e(TAG, "Cannot bind to media container service");  
  42.                         for (HandlerParams params : mPendingInstalls) {  
  43.                             mPendingInstalls.remove(0);  
  44.                             // Indicate service bind error   
  45.                             params.serviceError();  
  46.                         }  
  47.                         mPendingInstalls.clear();  
  48.                     } else if (mPendingInstalls.size() > 0) {  
  49.                         HandlerParams params = mPendingInstalls.get(0);  
  50.                         if (params != null) {  
  51.                             params.startCopy();  
  52.                         }  
  53.                     } else {  
  54.                         // Should never happen ideally.   
  55.                         Slog.w(TAG, "Empty queue");  
  56.                     }  
  57.                     break;  
  58.                 }  
  59.             ****************省略若干**********************  
  60. }  
  61. }               
void doHandleMessage(Message msg) { switch (msg.what) { case INIT_COPY: { if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy"); HandlerParams params = (HandlerParams) msg.obj; int idx = mPendingInstalls.size(); if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx); // If a bind was already initiated we dont really // need to do anything. The pending install // will be processed later on. if (!mBound) { // If this is the only one pending we might // have to bind to the service again. if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service"); params.serviceError(); return; } else { // Once we bind to the service, the first // pending request will be processed. mPendingInstalls.add(idx, params); } } else { mPendingInstalls.add(idx, params); // Already bound to the service. Just make // sure we trigger off processing the first request. if (idx == 0) { mHandler.sendEmptyMessage(MCS_BOUND); } } break; } case MCS_BOUND: { if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound"); if (msg.obj != null) { mContainerService = (IMediaContainerService) msg.obj; } if (mContainerService == null) { // Something seriously wrong. Bail out Slog.e(TAG, "Cannot bind to media container service"); for (HandlerParams params : mPendingInstalls) { mPendingInstalls.remove(0); // Indicate service bind error params.serviceError(); } mPendingInstalls.clear(); } else if (mPendingInstalls.size() > 0) { HandlerParams params = mPendingInstalls.get(0); if (params != null) { params.startCopy(); } } else { // Should never happen ideally. Slog.w(TAG, "Empty queue"); } break; } ****************省略若干********************** } }

public final boolean sendMessage (Message msg)

public final boolean sendEmptyMessage (int what)

两者参数有别。

然后调用抽象类HandlerParams中的一个startCopy()方法

abstract class HandlerParams {

final void startCopy() {

   ***************若干if语句判定否这打回handler消息*******

handleReturnCode();

}
}

handleReturnCode()复写了两次其中有一次是删除时要调用的,只列出安装调用的一个方法

       

  1. @Override  
  2.        void handleReturnCode() {  
  3.            // If mArgs is null, then MCS couldn't be reached. When it   
  4.            // reconnects, it will try again to install. At that point, this   
  5.            // will succeed.   
  6.            if (mArgs != null) {  
  7.                processPendingInstall(mArgs, mRet);  
  8.            }  
  9.        }  
@Override void handleReturnCode() { // If mArgs is null, then MCS couldn't be reached. When it // reconnects, it will try again to install. At that point, this // will succeed. if (mArgs != null) { processPendingInstall(mArgs, mRet); } }

这时可以清楚的看见 processPendingInstall()被调用。

其中run()方法如下

  1. run(){  
  2. synchronized (mInstallLock) {  
  3.                         ************省略*****************  
  4.                         installPackageLI(args, true, res);  
  5.                      
  6.  }  
  7. }  
  8. instaPacakgeLI()args,res参数分析  
run(){ synchronized (mInstallLock) { ************省略***************** installPackageLI(args, true, res); } } instaPacakgeLI()args,res参数分析

-----------------------------------------------------------------------------------------

//InstallArgs 是在PackageService定义的static abstract class InstallArgs 静态抽象类。

  

  1. static abstract class InstallArgs {  
  2. *********************************************************************  
  3. 其中定义了flag标志,packageURL,创建文件,拷贝apk,修改包名称,  
  4.                     还有一些删除文件的清理,释放存储函数。  
  5.     *********************************************************************  
  6. }  
  7.   class PackageInstalledInfo {  
  8.         String name;  
  9.         int uid;  
  10.         PackageParser.Package pkg;  
  11.         int returnCode;  
  12.         PackageRemovedInfo removedInfo;  
  13.  }  
static abstract class InstallArgs { ********************************************************************* 其中定义了flag标志,packageURL,创建文件,拷贝apk,修改包名称, 还有一些删除文件的清理,释放存储函数。 ********************************************************************* } class PackageInstalledInfo { String name; int uid; PackageParser.Package pkg; int returnCode; PackageRemovedInfo removedInfo; }

-----------------------------------------------------------------------------------------

  

  1. private void installPackageLI(InstallArgs args,  
  2.           boolean newInstall, PackageInstalledInfo res) {  
  3.       int pFlags = args.flags;  
  4.       String installerPackageName = args.installerPackageName;  
  5.       File tmpPackageFile = new File(args.getCodePath());  
  6.       boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);  
  7.       boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);  
  8.       boolean replace = false;  
  9.       int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE  
  10.               | (newInstall ? SCAN_NEW_INSTALL : 0);  
  11.       // Result object to be returned   
  12.       res.returnCode = PackageManager.INSTALL_SUCCEEDED;  
  13.       // Retrieve PackageSettings and parse package   
  14.       int parseFlags = PackageParser.PARSE_CHATTY |  
  15.       (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |  
  16.       (onSd ? PackageParser.PARSE_ON_SDCARD : 0);  
  17.       parseFlags |= mDefParseFlags;  
  18.       PackageParser pp = new PackageParser(tmpPackageFile.getPath());  
  19.       pp.setSeparateProcesses(mSeparateProcesses);  
  20.       final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,  
  21.               null, mMetrics, parseFlags);  
  22.       if (pkg == null) {  
  23.           res.returnCode = pp.getParseError();  
  24.           return;  
  25.       }  
  26.       String pkgName = res.name = pkg.packageName;  
  27.       if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {  
  28.           if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {  
  29.               res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;  
  30.               return;  
  31.           }  
  32.       }  
  33.       if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {  
  34.           res.returnCode = pp.getParseError();  
  35.           return;  
  36.       }  
  37.       // Get rid of all references to package scan path via parser.   
  38.       pp = null;  
  39.       String oldCodePath = null;  
  40.       boolean systemApp = false;  
  41.       synchronized (mPackages) {  
  42.           // Check if installing already existing package   
  43.           if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {  
  44.               String oldName = mSettings.mRenamedPackages.get(pkgName);  
  45.               if (pkg.mOriginalPackages != null  
  46.                       && pkg.mOriginalPackages.contains(oldName)  
  47.                       && mPackages.containsKey(oldName)) {  
  48.                   // This package is derived from an original package,   
  49.                   // and this device has been updating from that original   
  50.                   // name.  We must continue using the original name, so   
  51.                   // rename the new package here.   
  52.                   pkg.setPackageName(oldName);  
  53.                   pkgName = pkg.packageName;  
  54.                   replace = true;  
  55.               } else if (mPackages.containsKey(pkgName)) {  
  56.                   // This package, under its official name, already exists   
  57.                   // on the device; we should replace it.   
  58.                   replace = true;  
  59.               }  
  60.           }  
  61.           PackageSetting ps = mSettings.mPackages.get(pkgName);  
  62.           if (ps != null) {  
  63.               oldCodePath = mSettings.mPackages.get(pkgName).codePathString;  
  64.               if (ps.pkg != null && ps.pkg.applicationInfo != null) {  
  65.                   systemApp = (ps.pkg.applicationInfo.flags &  
  66.                           ApplicationInfo.FLAG_SYSTEM) != 0;  
  67.               }  
  68.           }  
  69.       }  
  70.       if (systemApp && onSd) {  
  71.           // Disable updates to system apps on sdcard   
  72.           Slog.w(TAG, "Cannot install updates to system apps on sdcard");  
  73.           res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;  
  74.           return;  
  75.       }  
  76.       if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {  
  77.           res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;  
  78.           return;  
  79.       }  
  80.       // Set application objects path explicitly after the rename   
  81.       setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());  
  82.       pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();  
  83.       if (replace) {  
  84.           replacePackageLI(pkg, parseFlags, scanMode,  
  85.                   installerPackageName, res);  
  86.       } else {  
  87.           installNewPackageLI(pkg, parseFlags, scanMode,  
  88.                   installerPackageName,res);  
  89.       }  
  90.   }  
private void installPackageLI(InstallArgs args, boolean newInstall, PackageInstalledInfo res) { int pFlags = args.flags; String installerPackageName = args.installerPackageName; File tmpPackageFile = new File(args.getCodePath()); boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0); boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0); boolean replace = false; int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE | (newInstall ? SCAN_NEW_INSTALL : 0); // Result object to be returned res.returnCode = PackageManager.INSTALL_SUCCEEDED; // Retrieve PackageSettings and parse package int parseFlags = PackageParser.PARSE_CHATTY | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | (onSd ? PackageParser.PARSE_ON_SDCARD : 0); parseFlags |= mDefParseFlags; PackageParser pp = new PackageParser(tmpPackageFile.getPath()); pp.setSeparateProcesses(mSeparateProcesses); final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile, null, mMetrics, parseFlags); if (pkg == null) { res.returnCode = pp.getParseError(); return; } String pkgName = res.name = pkg.packageName; if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) { if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) { res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY; return; } } if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) { res.returnCode = pp.getParseError(); return; } // Get rid of all references to package scan path via parser. pp = null; String oldCodePath = null; boolean systemApp = false; synchronized (mPackages) { // Check if installing already existing package if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) { String oldName = mSettings.mRenamedPackages.get(pkgName); if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName) && mPackages.containsKey(oldName)) { // This package is derived from an original package, // and this device has been updating from that original // name. We must continue using the original name, so // rename the new package here. pkg.setPackageName(oldName); pkgName = pkg.packageName; replace = true; } else if (mPackages.containsKey(pkgName)) { // This package, under its official name, already exists // on the device; we should replace it. replace = true; } } PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { oldCodePath = mSettings.mPackages.get(pkgName).codePathString; if (ps.pkg != null && ps.pkg.applicationInfo != null) { systemApp = (ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } } } if (systemApp && onSd) { // Disable updates to system apps on sdcard Slog.w(TAG, "Cannot install updates to system apps on sdcard"); res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; return; } if (!args.doRename(res.returnCode, pkgName, oldCodePath)) { res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return; } // Set application objects path explicitly after the rename setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath()); pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath(); if (replace) { replacePackageLI(pkg, parseFlags, scanMode, installerPackageName, res); } else { installNewPackageLI(pkg, parseFlags, scanMode, installerPackageName,res); } }

 

最后判断如果以前不存在那么调用installNewPackageLI()

    

  1. private void installNewPackageLI(PackageParser.Package pkg,  
  2.             int parseFlags,int scanMode,  
  3.             String installerPackageName, PackageInstalledInfo res) {  
  4.      ***********************省略若干*************************************************  
  5.         PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,  
  6.                System.currentTimeMillis());  
  7.      ***********************省略若干**************************************************    
  8. }  
private void installNewPackageLI(PackageParser.Package pkg, int parseFlags,int scanMode, String installerPackageName, PackageInstalledInfo res) { ***********************省略若干************************************************* PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode, System.currentTimeMillis()); ***********************省略若干************************************************** }

最后终于回到了和开机安装一样的地方.与开机方式安装调用统一方法。

三、从ADB工具安装 

其入口函数源文件为pm.java 

(源文件路径:android\frameworks\base\cmds\pm\src\com\android\commands\pm\pm.java)

其中\system\framework\pm.jar 包管理库

包管理脚本 \system\bin\pm 解析

showUsage就是使用方法

  1. private static void showUsage() {   
  2.         System.err.println("usage: pm [list|path|install|uninstall]");   
  3.         System.err.println("       pm list packages [-f]");   
  4.         System.err.println("       pm list permission-groups");   
  5.         System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");   
  6.         System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");   
  7.         System.err.println("       pm list features");   
  8.         System.err.println("       pm path PACKAGE");   
  9.         System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");   
  10.         System.err.println("       pm uninstall [-k] PACKAGE");   
  11.         System.err.println("       pm enable PACKAGE_OR_COMPONENT");   
  12.         System.err.println("       pm disable PACKAGE_OR_COMPONENT");   
  13.         System.err.println("       pm setInstallLocation [0/auto] [1/internal] [2/external]");  
  14.       **********************省略**************************  
  15.    }  
private static void showUsage() { System.err.println("usage: pm [list|path|install|uninstall]"); System.err.println(" pm list packages [-f]"); System.err.println(" pm list permission-groups"); System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]"); System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]"); System.err.println(" pm list features"); System.err.println(" pm path PACKAGE"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); System.err.println(" pm enable PACKAGE_OR_COMPONENT"); System.err.println(" pm disable PACKAGE_OR_COMPONENT"); System.err.println(" pm setInstallLocation [0/auto] [1/internal] [2/external]"); **********************省略************************** }

安装时候会调用 runInstall()方法

  

  1. private void runInstall() {  
  2.       int installFlags = 0;  
  3.       String installerPackageName = null;  
  4.       String opt;  
  5.       while ((opt=nextOption()) != null) {  
  6.           if (opt.equals("-l")) {  
  7.               installFlags |= PackageManager.INSTALL_FORWARD_LOCK;  
  8.           } else if (opt.equals("-r")) {  
  9.               installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;  
  10.           } else if (opt.equals("-i")) {  
  11.               installerPackageName = nextOptionData();  
  12.               if (installerPackageName == null) {  
  13.                   System.err.println("Error: no value specified for -i");  
  14.                   showUsage();  
  15.                   return;  
  16.               }  
  17.           } else if (opt.equals("-t")) {  
  18.               installFlags |= PackageManager.INSTALL_ALLOW_TEST;  
  19.           } else if (opt.equals("-s")) {  
  20.               // Override if -s option is specified.   
  21.               installFlags |= PackageManager.INSTALL_EXTERNAL;  
  22.           } else if (opt.equals("-f")) {  
  23.               // Override if -s option is specified.   
  24.               installFlags |= PackageManager.INSTALL_INTERNAL;  
  25.           } else {  
  26.               System.err.println("Error: Unknown option: " + opt);  
  27.               showUsage();  
  28.               return;  
  29.           }  
  30.       }  
  31.       String apkFilePath = nextArg();  
  32.       System.err.println("\tpkg: " + apkFilePath);  
  33.       if (apkFilePath == null) {  
  34.           System.err.println("Error: no package specified");  
  35.           showUsage();  
  36.           return;  
  37.       }  
  38.       PackageInstallObserver obs = new PackageInstallObserver();  
  39.       try {  
  40.           mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,  
  41.                   installerPackageName);  
  42.           synchronized (obs) {  
  43.               while (!obs.finished) {  
  44.                   try {  
  45.                       obs.wait();  
  46.                   } catch (InterruptedException e) {  
  47.                   }  
  48.               }  
  49.               if (obs.result == PackageManager.INSTALL_SUCCEEDED) {  
  50.                   System.out.println("Success");  
  51.               } else {  
  52.                   System.err.println("Failure ["  
  53.                           + installFailureToString(obs.result)  
  54.                           + "]");  
  55.               }  
  56.           }  
  57.       } catch (RemoteException e) {  
  58.           System.err.println(e.toString());  
  59.           System.err.println(PM_NOT_RUNNING_ERR);  
  60.       }  
  61.   }  
private void runInstall() { int installFlags = 0; String installerPackageName = null; String opt; while ((opt=nextOption()) != null) { if (opt.equals("-l")) { installFlags |= PackageManager.INSTALL_FORWARD_LOCK; } else if (opt.equals("-r")) { installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; } else if (opt.equals("-i")) { installerPackageName = nextOptionData(); if (installerPackageName == null) { System.err.println("Error: no value specified for -i"); showUsage(); return; } } else if (opt.equals("-t")) { installFlags |= PackageManager.INSTALL_ALLOW_TEST; } else if (opt.equals("-s")) { // Override if -s option is specified. installFlags |= PackageManager.INSTALL_EXTERNAL; } else if (opt.equals("-f")) { // Override if -s option is specified. installFlags |= PackageManager.INSTALL_INTERNAL; } else { System.err.println("Error: Unknown option: " + opt); showUsage(); return; } } String apkFilePath = nextArg(); System.err.println("\tpkg: " + apkFilePath); if (apkFilePath == null) { System.err.println("Error: no package specified"); showUsage(); return; } PackageInstallObserver obs = new PackageInstallObserver(); try { mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags, installerPackageName); synchronized (obs) { while (!obs.finished) { try { obs.wait(); } catch (InterruptedException e) { } } if (obs.result == PackageManager.INSTALL_SUCCEEDED) { System.out.println("Success"); } else { System.err.println("Failure [" + installFailureToString(obs.result) + "]"); } } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); } }

其中的   

   

PackageInstallObserver obs = new PackageInstallObserver();

        

            mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,

                    installerPackageName);

如果安装成功

obs.result == PackageManager.INSTALL_SUCCEEDED)

又因为有

IPackageManage mPm;

        mPm = IpackageManager.Stub.asInterface(ServiceManager.getService("package"));

Stub是接口IPackageManage的静态抽象类,asInterface是返回IPackageManager代理的静态方法。

因为class PackageManagerService extends IPackageManager.Stub

所以mPm.installPackage 调用 

    /* Called when a downloaded package installation has been confirmed by the user */

    public void installPackage(

            final Uri packageURI, final IPackageInstallObserver observer, final int flags,final String installerPackageName) 

这样就是从网络下载安装的入口了。

四,从SD卡安装

系统调用PackageInstallerActivity.java(/home/zhongda/androidSRC/vortex-8inch-for-hoperun/packages/apps/PackageInstaller/src/com/android/packageinstaller)

进入这个Activity会判断信息是否有错,然后调用

      private void initiateInstall()判断是否曾经有过同名包的安装,或者包已经安装

通过后执行private void startInstallConfirm() 点击OK按钮后经过一系列的安装信息的判断Intent跳转到

  1. public class InstallAppProgress extends Activity implements View.OnClickListener, OnCancelListener  
  2.    public void onCreate(Bundle icicle) {  
  3.         super.onCreate(icicle);  
  4.         Intent intent = getIntent();  
  5.         mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);  
  6.         mPackageURI = intent.getData();  
  7.         initView();  
  8.     }  
public class InstallAppProgress extends Activity implements View.OnClickListener, OnCancelListener public void onCreate(Bundle icicle) { super.onCreate(icicle); Intent intent = getIntent(); mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO); mPackageURI = intent.getData(); initView(); }

方法中调用了initView()方法

   

  1. public void initView() {  
  2.        requestWindowFeature(Window.FEATURE_NO_TITLE);  
  3.        setContentView(R.layout.op_progress);  
  4.        int installFlags = 0;  
  5.        PackageManager pm = getPackageManager();  
  6.        try {  
  7.            PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName,   
  8.                    PackageManager.GET_UNINSTALLED_PACKAGES);  
  9.            if(pi != null) {  
  10.                installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;  
  11.            }  
  12.        } catch (NameNotFoundException e) {  
  13.        }  
  14.        if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) {  
  15.            Log.w(TAG, "Replacing package:" + mAppInfo.packageName);  
  16.        }  
  17.        PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mAppInfo,  
  18.                mPackageURI);  
  19.        mLabel = as.label;  
  20.        PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);  
  21.        mStatusTextView = (TextView)findViewById(R.id.center_text);  
  22.        mStatusTextView.setText(R.string.installing);  
  23.        mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);  
  24.        mProgressBar.setIndeterminate(true);  
  25.        // Hide button till progress is being displayed   
  26.        mOkPanel = (View)findViewById(R.id.buttons_panel);  
  27.        mDoneButton = (Button)findViewById(R.id.done_button);  
  28.        mLaunchButton = (Button)findViewById(R.id.launch_button);  
  29.        mOkPanel.setVisibility(View.INVISIBLE);  
  30.        String installerPackageName = getIntent().getStringExtra(  
  31.                Intent.EXTRA_INSTALLER_PACKAGE_NAME);  
  32.        PackageInstallObserver observer = new PackageInstallObserver();  
  33.        pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);  
  34.    }  
public void initView() { requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.op_progress); int installFlags = 0; PackageManager pm = getPackageManager(); try { PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName, PackageManager.GET_UNINSTALLED_PACKAGES); if(pi != null) { installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; } } catch (NameNotFoundException e) { } if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) { Log.w(TAG, "Replacing package:" + mAppInfo.packageName); } PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mAppInfo, mPackageURI); mLabel = as.label; PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet); mStatusTextView = (TextView)findViewById(R.id.center_text); mStatusTextView.setText(R.string.installing); mProgressBar = (ProgressBar) findViewById(R.id.progress_bar); mProgressBar.setIndeterminate(true); // Hide button till progress is being displayed mOkPanel = (View)findViewById(R.id.buttons_panel); mDoneButton = (Button)findViewById(R.id.done_button); mLaunchButton = (Button)findViewById(R.id.launch_button); mOkPanel.setVisibility(View.INVISIBLE); String installerPackageName = getIntent().getStringExtra( Intent.EXTRA_INSTALLER_PACKAGE_NAME); PackageInstallObserver observer = new PackageInstallObserver(); pm.installPackage(mPackageURI, observer, installFlags, installerPackageName); }




方法最后我们可以看到再次调用安装接口完成安装。

posted @ 2012-07-02 13:57 00000000O 阅读( ...) 评论( ...) 编辑 收藏
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐