APK安装过程及原理详解

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

APK为AndroidPackage的缩写

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

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

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

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

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

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

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

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. //Findbaseframeworks(resourcepackageswithoutcode).
  2. mFrameworkInstallObserver=newAppDirObserver(
  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. //Collectallsystempackages.
  2. mSystemAppDir=newFile(Environment.getRootDirectory(),"app");
  3. mSystemInstallObserver=newAppDirObserver(
  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. //Collectallvendorpackages.
  2. mVendorAppDir=newFile("/vendor/app");
  3. mVendorInstallObserver=newAppDirObserver(
  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. privatevoidscanDirLI(Filedir,intflags,intscanMode,longcurrentTime){
  2. String[]files=dir.list();
  3. if(files==null){
  4. Log.d(TAG,"Nofilesinappdir"+dir);
  5. return;
  6. }
  7. if(false){
  8. Log.d(TAG,"Scanningappdir"+dir);
  9. }
  10. inti;
  11. for(i=0;i<files.length;i++){
  12. Filefile=newFile(dir,files[i]);
  13. if(!isPackageFilename(files[i])){
  14. //Ignoreentrieswhicharenotapk's
  15. continue;
  16. }
  17. PackageParser.Packagepkg=scanPackageLI(file,
  18. flags|PackageParser.PARSE_MUST_BE_APK,scanMode,currentTime);
  19. //Don'tmessaroundwithappsinsystempartition.
  20. if(pkg==null&&(flags&PackageParser.PARSE_IS_SYSTEM)==0&&
  21. mLastScanError==PackageManager.INSTALL_FAILED_INVALID_APK){
  22. //Deletetheapk
  23. Slog.w(TAG,"Cleaningupfailedinstallof"+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()

privatePackageParser.PackagescanPackageLI(FilescanFile,

intparseFlags,intscanMode,longcurrentTime)

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

  1. if(mInstaller!=null){
  2. intret=mInstaller.install(pkgName,useEncryptedFSDir,pkg.applicationInfo.uid,pkg.applicationInfo.uid);
  3. if(ret<0){
  4. //Errorfrominstaller
  5. mLastScanError=PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
  6. returnnull;
  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()通过

LocalSocketAddressaddress=newLocalSocketAddress(

"installd",LocalSocketAddress.Namespace.RESERVED);

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

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

二、从网络上下载应用:

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

/*Calledwhenadownloadedpackageinstallationhasbeenconfirmedbytheuser*/

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

  1. publicvoidinstallPackage(
  2. finalUripackageURI,finalIPackageInstallObserverobserver,finalintflags,
  3. finalStringinstallerPackageName){
  4. mContext.enforceCallingOrSelfPermission(
  5. android.Manifest.permission.INSTALL_PACKAGES,null);
  6. Messagemsg=mHandler.obtainMessage(INIT_COPY);
  7. msg.obj=newInstallParams(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. classPackageHandlerextendsHandler{
  2. *****************省略若干********************
  3. publicvoidhandleMessage(Messagemsg){
  4. try{
  5. doHandleMessage(msg);
  6. }finally{
  7. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  8. }
  9. }
  10. ******************省略若干**********************
  11. }
class PackageHandler extends Handler{ *****************省略若干******************** public void handleMessage(Message msg) { try { doHandleMessage(msg); } finally { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } } ******************省略若干********************** }

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

  1. voiddoHandleMessage(Messagemsg){
  2. switch(msg.what){
  3. caseINIT_COPY:{
  4. if(DEBUG_SD_INSTALL)Log.i(TAG,"init_copy");
  5. HandlerParamsparams=(HandlerParams)msg.obj;
  6. intidx=mPendingInstalls.size();
  7. if(DEBUG_SD_INSTALL)Log.i(TAG,"idx="+idx);
  8. //Ifabindwasalreadyinitiatedwedontreally
  9. //needtodoanything.Thependinginstall
  10. //willbeprocessedlateron.
  11. if(!mBound){
  12. //Ifthisistheonlyonependingwemight
  13. //havetobindtotheserviceagain.
  14. if(!connectToService()){
  15. Slog.e(TAG,"Failedtobindtomediacontainerservice");
  16. params.serviceError();
  17. return;
  18. }else{
  19. //Oncewebindtotheservice,thefirst
  20. //pendingrequestwillbeprocessed.
  21. mPendingInstalls.add(idx,params);
  22. }
  23. }else{
  24. mPendingInstalls.add(idx,params);
  25. //Alreadyboundtotheservice.Justmake
  26. //surewetriggeroffprocessingthefirstrequest.
  27. if(idx==0){
  28. mHandler.sendEmptyMessage(MCS_BOUND);
  29. }
  30. }
  31. break;
  32. }
  33. caseMCS_BOUND:{
  34. if(DEBUG_SD_INSTALL)Log.i(TAG,"mcs_bound");
  35. if(msg.obj!=null){
  36. mContainerService=(IMediaContainerService)msg.obj;
  37. }
  38. if(mContainerService==null){
  39. //Somethingseriouslywrong.Bailout
  40. Slog.e(TAG,"Cannotbindtomediacontainerservice");
  41. for(HandlerParamsparams:mPendingInstalls){
  42. mPendingInstalls.remove(0);
  43. //Indicateservicebinderror
  44. params.serviceError();
  45. }
  46. mPendingInstalls.clear();
  47. }elseif(mPendingInstalls.size()>0){
  48. HandlerParamsparams=mPendingInstalls.get(0);
  49. if(params!=null){
  50. params.startCopy();
  51. }
  52. }else{
  53. //Shouldneverhappenideally.
  54. Slog.w(TAG,"Emptyqueue");
  55. }
  56. break;
  57. }
  58. ****************省略若干**********************
  59. }
  60. }
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; } ****************省略若干********************** } }

publicfinalbooleansendMessage(Messagemsg)

publicfinalbooleansendEmptyMessage(intwhat)

两者参数有别。

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

abstractclassHandlerParams{

finalvoidstartCopy(){

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

handleReturnCode();

}
}

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

  1. @Override
  2. voidhandleReturnCode(){
  3. //IfmArgsisnull,thenMCScouldn'tbereached.Whenit
  4. //reconnects,itwilltryagaintoinstall.Atthatpoint,this
  5. //willsucceed.
  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. instaPacakgeLI()args,res参数分析
run(){ synchronized (mInstallLock) { ************省略***************** installPackageLI(args, true, res); } } instaPacakgeLI()args,res参数分析

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

//InstallArgs是在PackageService定义的staticabstractclassInstallArgs静态抽象类。

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

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

  1. privatevoidinstallPackageLI(InstallArgsargs,
  2. booleannewInstall,PackageInstalledInfores){
  3. intpFlags=args.flags;
  4. StringinstallerPackageName=args.installerPackageName;
  5. FiletmpPackageFile=newFile(args.getCodePath());
  6. booleanforwardLocked=((pFlags&PackageManager.INSTALL_FORWARD_LOCK)!=0);
  7. booleanonSd=((pFlags&PackageManager.INSTALL_EXTERNAL)!=0);
  8. booleanreplace=false;
  9. intscanMode=(onSd?0:SCAN_MONITOR)|SCAN_FORCE_DEX|SCAN_UPDATE_SIGNATURE
  10. |(newInstall?SCAN_NEW_INSTALL:0);
  11. //Resultobjecttobereturned
  12. res.returnCode=PackageManager.INSTALL_SUCCEEDED;
  13. //RetrievePackageSettingsandparsepackage
  14. intparseFlags=PackageParser.PARSE_CHATTY|
  15. (forwardLocked?PackageParser.PARSE_FORWARD_LOCK:0)|
  16. (onSd?PackageParser.PARSE_ON_SDCARD:0);
  17. parseFlags|=mDefParseFlags;
  18. PackageParserpp=newPackageParser(tmpPackageFile.getPath());
  19. pp.setSeparateProcesses(mSeparateProcesses);
  20. finalPackageParser.Packagepkg=pp.parsePackage(tmpPackageFile,
  21. null,mMetrics,parseFlags);
  22. if(pkg==null){
  23. res.returnCode=pp.getParseError();
  24. return;
  25. }
  26. StringpkgName=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. //Getridofallreferencestopackagescanpathviaparser.
  38. pp=null;
  39. StringoldCodePath=null;
  40. booleansystemApp=false;
  41. synchronized(mPackages){
  42. //Checkifinstallingalreadyexistingpackage
  43. if((pFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
  44. StringoldName=mSettings.mRenamedPackages.get(pkgName);
  45. if(pkg.mOriginalPackages!=null
  46. &&pkg.mOriginalPackages.contains(oldName)
  47. &&mPackages.containsKey(oldName)){
  48. //Thispackageisderivedfromanoriginalpackage,
  49. //andthisdevicehasbeenupdatingfromthatoriginal
  50. //name.Wemustcontinueusingtheoriginalname,so
  51. //renamethenewpackagehere.
  52. pkg.setPackageName(oldName);
  53. pkgName=pkg.packageName;
  54. replace=true;
  55. }elseif(mPackages.containsKey(pkgName)){
  56. //Thispackage,underitsofficialname,alreadyexists
  57. //onthedevice;weshouldreplaceit.
  58. replace=true;
  59. }
  60. }
  61. PackageSettingps=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. //Disableupdatestosystemappsonsdcard
  72. Slog.w(TAG,"Cannotinstallupdatestosystemappsonsdcard");
  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. //Setapplicationobjectspathexplicitlyaftertherename
  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. privatevoidinstallNewPackageLI(PackageParser.Packagepkg,
  2. intparseFlags,intscanMode,
  3. StringinstallerPackageName,PackageInstalledInfores){
  4. ***********************省略若干*************************************************
  5. PackageParser.PackagenewPackage=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. privatestaticvoidshowUsage(){
  2. System.err.println("usage:pm[list|path|install|uninstall]");
  3. System.err.println("pmlistpackages[-f]");
  4. System.err.println("pmlistpermission-groups");
  5. System.err.println("pmlistpermissions[-g][-f][-d][-u][GROUP]");
  6. System.err.println("pmlistinstrumentation[-f][TARGET-PACKAGE]");
  7. System.err.println("pmlistfeatures");
  8. System.err.println("pmpathPACKAGE");
  9. System.err.println("pminstall[-l][-r][-t][-iINSTALLER_PACKAGE_NAME][-s][-f]PATH");
  10. System.err.println("pmuninstall[-k]PACKAGE");
  11. System.err.println("pmenablePACKAGE_OR_COMPONENT");
  12. System.err.println("pmdisablePACKAGE_OR_COMPONENT");
  13. System.err.println("pmsetInstallLocation[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. privatevoidrunInstall(){
  2. intinstallFlags=0;
  3. StringinstallerPackageName=null;
  4. Stringopt;
  5. while((opt=nextOption())!=null){
  6. if(opt.equals("-l")){
  7. installFlags|=PackageManager.INSTALL_FORWARD_LOCK;
  8. }elseif(opt.equals("-r")){
  9. installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
  10. }elseif(opt.equals("-i")){
  11. installerPackageName=nextOptionData();
  12. if(installerPackageName==null){
  13. System.err.println("Error:novaluespecifiedfor-i");
  14. showUsage();
  15. return;
  16. }
  17. }elseif(opt.equals("-t")){
  18. installFlags|=PackageManager.INSTALL_ALLOW_TEST;
  19. }elseif(opt.equals("-s")){
  20. //Overrideif-soptionisspecified.
  21. installFlags|=PackageManager.INSTALL_EXTERNAL;
  22. }elseif(opt.equals("-f")){
  23. //Overrideif-soptionisspecified.
  24. installFlags|=PackageManager.INSTALL_INTERNAL;
  25. }else{
  26. System.err.println("Error:Unknownoption:"+opt);
  27. showUsage();
  28. return;
  29. }
  30. }
  31. StringapkFilePath=nextArg();
  32. System.err.println("\tpkg:"+apkFilePath);
  33. if(apkFilePath==null){
  34. System.err.println("Error:nopackagespecified");
  35. showUsage();
  36. return;
  37. }
  38. PackageInstallObserverobs=newPackageInstallObserver();
  39. try{
  40. mPm.installPackage(Uri.fromFile(newFile(apkFilePath)),obs,installFlags,
  41. installerPackageName);
  42. synchronized(obs){
  43. while(!obs.finished){
  44. try{
  45. obs.wait();
  46. }catch(InterruptedExceptione){
  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(RemoteExceptione){
  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); } }

其中的

PackageInstallObserverobs=newPackageInstallObserver();

mPm.installPackage(Uri.fromFile(newFile(apkFilePath)),obs,installFlags,

installerPackageName);

如果安装成功

obs.result==PackageManager.INSTALL_SUCCEEDED)

又因为有

IPackageManagemPm;

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

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

因为classPackageManagerServiceextendsIPackageManager.Stub

所以mPm.installPackage调用

/*Calledwhenadownloadedpackageinstallationhasbeenconfirmedbytheuser*/

publicvoidinstallPackage(

finalUripackageURI,finalIPackageInstallObserverobserver,finalintflags,finalStringinstallerPackageName)

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

四,从SD卡安装

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

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

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

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

  1. publicclassInstallAppProgressextendsActivityimplementsView.OnClickListener,OnCancelListener
  2. publicvoidonCreate(Bundleicicle){
  3. super.onCreate(icicle);
  4. Intentintent=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. publicvoidinitView(){
  2. requestWindowFeature(Window.FEATURE_NO_TITLE);
  3. setContentView(R.layout.op_progress);
  4. intinstallFlags=0;
  5. PackageManagerpm=getPackageManager();
  6. try{
  7. PackageInfopi=pm.getPackageInfo(mAppInfo.packageName,
  8. PackageManager.GET_UNINSTALLED_PACKAGES);
  9. if(pi!=null){
  10. installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
  11. }
  12. }catch(NameNotFoundExceptione){
  13. }
  14. if((installFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
  15. Log.w(TAG,"Replacingpackage:"+mAppInfo.packageName);
  16. }
  17. PackageUtil.AppSnippetas=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. //Hidebuttontillprogressisbeingdisplayed
  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. StringinstallerPackageName=getIntent().getStringExtra(
  31. Intent.EXTRA_INSTALLER_PACKAGE_NAME);
  32. PackageInstallObserverobserver=newPackageInstallObserver();
  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); }



APK为AndroidPackage的缩写

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

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

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

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

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

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

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

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. //Findbaseframeworks(resourcepackageswithoutcode).
  2. mFrameworkInstallObserver=newAppDirObserver(
  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. //Collectallsystempackages.
  2. mSystemAppDir=newFile(Environment.getRootDirectory(),"app");
  3. mSystemInstallObserver=newAppDirObserver(
  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. //Collectallvendorpackages.
  2. mVendorAppDir=newFile("/vendor/app");
  3. mVendorInstallObserver=newAppDirObserver(
  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. privatevoidscanDirLI(Filedir,intflags,intscanMode,longcurrentTime){
  2. String[]files=dir.list();
  3. if(files==null){
  4. Log.d(TAG,"Nofilesinappdir"+dir);
  5. return;
  6. }
  7. if(false){
  8. Log.d(TAG,"Scanningappdir"+dir);
  9. }
  10. inti;
  11. for(i=0;i<files.length;i++){
  12. Filefile=newFile(dir,files[i]);
  13. if(!isPackageFilename(files[i])){
  14. //Ignoreentrieswhicharenotapk's
  15. continue;
  16. }
  17. PackageParser.Packagepkg=scanPackageLI(file,
  18. flags|PackageParser.PARSE_MUST_BE_APK,scanMode,currentTime);
  19. //Don'tmessaroundwithappsinsystempartition.
  20. if(pkg==null&&(flags&PackageParser.PARSE_IS_SYSTEM)==0&&
  21. mLastScanError==PackageManager.INSTALL_FAILED_INVALID_APK){
  22. //Deletetheapk
  23. Slog.w(TAG,"Cleaningupfailedinstallof"+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()

privatePackageParser.PackagescanPackageLI(FilescanFile,

intparseFlags,intscanMode,longcurrentTime)

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

  1. if(mInstaller!=null){
  2. intret=mInstaller.install(pkgName,useEncryptedFSDir,pkg.applicationInfo.uid,pkg.applicationInfo.uid);
  3. if(ret<0){
  4. //Errorfrominstaller
  5. mLastScanError=PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
  6. returnnull;
  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()通过

LocalSocketAddressaddress=newLocalSocketAddress(

"installd",LocalSocketAddress.Namespace.RESERVED);

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

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

二、从网络上下载应用:

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

/*Calledwhenadownloadedpackageinstallationhasbeenconfirmedbytheuser*/

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

  1. publicvoidinstallPackage(
  2. finalUripackageURI,finalIPackageInstallObserverobserver,finalintflags,
  3. finalStringinstallerPackageName){
  4. mContext.enforceCallingOrSelfPermission(
  5. android.Manifest.permission.INSTALL_PACKAGES,null);
  6. Messagemsg=mHandler.obtainMessage(INIT_COPY);
  7. msg.obj=newInstallParams(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. classPackageHandlerextendsHandler{
  2. *****************省略若干********************
  3. publicvoidhandleMessage(Messagemsg){
  4. try{
  5. doHandleMessage(msg);
  6. }finally{
  7. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  8. }
  9. }
  10. ******************省略若干**********************
  11. }
class PackageHandler extends Handler{ *****************省略若干******************** public void handleMessage(Message msg) { try { doHandleMessage(msg); } finally { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } } ******************省略若干********************** }

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

  1. voiddoHandleMessage(Messagemsg){
  2. switch(msg.what){
  3. caseINIT_COPY:{
  4. if(DEBUG_SD_INSTALL)Log.i(TAG,"init_copy");
  5. HandlerParamsparams=(HandlerParams)msg.obj;
  6. intidx=mPendingInstalls.size();
  7. if(DEBUG_SD_INSTALL)Log.i(TAG,"idx="+idx);
  8. //Ifabindwasalreadyinitiatedwedontreally
  9. //needtodoanything.Thependinginstall
  10. //willbeprocessedlateron.
  11. if(!mBound){
  12. //Ifthisistheonlyonependingwemight
  13. //havetobindtotheserviceagain.
  14. if(!connectToService()){
  15. Slog.e(TAG,"Failedtobindtomediacontainerservice");
  16. params.serviceError();
  17. return;
  18. }else{
  19. //Oncewebindtotheservice,thefirst
  20. //pendingrequestwillbeprocessed.
  21. mPendingInstalls.add(idx,params);
  22. }
  23. }else{
  24. mPendingInstalls.add(idx,params);
  25. //Alreadyboundtotheservice.Justmake
  26. //surewetriggeroffprocessingthefirstrequest.
  27. if(idx==0){
  28. mHandler.sendEmptyMessage(MCS_BOUND);
  29. }
  30. }
  31. break;
  32. }
  33. caseMCS_BOUND:{
  34. if(DEBUG_SD_INSTALL)Log.i(TAG,"mcs_bound");
  35. if(msg.obj!=null){
  36. mContainerService=(IMediaContainerService)msg.obj;
  37. }
  38. if(mContainerService==null){
  39. //Somethingseriouslywrong.Bailout
  40. Slog.e(TAG,"Cannotbindtomediacontainerservice");
  41. for(HandlerParamsparams:mPendingInstalls){
  42. mPendingInstalls.remove(0);
  43. //Indicateservicebinderror
  44. params.serviceError();
  45. }
  46. mPendingInstalls.clear();
  47. }elseif(mPendingInstalls.size()>0){
  48. HandlerParamsparams=mPendingInstalls.get(0);
  49. if(params!=null){
  50. params.startCopy();
  51. }
  52. }else{
  53. //Shouldneverhappenideally.
  54. Slog.w(TAG,"Emptyqueue");
  55. }
  56. break;
  57. }
  58. ****************省略若干**********************
  59. }
  60. }
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; } ****************省略若干********************** } }

publicfinalbooleansendMessage(Messagemsg)

publicfinalbooleansendEmptyMessage(intwhat)

两者参数有别。

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

abstractclassHandlerParams{

finalvoidstartCopy(){

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

handleReturnCode();

}
}

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

  1. @Override
  2. voidhandleReturnCode(){
  3. //IfmArgsisnull,thenMCScouldn'tbereached.Whenit
  4. //reconnects,itwilltryagaintoinstall.Atthatpoint,this
  5. //willsucceed.
  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. instaPacakgeLI()args,res参数分析
run(){ synchronized (mInstallLock) { ************省略***************** installPackageLI(args, true, res); } } instaPacakgeLI()args,res参数分析

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

//InstallArgs是在PackageService定义的staticabstractclassInstallArgs静态抽象类。

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

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

  1. privatevoidinstallPackageLI(InstallArgsargs,
  2. booleannewInstall,PackageInstalledInfores){
  3. intpFlags=args.flags;
  4. StringinstallerPackageName=args.installerPackageName;
  5. FiletmpPackageFile=newFile(args.getCodePath());
  6. booleanforwardLocked=((pFlags&PackageManager.INSTALL_FORWARD_LOCK)!=0);
  7. booleanonSd=((pFlags&PackageManager.INSTALL_EXTERNAL)!=0);
  8. booleanreplace=false;
  9. intscanMode=(onSd?0:SCAN_MONITOR)|SCAN_FORCE_DEX|SCAN_UPDATE_SIGNATURE
  10. |(newInstall?SCAN_NEW_INSTALL:0);
  11. //Resultobjecttobereturned
  12. res.returnCode=PackageManager.INSTALL_SUCCEEDED;
  13. //RetrievePackageSettingsandparsepackage
  14. intparseFlags=PackageParser.PARSE_CHATTY|
  15. (forwardLocked?PackageParser.PARSE_FORWARD_LOCK:0)|
  16. (onSd?PackageParser.PARSE_ON_SDCARD:0);
  17. parseFlags|=mDefParseFlags;
  18. PackageParserpp=newPackageParser(tmpPackageFile.getPath());
  19. pp.setSeparateProcesses(mSeparateProcesses);
  20. finalPackageParser.Packagepkg=pp.parsePackage(tmpPackageFile,
  21. null,mMetrics,parseFlags);
  22. if(pkg==null){
  23. res.returnCode=pp.getParseError();
  24. return;
  25. }
  26. StringpkgName=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. //Getridofallreferencestopackagescanpathviaparser.
  38. pp=null;
  39. StringoldCodePath=null;
  40. booleansystemApp=false;
  41. synchronized(mPackages){
  42. //Checkifinstallingalreadyexistingpackage
  43. if((pFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
  44. StringoldName=mSettings.mRenamedPackages.get(pkgName);
  45. if(pkg.mOriginalPackages!=null
  46. &&pkg.mOriginalPackages.contains(oldName)
  47. &&mPackages.containsKey(oldName)){
  48. //Thispackageisderivedfromanoriginalpackage,
  49. //andthisdevicehasbeenupdatingfromthatoriginal
  50. //name.Wemustcontinueusingtheoriginalname,so
  51. //renamethenewpackagehere.
  52. pkg.setPackageName(oldName);
  53. pkgName=pkg.packageName;
  54. replace=true;
  55. }elseif(mPackages.containsKey(pkgName)){
  56. //Thispackage,underitsofficialname,alreadyexists
  57. //onthedevice;weshouldreplaceit.
  58. replace=true;
  59. }
  60. }
  61. PackageSettingps=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. //Disableupdatestosystemappsonsdcard
  72. Slog.w(TAG,"Cannotinstallupdatestosystemappsonsdcard");
  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. //Setapplicationobjectspathexplicitlyaftertherename
  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. privatevoidinstallNewPackageLI(PackageParser.Packagepkg,
  2. intparseFlags,intscanMode,
  3. StringinstallerPackageName,PackageInstalledInfores){
  4. ***********************省略若干*************************************************
  5. PackageParser.PackagenewPackage=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. privatestaticvoidshowUsage(){
  2. System.err.println("usage:pm[list|path|install|uninstall]");
  3. System.err.println("pmlistpackages[-f]");
  4. System.err.println("pmlistpermission-groups");
  5. System.err.println("pmlistpermissions[-g][-f][-d][-u][GROUP]");
  6. System.err.println("pmlistinstrumentation[-f][TARGET-PACKAGE]");
  7. System.err.println("pmlistfeatures");
  8. System.err.println("pmpathPACKAGE");
  9. System.err.println("pminstall[-l][-r][-t][-iINSTALLER_PACKAGE_NAME][-s][-f]PATH");
  10. System.err.println("pmuninstall[-k]PACKAGE");
  11. System.err.println("pmenablePACKAGE_OR_COMPONENT");
  12. System.err.println("pmdisablePACKAGE_OR_COMPONENT");
  13. System.err.println("pmsetInstallLocation[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. privatevoidrunInstall(){
  2. intinstallFlags=0;
  3. StringinstallerPackageName=null;
  4. Stringopt;
  5. while((opt=nextOption())!=null){
  6. if(opt.equals("-l")){
  7. installFlags|=PackageManager.INSTALL_FORWARD_LOCK;
  8. }elseif(opt.equals("-r")){
  9. installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
  10. }elseif(opt.equals("-i")){
  11. installerPackageName=nextOptionData();
  12. if(installerPackageName==null){
  13. System.err.println("Error:novaluespecifiedfor-i");
  14. showUsage();
  15. return;
  16. }
  17. }elseif(opt.equals("-t")){
  18. installFlags|=PackageManager.INSTALL_ALLOW_TEST;
  19. }elseif(opt.equals("-s")){
  20. //Overrideif-soptionisspecified.
  21. installFlags|=PackageManager.INSTALL_EXTERNAL;
  22. }elseif(opt.equals("-f")){
  23. //Overrideif-soptionisspecified.
  24. installFlags|=PackageManager.INSTALL_INTERNAL;
  25. }else{
  26. System.err.println("Error:Unknownoption:"+opt);
  27. showUsage();
  28. return;
  29. }
  30. }
  31. StringapkFilePath=nextArg();
  32. System.err.println("\tpkg:"+apkFilePath);
  33. if(apkFilePath==null){
  34. System.err.println("Error:nopackagespecified");
  35. showUsage();
  36. return;
  37. }
  38. PackageInstallObserverobs=newPackageInstallObserver();
  39. try{
  40. mPm.installPackage(Uri.fromFile(newFile(apkFilePath)),obs,installFlags,
  41. installerPackageName);
  42. synchronized(obs){
  43. while(!obs.finished){
  44. try{
  45. obs.wait();
  46. }catch(InterruptedExceptione){
  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(RemoteExceptione){
  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); } }

其中的

PackageInstallObserverobs=newPackageInstallObserver();

mPm.installPackage(Uri.fromFile(newFile(apkFilePath)),obs,installFlags,

installerPackageName);

如果安装成功

obs.result==PackageManager.INSTALL_SUCCEEDED)

又因为有

IPackageManagemPm;

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

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

因为classPackageManagerServiceextendsIPackageManager.Stub

所以mPm.installPackage调用

/*Calledwhenadownloadedpackageinstallationhasbeenconfirmedbytheuser*/

publicvoidinstallPackage(

finalUripackageURI,finalIPackageInstallObserverobserver,finalintflags,finalStringinstallerPackageName)

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

四,从SD卡安装

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

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

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

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

  1. publicclassInstallAppProgressextendsActivityimplementsView.OnClickListener,OnCancelListener
  2. publicvoidonCreate(Bundleicicle){
  3. super.onCreate(icicle);
  4. Intentintent=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. publicvoidinitView(){
  2. requestWindowFeature(Window.FEATURE_NO_TITLE);
  3. setContentView(R.layout.op_progress);
  4. intinstallFlags=0;
  5. PackageManagerpm=getPackageManager();
  6. try{
  7. PackageInfopi=pm.getPackageInfo(mAppInfo.packageName,
  8. PackageManager.GET_UNINSTALLED_PACKAGES);
  9. if(pi!=null){
  10. installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
  11. }
  12. }catch(NameNotFoundExceptione){
  13. }
  14. if((installFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
  15. Log.w(TAG,"Replacingpackage:"+mAppInfo.packageName);
  16. }
  17. PackageUtil.AppSnippetas=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. //Hidebuttontillprogressisbeingdisplayed
  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. StringinstallerPackageName=getIntent().getStringExtra(
  31. Intent.EXTRA_INSTALLER_PACKAGE_NAME);
  32. PackageInstallObserverobserver=newPackageInstallObserver();
  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); }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值