Android APK安装过程及原理详解
FROM:http://blog.csdn.net/hdhd588/article/details/6739281
=============================================================
应用程序包的安装是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包
[java] view plain copy- //Findbaseframeworks(resourcepackageswithoutcode).
- mFrameworkInstallObserver=newAppDirObserver(
- 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的应用程序
[java] view plain copy- //Collectallsystempackages.
- mSystemAppDir=newFile(Environment.getRootDirectory(),"app");
- mSystemInstallObserver=newAppDirObserver(
- mSystemAppDir.getPath(),OBSERVER_EVENTS,true);
- mSystemInstallObserver.startWatching();
- scanDirLI(mSystemAppDir,PackageParser.PARSE_IS_SYSTEM
- |PackageParser.PARSE_IS_SYSTEM_DIR,scanMode,0);
3.制造商的目录下/vendor/app应用包
[java] view plain copy- //Collectallvendorpackages.
- mVendorAppDir=newFile("/vendor/app");
- mVendorInstallObserver=newAppDirObserver(
- mVendorAppDir.getPath(),OBSERVER_EVENTS,true);
- mVendorInstallObserver.startWatching();
- scanDirLI(mVendorAppDir,PackageParser.PARSE_IS_SYSTEM
- |PackageParser.PARSE_IS_SYSTEM_DIR,scanMode,0);
4.扫描“data\app”目录,即用户安装的第三方应用
[java] view plain copy
- scanDirLI(mAppInstallDir,0,scanMode,0);
5.扫描"data\app-private"目录,即安装DRM保护的APK文件(一个受保护的歌曲或受保 护的视频是使用DRM保护的文件)
[java] view plain copy
- scanDirLI(mDrmAppPrivateInstallDir,PackageParser.PARSE_FORWARD_LOCK,
- scanMode,0);
扫描方法的代码清单
[java] view plain copy
- privatevoidscanDirLI(Filedir,intflags,intscanMode,longcurrentTime){
- String[]files=dir.list();
- if(files==null){
- Log.d(TAG,"Nofilesinappdir"+dir);
- return;
- }
- if(false){
- Log.d(TAG,"Scanningappdir"+dir);
- }
- inti;
- for(i=0;i<files.length;i++){
- Filefile=newFile(dir,files[i]);
- if(!isPackageFilename(files[i])){
- //Ignoreentrieswhicharenotapk's
- continue;
- }
- PackageParser.Packagepkg=scanPackageLI(file,
- flags|PackageParser.PARSE_MUST_BE_APK,scanMode,currentTime);
- //Don'tmessaroundwithappsinsystempartition.
- if(pkg==null&&(flags&PackageParser.PARSE_IS_SYSTEM)==0&&
- mLastScanError==PackageManager.INSTALL_FAILED_INVALID_APK){
- //Deletetheapk
- Slog.w(TAG,"Cleaningupfailedinstallof"+file);
- file.delete();
- }
- }
- }
并且从该扫描方法中可以看出调用了scanPackageLI()
privatePackageParser.PackagescanPackageLI(FilescanFile,
intparseFlags,intscanMode,longcurrentTime)
跟踪scanPackageLI()方法后发现,程序经过很多次的ifelse的筛选,最后判定可以安装后调用了mInstaller.install
[java] view plain copy
- if(mInstaller!=null){
- intret=mInstaller.install(pkgName,useEncryptedFSDir,pkg.applicationInfo.uid,pkg.applicationInfo.uid);
- if(ret<0){
- //Errorfrominstaller
- mLastScanError=PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- returnnull;
- }
- }
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()函数为安装程序入口。
[java] view plain copy- publicvoidinstallPackage(
- finalUripackageURI,finalIPackageInstallObserverobserver,finalintflags,
- finalStringinstallerPackageName){
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INSTALL_PACKAGES,null);
- Messagemsg=mHandler.obtainMessage(INIT_COPY);
- msg.obj=newInstallParams(packageURI,observer,flags,
- installerPackageName);
- mHandler.sendMessage(msg);
- }
其中是通过PackageHandler的实例mhandler.sendMessage(msg)把信息发给继承Handler的类HandleMessage()方法
[java] view plain copy
- classPackageHandlerextendsHandler{
- *****************省略若干********************
- publicvoidhandleMessage(Messagemsg){
- try{
- doHandleMessage(msg);
- }finally{
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- }
- }
- ******************省略若干**********************
- }
把信息发给doHandleMessage()方法,方法中用switch()语句进行判定传来Message
[java] view plain copy- voiddoHandleMessage(Messagemsg){
- switch(msg.what){
- caseINIT_COPY:{
- if(DEBUG_SD_INSTALL)Log.i(TAG,"init_copy");
- HandlerParamsparams=(HandlerParams)msg.obj;
- intidx=mPendingInstalls.size();
- if(DEBUG_SD_INSTALL)Log.i(TAG,"idx="+idx);
- //Ifabindwasalreadyinitiatedwedontreally
- //needtodoanything.Thependinginstall
- //willbeprocessedlateron.
- if(!mBound){
- //Ifthisistheonlyonependingwemight
- //havetobindtotheserviceagain.
- if(!connectToService()){
- Slog.e(TAG,"Failedtobindtomediacontainerservice");
- params.serviceError();
- return;
- }else{
- //Oncewebindtotheservice,thefirst
- //pendingrequestwillbeprocessed.
- mPendingInstalls.add(idx,params);
- }
- }else{
- mPendingInstalls.add(idx,params);
- //Alreadyboundtotheservice.Justmake
- //surewetriggeroffprocessingthefirstrequest.
- if(idx==0){
- mHandler.sendEmptyMessage(MCS_BOUND);
- }
- }
- break;
- }
- caseMCS_BOUND:{
- if(DEBUG_SD_INSTALL)Log.i(TAG,"mcs_bound");
- if(msg.obj!=null){
- mContainerService=(IMediaContainerService)msg.obj;
- }
- if(mContainerService==null){
- //Somethingseriouslywrong.Bailout
- Slog.e(TAG,"Cannotbindtomediacontainerservice");
- for(HandlerParamsparams:mPendingInstalls){
- mPendingInstalls.remove(0);
- //Indicateservicebinderror
- params.serviceError();
- }
- mPendingInstalls.clear();
- }elseif(mPendingInstalls.size()>0){
- HandlerParamsparams=mPendingInstalls.get(0);
- if(params!=null){
- params.startCopy();
- }
- }else{
- //Shouldneverhappenideally.
- Slog.w(TAG,"Emptyqueue");
- }
- break;
- }
- ****************省略若干**********************
- }
- }
publicfinalbooleansendMessage(Messagemsg)
publicfinalbooleansendEmptyMessage(intwhat)
两者参数有别。
然后调用抽象类HandlerParams中的一个startCopy()方法
abstractclassHandlerParams{
finalvoidstartCopy(){
***************若干if语句判定否这打回handler消息*******
handleReturnCode();
}
}
handleReturnCode()复写了两次其中有一次是删除时要调用的,只列出安装调用的一个方法
[java] view plain copy- @Override
- voidhandleReturnCode(){
- //IfmArgsisnull,thenMCScouldn'tbereached.Whenit
- //reconnects,itwilltryagaintoinstall.Atthatpoint,this
- //willsucceed.
- if(mArgs!=null){
- processPendingInstall(mArgs,mRet);
- }
- }
这时可以清楚的看见processPendingInstall()被调用。
其中run()方法如下
[java] view plain copy
- run(){
- synchronized(mInstallLock){
- ************省略*****************
- installPackageLI(args,true,res);
- }
- }
- instaPacakgeLI()args,res参数分析
-----------------------------------------------------------------------------------------
//InstallArgs是在PackageService定义的staticabstractclassInstallArgs静态抽象类。
[java] view plain copy
- staticabstractclassInstallArgs{
- *********************************************************************
- 其中定义了flag标志,packageURL,创建文件,拷贝apk,修改包名称,
- 还有一些删除文件的清理,释放存储函数。
- *********************************************************************
- }
- classPackageInstalledInfo{
- Stringname;
- intuid;
- PackageParser.Packagepkg;
- intreturnCode;
- PackageRemovedInforemovedInfo;
- }
-----------------------------------------------------------------------------------------
[java] view plain copy- privatevoidinstallPackageLI(InstallArgsargs,
- booleannewInstall,PackageInstalledInfores){
- intpFlags=args.flags;
- StringinstallerPackageName=args.installerPackageName;
- FiletmpPackageFile=newFile(args.getCodePath());
- booleanforwardLocked=((pFlags&PackageManager.INSTALL_FORWARD_LOCK)!=0);
- booleanonSd=((pFlags&PackageManager.INSTALL_EXTERNAL)!=0);
- booleanreplace=false;
- intscanMode=(onSd?0:SCAN_MONITOR)|SCAN_FORCE_DEX|SCAN_UPDATE_SIGNATURE
- |(newInstall?SCAN_NEW_INSTALL:0);
- //Resultobjecttobereturned
- res.returnCode=PackageManager.INSTALL_SUCCEEDED;
- //RetrievePackageSettingsandparsepackage
- intparseFlags=PackageParser.PARSE_CHATTY|
- (forwardLocked?PackageParser.PARSE_FORWARD_LOCK:0)|
- (onSd?PackageParser.PARSE_ON_SDCARD:0);
- parseFlags|=mDefParseFlags;
- PackageParserpp=newPackageParser(tmpPackageFile.getPath());
- pp.setSeparateProcesses(mSeparateProcesses);
- finalPackageParser.Packagepkg=pp.parsePackage(tmpPackageFile,
- null,mMetrics,parseFlags);
- if(pkg==null){
- res.returnCode=pp.getParseError();
- return;
- }
- StringpkgName=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;
- }
- //Getridofallreferencestopackagescanpathviaparser.
- pp=null;
- StringoldCodePath=null;
- booleansystemApp=false;
- synchronized(mPackages){
- //Checkifinstallingalreadyexistingpackage
- if((pFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
- StringoldName=mSettings.mRenamedPackages.get(pkgName);
- if(pkg.mOriginalPackages!=null
- &&pkg.mOriginalPackages.contains(oldName)
- &&mPackages.containsKey(oldName)){
- //Thispackageisderivedfromanoriginalpackage,
- //andthisdevicehasbeenupdatingfromthatoriginal
- //name.Wemustcontinueusingtheoriginalname,so
- //renamethenewpackagehere.
- pkg.setPackageName(oldName);
- pkgName=pkg.packageName;
- replace=true;
- }elseif(mPackages.containsKey(pkgName)){
- //Thispackage,underitsofficialname,alreadyexists
- //onthedevice;weshouldreplaceit.
- replace=true;
- }
- }
- PackageSettingps=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){
- //Disableupdatestosystemappsonsdcard
- Slog.w(TAG,"Cannotinstallupdatestosystemappsonsdcard");
- res.returnCode=PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
- return;
- }
- if(!args.doRename(res.returnCode,pkgName,oldCodePath)){
- res.returnCode=PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- return;
- }
- //Setapplicationobjectspathexplicitlyaftertherename
- 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()
[java] view plain copy- privatevoidinstallNewPackageLI(PackageParser.Packagepkg,
- intparseFlags,intscanMode,
- StringinstallerPackageName,PackageInstalledInfores){
- ***********************省略若干*************************************************
- PackageParser.PackagenewPackage=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就是使用方法
[java] view plain copy
- privatestaticvoidshowUsage(){
- System.err.println("usage:pm[list|path|install|uninstall]");
- System.err.println("pmlistpackages[-f]");
- System.err.println("pmlistpermission-groups");
- System.err.println("pmlistpermissions[-g][-f][-d][-u][GROUP]");
- System.err.println("pmlistinstrumentation[-f][TARGET-PACKAGE]");
- System.err.println("pmlistfeatures");
- System.err.println("pmpathPACKAGE");
- System.err.println("pminstall[-l][-r][-t][-iINSTALLER_PACKAGE_NAME][-s][-f]PATH");
- System.err.println("pmuninstall[-k]PACKAGE");
- System.err.println("pmenablePACKAGE_OR_COMPONENT");
- System.err.println("pmdisablePACKAGE_OR_COMPONENT");
- System.err.println("pmsetInstallLocation[0/auto][1/internal][2/external]");
- **********************省略**************************
- }
安装时候会调用runInstall()方法
[java] view plain copy- privatevoidrunInstall(){
- intinstallFlags=0;
- StringinstallerPackageName=null;
- Stringopt;
- while((opt=nextOption())!=null){
- if(opt.equals("-l")){
- installFlags|=PackageManager.INSTALL_FORWARD_LOCK;
- }elseif(opt.equals("-r")){
- installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
- }elseif(opt.equals("-i")){
- installerPackageName=nextOptionData();
- if(installerPackageName==null){
- System.err.println("Error:novaluespecifiedfor-i");
- showUsage();
- return;
- }
- }elseif(opt.equals("-t")){
- installFlags|=PackageManager.INSTALL_ALLOW_TEST;
- }elseif(opt.equals("-s")){
- //Overrideif-soptionisspecified.
- installFlags|=PackageManager.INSTALL_EXTERNAL;
- }elseif(opt.equals("-f")){
- //Overrideif-soptionisspecified.
- installFlags|=PackageManager.INSTALL_INTERNAL;
- }else{
- System.err.println("Error:Unknownoption:"+opt);
- showUsage();
- return;
- }
- }
- StringapkFilePath=nextArg();
- System.err.println("\tpkg:"+apkFilePath);
- if(apkFilePath==null){
- System.err.println("Error:nopackagespecified");
- showUsage();
- return;
- }
- PackageInstallObserverobs=newPackageInstallObserver();
- try{
- mPm.installPackage(Uri.fromFile(newFile(apkFilePath)),obs,installFlags,
- installerPackageName);
- synchronized(obs){
- while(!obs.finished){
- try{
- obs.wait();
- }catch(InterruptedExceptione){
- }
- }
- if(obs.result==PackageManager.INSTALL_SUCCEEDED){
- System.out.println("Success");
- }else{
- System.err.println("Failure["
- +installFailureToString(obs.result)
- +"]");
- }
- }
- }catch(RemoteExceptione){
- 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跳转到
[java] view plain copy
- publicclassInstallAppProgressextendsActivityimplementsView.OnClickListener,OnCancelListener
- publicvoidonCreate(Bundleicicle){
- super.onCreate(icicle);
- Intentintent=getIntent();
- mAppInfo=intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
- mPackageURI=intent.getData();
- initView();
- }
方法中调用了initView()方法
[java] view plain copy- publicvoidinitView(){
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.op_progress);
- intinstallFlags=0;
- PackageManagerpm=getPackageManager();
- try{
- PackageInfopi=pm.getPackageInfo(mAppInfo.packageName,
- PackageManager.GET_UNINSTALLED_PACKAGES);
- if(pi!=null){
- installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
- }
- }catch(NameNotFoundExceptione){
- }
- if((installFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
- Log.w(TAG,"Replacingpackage:"+mAppInfo.packageName);
- }
- PackageUtil.AppSnippetas=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);
- //Hidebuttontillprogressisbeingdisplayed
- 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);
- StringinstallerPackageName=getIntent().getStringExtra(
- Intent.EXTRA_INSTALLER_PACKAGE_NAME);
- PackageInstallObserverobserver=newPackageInstallObserver();
- pm.installPackage(mPackageURI,observer,installFlags,installerPackageName);
- }
方法最后我们可以看到再次调用安装接口installPackage()完成安装。
更多相关文章
- Android写文件到SDCard的一般过程和代码
- Android 获取本地音乐文件
- Android 4.0系统源码目录结构详解
- Android播放在线音乐文件
- 文件读写
- Android读取Txt文件
- 在android获取root权限的方法^_^。
- android 不使用布局文件,完全由代码控制布局实例