精华内容
下载资源
问答
  • Android APK安装脚本.rar

    2013-04-07 15:20:44
    Android APK安装脚本,用超级终端安装APK,可安装到system/app
  • Android apk安装器.rar

    2012-06-13 16:50:16
    Android apk安装器 很好用,推荐大家下载
  • 一文看懂Android APK安装的原理

    千次阅读 2019-07-23 23:56:12
    我们知道,Windows应用程序的安装包是一个可执行的压缩包,安装的过程是把压缩包中的数据和依赖库拷贝到安装目录,再在桌面或启动栏创建快捷方式,那么安卓APK安装过程是不是也是这样的呢?本文将为大家解答这些...

    一文看懂Android APK安装的原理

    前言

    大家有没有想过一个应用的APK是怎么被安装到安卓手机上的,安装的本质是什么?我们知道,Windows应用程序的安装包是一个可执行的压缩包,安装的过程是把压缩包中的数据和依赖库拷贝到安装目录,再在桌面或启动栏创建快捷方式,那么安卓的APK安装过程是不是也是这样的呢?本文将为大家解答这些问题。

    APK包的构成

    首先,我看一下APK包的构成,Android的APK包和Windows应用程序安装包是不同的,它只是个简单的压缩包,没有可执行的能力,我们还可以用zip工具直接解压它。

    一个APK包含以下这些文件:

    • META-INF目录:包含两个签名文件(CERT.SF和CERT.RSA),以及一个manifest文件(MANIFEST.MF)
    • assets目录:包含工程中的asset目录下的文件,可以使用AssetManager获取
    • res目录:包含那些没有被编译到resources.arsc的资源
    • lib目录:包含适用于不同处理器的第三方依赖库,这里边可以有多个子目录,比如armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, 以及mips
    • resources.arsc文件:存储编译好的资源,包括项目工程中的res/values目录里的xml文件,它们都被编译成二进制格式,也包括一些路径,指向那些没有被编译的资源,比如layout文件和图片
    • classes.dex文件:项目中的java类都被编译到该dex文件,这个文件可以被Android的Dalvik/ART虚拟机解析。
    • AndroidManifest.xml:二进制格式的manifest文件,这个文件是必须的。

    这些文件是Android系统运行一个应用程序时会用到的数据和代码,下面介绍系统如何安装一个APK包。

    安装APK

    我们安装应用程序,最常用的方法就是在PC上运行命令adb install 加APK的文件路径,回车等待Android设备安装完成,安装成功命令行会显示Success。那么其内部是怎样的一个过程呢?

    1. 将APK包push到手机
    首先,adb会将PC端的APK文件push到Android设备的/data/local/tmp目录下,一些手机会将拷贝的进度反馈给adb客户端,于是PC上的命令行会展示拷贝的进度。

    2. 执行pm命令
    PC端的adb程序会向Android端的adbd发送shell:pm命令,于是adbd会向系统的PackageManagerService(PMS)进程发送消息,通知其安装apk包。这里我有两个理解:
    **理解一:**我们平常也可以在adb shell上执行pm命令与PMS交互,那么pm应该是个独立的进程,adbd执行pm命令,是启动了pm这个进程,这个进程再向PMS进程发送消息,通知其安装APK。
    **理解二:**adbd直接向PMS进程发送消息,通知其安装APK。
    不知哪个正确,这个有待继续研究,如果有童鞋了解这个,希望能不吝赐教。

    3. 触发安装过程
    PMS首先将APK包拷贝到另外一个目录/data/app,这个目录是非系统应用的apk存放的目录,与之相对应的,系统应用的apk存放的目录是/system/frameworks、/system/app和/vendor/app。
    PMS内部有个AppDirObserver类,其监听着/data/app目录的变化,当apk被复制到/data/app目录之后,该类随即触发PMS对APK进行解析。

    4. APK的解析
    我们可以先想想,Android系统是如何启动一个APP的?比如点击屏幕上的应用图标,然后一个Activity就被启动了。这个过程中,桌面程序Launcher先是向ActivityManagerService(AMS)进程发送了一个Intent,AMS随即会将这个Intent扔给PMS,PMS则解析这个Intent得到Activity的信息给到AMS,然后AMS会启动一个空进程,并通知该进程创建该Activity。那么PMS为什么会有这个Activity的信息呢?

    这就是PMS解析APK要做的事情了,而解析APK的时机又要分成两种场景:

    1. 系统启动时解析APK
    Android系统在启动的时候,会启动一个system_server进程,这个进程驻留着系统多个重要的服务,其中便包含了与APK最相关的PackageManagerService服务,这个服务在启动的时候,会扫描Android系统中几个目标文件夹中的APK,对每个APK进行解析。
    2. 安装过程中解析APK
    安装一个apk的过程,PMS也会对这个APK进行解析,其调用的是PackageManagerService.java的scanPackageLI()方法,其实在系统启动时扫描全部apk的过程也是调用该方法。

    可以这样理解,系统启动的时候,是解析已经安装的所有APK,而安装单个APK时,则是用同样的方法解析这个APK,过程是一样的。

    那么解析APK具体做的是什么事情呢?

    其中主要的过程就是解析APK中的AndroidManifest.xml文件,将APK的关键信息四大组件信息、权限信息等存储在内存中的PackageParser对象中,PackageParser对象的结构如图所示:

    来源:https://blog.csdn.net/Innost/article/details/47253179

    这个PackageParser包含了IntentFilter的信息,使得PMS可以根据Intent来获取一个Activity的信息。那么,PMS在得到PackageParser对象之后,接着会将这个APK的信息加入到PMS自身管理中去,比如将Activity的数据保存在mActivities对象中,将Provider的数据保存在mProviders对象中等,PKMS提供了好几个重要数据结构来保存这些数据,这些数据结构的相关信息如图所示:

    来源:https://blog.csdn.net/Innost/article/details/47253179

    除了解析和保存APK的核心数据,PMS还会创建应用程序目录:/data/data/包名,同时提取apk中的dex文件并保存到/data/dalvik-cache中,如果该APK包含了native动态库,则需要将它们从APK文件中解压并复制到对应目录中,以及对APK进行dex优化,还有其它一些细节比如APK签名的校验,杀死APK所在进程(覆盖安装的情况)等,安装过程的最后,会发送ACTION_PACKAGE_ADDED广播,通知所有其它应用有新应用安装了。

    总结

    至此,APK安装过程就结束了。纵观整个过程,apk安装的关键就是解析AndroidManifest.xml,将重要的信息保存在PMS进程的内存中,以保证后续启动这个应用程序的组件时,可以在PMS中找到这个组件的信息。我们本来认为的更重要的代码只是进行dex优化后简单地提取到一个目录中而已,另外,APK中的资源并没有被处理,而是在启动应用进程的时候,动态去从APK包中加载而已。

    本文完。


    简书:https://www.jianshu.com/p/79e963715d1d
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • android apk安装过程分析
  • Apk安装Android11之前可通过 Intent.ACTION_INSTALL_PACKAGE 进行传递Apk的URI进行安装但是在Android11版本 Intent.ACTION_INSTALL_PACKAGE 已标注弃用同时推荐在Android5版本提供的PackageInstaller类进行安装兼容...

    Apk安装

    Android11之前可通过 Intent.ACTION_INSTALL_PACKAGE 进行传递Apk的URI进行安装

    但是在Android11版本 Intent.ACTION_INSTALL_PACKAGE 已标注弃用

    同时推荐在Android5版本提供的PackageInstaller类进行安装

    兼容到Android5.0

    PackageInstaller

    先看看该类的使用流程

    e42f9973aea2

    Android Apk 安装.jpg

    额外提示

    通过该方式,不需要主动去申请App内安装Apk权限,PackageInstaller内置了该申请

    代码实现

    注意 该类启动模式为 栈顶单例

    同时需配备一个 intent-filter

    //注意 该类启动模式为 栈顶单例

    class InstallActivity : AppCompatActivity() {

    //intent-filter 的 action

    private val ACTION_INSTALL = "cc.xiaobaicz.work.INSTALL_APK"

    override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)

    install()

    }

    /**

    * 安装

    */

    private fun install() {

    packageManager.packageInstaller.apply {

    //生成参数

    val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)

    //创建ID

    val id = createSession(params)

    //打开Session

    val session = openSession(id)

    //写入文件

    writeAssetsApk2Session(session, "pbox.apk")

    //新建IntentSender

    val intent = createIntentSender()

    //提交,进行安装

    session.commit(intent)

    }

    }

    /**

    * 新建一个IntentSender用于接收结果

    * 该例子通过当前页面接收

    */

    private fun createIntentSender(): IntentSender {

    val intent = Intent(this, MainActivity::class.java).apply {

    action = ACTION_INSTALL

    }

    val pending = PendingIntent.getActivity(this, 0, intent, 0)

    return pending.intentSender

    }

    //写入Apk到Session输出流,该例子 获取Assets内文件,可通过其他方式获取Apk流

    private fun writeAssetsApk2Session(session: PackageInstaller.Session, s: String) {

    assets.open(s).use { input ->

    session.openWrite("apk", 0, -1).use { output ->

    output.write(input.readBytes())

    }

    }

    }

    /**

    * 接收安装结果

    */

    override fun onNewIntent(intent: Intent?) {

    super.onNewIntent(intent)

    intent ?: return

    if (intent.action != ACTION_INSTALL) {

    return

    }

    intent.extras?.apply {

    when (this.getInt(PackageInstaller.EXTRA_STATUS)) {

    PackageInstaller.STATUS_PENDING_USER_ACTION -> {

    //提示用户进行安装

    startActivity(this.get(Intent.EXTRA_INTENT) as Intent)

    }

    PackageInstaller.STATUS_SUCCESS -> {

    //安装成功

    }

    else -> {

    //失败信息

    val msg = this.getString(PackageInstaller.EXTRA_STATUS_MESSAGE)

    }

    }

    }

    }

    }

    展开全文
  • android apk安装工具(adb封装),实现了代码调用adb实例。
  • Android APK安装完成自动删除安装包

    万次阅读 2018-01-10 16:10:24
    Android APK安装完成自动删除安装包 需要实现此功能,一般实际开发是在自动版本更新上,当更新完开始自动安装完毕后,删除内存卡里的安装包。实现方式很简单,监听应用广播,获取内存卡下的文件,删除! 1、监听...

    Android APK安装完成自动删除安装包

    需要实现此功能,一般实际开发是在自动版本更新上,当更新完开始自动安装完毕后,删除内存卡里的安装包。实现方式很简单,监听应用广播,获取内存卡下的文件,删除!
    1、监听广播
    package com.example.a75213.testdownloaddemo;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.widget.Toast;
    
    import com.example.a75213.testdownloaddemo.contant.comm;
    
    /**
     * Created by 75213 on 2017/11/7.
     */
    
    public class InitApkBroadCastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
    
            if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
                comm.rmoveFile("http://imtt.dd.qq.com/16891/7C7BB50B68B684A36339AF1F615E2848.apk");
                Toast.makeText(context , "监听到系统广播添加" , Toast.LENGTH_LONG).show();
            }
    
            if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                comm.rmoveFile("http://imtt.dd.qq.com/16891/7C7BB50B68B684A36339AF1F615E2848.apk");
                Toast.makeText(context , "监听到系统广播移除" , Toast.LENGTH_LONG).show();
                System.out.println("");
            }
    
            if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) {
                comm.rmoveFile("http://imtt.dd.qq.com/16891/7C7BB50B68B684A36339AF1F615E2848.apk");
                Toast.makeText(context , "监听到系统广播替换" , Toast.LENGTH_LONG).show();
            }
        }
    }

    2、记得给删除权限和广播注册【AndroidMainifest】
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <receiver
                android:name=".InitApkBroadCastReceiver"
                android:enabled="true">
                <intent-filter>
                    <action android:name="android.intent.action.PACKAGE_ADDED" />
                    <action android:name="android.intent.action.PACKAGE_REPLACED" />
                    <action android:name="android.intent.action.PACKAGE_REMOVED" />
    
                    <data android:scheme="package" />
                </intent-filter>
            </receiver>

    3、删除工具类
    package com.example.a75213.testdownloaddemo.contant;
    
    import android.os.Environment;
    
    import java.io.File;
    
    /**
     * Created by 75213 on 2017/11/1.
     */
    
    public class comm{
        public static File getPathFile(String path){
            String apkName = path.substring(path.lastIndexOf("/"));
            File outputFile = new File(Environment.getExternalStoragePublicDirectory
                    (Environment.DIRECTORY_DOWNLOADS), apkName);
            return outputFile;
        }
    
        public static void rmoveFile(String path){
            File file = getPathFile(path);
            file.delete();
        }
    }



    展开全文
  • Android APK安装流程

    2020-05-06 14:40:36
    我们来思考一下Android系统是如何安装一个APK文件的,从直观的流程上,当我们点击一个APK文件或者从应用商店下载一个APK文件,会弹起一个安装对话框,点击安装就可以安装应用。 那么这里面的流程是什么样的呢?????...

    我们来思考一下Android系统是如何安装一个APK文件的,从直观的流程上,当我们点击一个APK文件或者从应用商店下载一个APK文件,会弹起一个安装对话框,点击安装就可以安装应用。

    那么这里面的流程是什么样的呢?🤔

    首先很容易想到的是,Android根据文件类型MimeType来判断是否弹起安装页面,就行点击一个视频会调起视频播放器一样。

    Android系统常见的文件类型如下所示:

    👉 MimeUtils.java

    • add("application/zip", "zip");
    • add("application/vnd.android.package-archive", "apk");
    • add("video/mp4", "mp4");
    • add("video/3gpp", "3gpp");
    • add("text/plain", "txt");
    • add("image/gif", "gif");
    • add("image/ico", "ico");
    • add("image/jpeg", "jpeg");
    • add("image/jpeg", "jpg");

    这里面就有我们今天聊的APK文件,当点击APK文件时会调起安装界面,这个安装界面其实就是PackageInstallerActivity

    //点击APK文件,弹起对话框,询问是否安装此应用。
    File apkFile;
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
    context.startActivity(intent);

    PackageInstallerActivity显示的是个对话框,当点击确定安装以后,会启动真正的安装界面,这个界面就是InstallAppProgress,它也是一个Activity,会显示安装的进度,

    整个APK的安装流程如下所示:

    1. 复制APK到/data/app目录下,解压并扫描安装包。
    2. 资源管理器解析APK里的资源文件。
    3. 解析AndroidManifest文件,并在/data/data/目录下创建对应的应用数据目录。
    4. 然后对dex文件进行优化,并保存在dalvik-cache目录下。
    5. 将AndroidManifest文件解析出的四大组件信息注册到PackageManagerService中。
    6. 安装完成后,发送广播。

    总体说来就两件事情拷贝APK和解析APK,解析APK主要是解析APK的应用配置文件AndroidManifest.xml,以便获得它的安装信息。在安装的过程中还会这个应用分配Linux用 户ID和Linux用户组ID(以便它可以在系统中获取合适的运行权限)。

    关于Linux用户ID与Linux用户组ID

    Linux用户ID与Linux用户组ID的分配与管理是由Settings类来完成的。

    Settings:该类用来管理应用程序的安装信息(APK包信息、Linux用户ID、Linux用户组ID等),Android系统在每次重启是都会将应用程序重新安装一遍,Settings就是保证在重新安装应用时可以恢复应用的信息。

    在Android系统中,用户ID可以划分为以下层次:

    • 小于FIRST_APPLICATION_UID:特权用户ID,用户应用程序不能直接使用,但是可以以一种sharedUserId的方式共享使用,例如想要修改系统时间就设置android:sharedUserId = "android.uid.system"。
    • FIRST_APPLICATION_UID 至 FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS:给用户应用程序使用,共有1000个。
    • 大于FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS:非法的Linxu用户ID。

    以上便是对APK安装流程的整体概述,有了整体的把握,我们接着来看实现细节。APK安装流程序列图如下所示:

    👉 点击图片查看高清大图

    嗯,看起来有点长😤,但只要我们掌握核心逻辑和原理,再长的函数调用链都是纸老虎。😎

    整个序列图按照颜色划分为三个进程:

    • PackageInstaller进程:PackageInstaller事实上是一个应用,它负责APK安装以及卸载过程中与用户的交互流程。
    • SystemServer进程:该进程主要运行的是系统服务,APK的安装、卸载和查询都由PackageManagerService负责,它也是Android核心系统服务的一种,在SystemServer里初始化系统服务的时候被启动。
    • DefaultContainerService进程:DefaultContainerService也是一个单独的进程,它主要负责检查和复制设备上的文件,APK的复制就是由DefaultContainerService来完成的。

    PackageInstaller和DefaultContainerService都比较简单,我们重点关注的是Android的包管理服务PackageManagerService。

    一 APK解析流程

    Android的应用程序是一个以".apk"为后缀名的归档文件,它在安装之前会先DefaultContainerService将自己复制到/data/app目录中去,拷贝完成以后 便开始解析APK。

    这里提一下/data/app这个目录,Android不同的目录存放不同类型的应用,如下所示:

    • /system/framwork:保存的是资源型的应用程序,它们用来打包资源文件。
    • /system/app:保存系统自带的应用程序。
    • /data/app:保存用户安装的应用程序。
    • /data/app-private:保存受DRM保护的私有应用程序。
    • /vendor/app:保存设备厂商提供的应用程序。

    APK文件里包含了一个配置文件AndroidManifest.xml,Android应用程序的解析过程就是解析这个xml文件的过程。

    从上面的序列图我们可以看出,APK解析是从PackageManagerService的scanPackageLI开始的,而该方法内部又调用的是scanPackageDirtyLI()方法,我们来看一下这个方法的实现。

    public class PackageManagerService extends IPackageManager.Stub {
    
           private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
                   int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
               //...
               // writer
               synchronized (mPackages) {
                   // 验证已注册的ContentProvider是否有其他同名,做冲突检测。
                   if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
                       final int N = pkg.providers.size();
                       int i;
                       for (i=0; i<N; i++) {
                           PackageParser.Provider p = pkg.providers.get(i);
                           if (p.info.authority != null) {
                               String names[] = p.info.authority.split(";");
                               for (int j = 0; j < names.length; j++) {
                                   if (mProvidersByAuthority.containsKey(names[j])) {
                                       PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
                                       final String otherPackageName =
                                               ((other != null && other.getComponentName() != null) ?
                                                       other.getComponentName().getPackageName() : "?");
                                       throw new PackageManagerException(
                                               INSTALL_FAILED_CONFLICTING_PROVIDER,
                                                       "Can't install because provider name " + names[j]
                                                       + " (in package " + pkg.applicationInfo.packageName
                                                       + ") is already used by " + otherPackageName);
                                   }
                               }
                           }
                       }
                   }
               }
    
               if (mPlatformPackage == pkg) {
                  //...
               } else {
                   // This is a normal package, need to make its data directory.
                   dataPath = getDataPathForPackage(pkg.packageName, 0);
                   if (dataPath.exists()) {
                       //...
                   } else {
                       //invoke installer to do the actual installation
                       //这里创建了应用数据目录,用于存放用户数据
                       int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
                                                  pkg.applicationInfo.seinfo);
                       //...
                   }
    
               }
    
               // We also need to dexopt any apps that are dependent on this library.  Note that
               // if these fail, we should abort the install since installing the library will
               // result in some apps being broken.
               if (clientLibPkgs != null) {
                   if ((scanFlags & SCAN_NO_DEX) == 0) {
                       for (int i = 0; i < clientLibPkgs.size(); i++) {
                           PackageParser.Package clientPkg = clientLibPkgs.get(i);
                           if (performDexOptLI(clientPkg, null /* instruction sets */, forceDex,
                                   (scanFlags & SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) {
                               throw new PackageManagerException(INSTALL_FAILED_DEXOPT,
                                       "scanPackageLI failed to dexopt clientLibPkgs");
                           }
                       }
                   }
               }
    
               // writer
               synchronized (mPackages) {
                   //...
                   // 以下对四大组件进行注册
                   int N = pkg.providers.size();
                   StringBuilder r = null;
                   int i;
                   for (i=0; i<N; i++) {
                       PackageParser.Provider p = pkg.providers.get(i);
                       p.info.processName = fixProcessName(pkg.applicationInfo.processName,
                               p.info.processName, pkg.applicationInfo.uid);
                       //注册Content Provider
                       mProviders.addProvider(p);
                       //...
                   }
                   //...
               }
           }
           //...
       }
    }

    scanPackageDirtyLI是一个上千行的函数,它主要完成的工作如下所示:

    1. 调用PackageParser的parsePackage()方法解析AndroidMainfest.xml文件,主要包括四大组件、权限信息、用户ID,其他use-feature、shared-userId、use-library等 信息,并保存到PackageManagerService相应的成员变量中。
    2. 调用签名验证方法verifySignaturesLP()进行签名验证,验证失败的无法进行安装。
    3. 调用createDataDirsDirtyLI()方法创建应用目录/data/data/package,同时将APK中提取的DEX文件保存到/data/dalvik-cache中。
    4. 调用performDexOptLI()方法执行dexopt操作。

    我们接着来看看APK里的信息是如何被解析出来的。

    Apk的解析是PackageParser的parsePackage()函数来完成的,我们来看看它的实现。

    public class PackageParser {
    
         public Package parsePackage(File packageFile, int flags) throws PackageParserException {
             if (packageFile.isDirectory()) {
                 return parseClusterPackage(packageFile, flags);
             } else {
                 return parseMonolithicPackage(packageFile, flags);
             }
         }
    
         private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
                 //...
    
                 //初始化AssetManager
                 final AssetManager assets = new AssetManager();
                 try {
                     //...
                     //解析Base APk,解析AndroidManifest.xml
                     final Package pkg = parseBaseApk(baseApk, assets, flags);
                     if (pkg == null) {
                         throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
                                 "Failed to parse base APK: " + baseApk);
                     }
    
                     //如果splitName不为空,则循环解析Split Apk
                     if (!ArrayUtils.isEmpty(lite.splitNames)) {
                         final int num = lite.splitNames.length;
                         pkg.splitNames = lite.splitNames;
                         pkg.splitCodePaths = lite.splitCodePaths;
                         pkg.splitRevisionCodes = lite.splitRevisionCodes;
                         pkg.splitFlags = new int[num];
                         pkg.splitPrivateFlags = new int[num];
    
                         for (int i = 0; i < num; i++) {
                             //解析
                             parseSplitApk(pkg, i, assets, flags);
                         }
                     }
    
                     pkg.setCodePath(packageDir.getAbsolutePath());
                     pkg.setUse32bitAbi(lite.use32bitAbi);
                     return pkg;
                 } finally {
                     IoUtils.closeQuietly(assets);
                 }
             }
    }
    

    注:Split APK是Google为解决65535上限以及APK越来越大的问题而提出的一种方案,它可以将一个庞大的APK按照屏幕密度、ABI等形式拆分成多个独立的APK,这些APK共享相同的data、cache目录。 共享相同的进程,共享相同的包名。它们还可以使用各自的资源,并且继承了Base APK里的资源。更多细节可以查阅官方文档Build Multiple APKs

    该方法调用parseBaseApk()去解析AndroidManifest.xml,AndroidManifest.xml也是xml文件,当然也使用XmlResourceParser来解析。这个解析相应标签并保存到PackageManagerService对应的成员变量中去。 此处就不再展开。

    通过上面的讲解,我们理解了APK的计息流程,APK解包以后,里面有个DEX文件,我们前面也说过PackageManagerService的performPackageLI()方法去执行dexopt操作 ,我们接着来分析它是如何实现的。

    二 DEX的dexopt流程

    我们先来了解一下什么dexopt操作,dexopt操作实际上对DEX文件在执行前进行一些优化,但是不同的虚拟机操作有所不同。

    • Davlik:将dex文件优化生成odex文件,这个odex文件的后缀也是dex,保存在/data/dalvik-cache目录下。
    • ART:将dex文件翻译生成oat文件

    从上面的序列图我们可以看出,Installer.java通过Socket方式请求守护进程installd完成dexopt操作。

    public final class Installer {  
        public int dexopt(String apkPath, int uid, boolean isPublic) {  
            StringBuilder builder = new StringBuilder("dexopt");  
            builder.append(' ');  
            builder.append(apkPath);  
            builder.append(' ');  
            builder.append(uid);  
            builder.append(isPublic ? " 1" : " 0");  
            return execute(builder.toString());  
        }  
    }

    守护进程调用Command.c里的dexopt()方法执行dexopt操作,如果你对dexopt的C++层的实现感兴趣可以异步:

    👉 Android ART运行时无缝替换Dalvik虚拟机的过程分析

    APK安装完成以后会在桌面生成一个快捷图标,点击图标就可以启动应用了。

    展开全文
  • android apk安装过程源码解析

    千次阅读 2017-07-13 23:11:18
    前言: 前一篇博客分析了一下PackageManagerService是如何解析apk的以及我们如何解析未安装apk中的androidManifest.xml文件。解析完肯定要安装的,索性写一篇关于android系统是如何...apk安装java层的起始位置是在Pm.
  • Android apk安装失败解决

    千次阅读 2019-12-23 15:52:58
    以下是本人安装apk失败的经验之谈,不完善之处,还请指教。 1、未签名文件 Build apk生成的apk文件,或者直接运行,不经过签名过程。都属于这种。正常运行可以,但是无法使用版本更新和apk文件覆盖安装。 .....
  • 注:本文不对apk安装之前,系统所做的复杂工作做分析,只针对普通的apk安装过程进行简单的过程理解 一般情况下,在apk安装时,系统一般会显示一个安装界面,获取用户同意之后进行安装,并且有一些apk预处理相关的...
  • 我们知道,Windows应用程序的安装包是一个可执行的压缩包,安装的过程是把压缩包中的数据和依赖库拷贝到安装目录,再在桌面或启动栏创建快捷方式,那么安卓APK安装过程是不是也是这样的呢?本文将为大家解答这些...
  • Android APK安装与卸载机制

    千次阅读 2016-07-18 12:49:20
    本文主要介绍Android系统如何实现APK安装、卸载、更新等操作。主要内容包括以下内容: 安装和卸载APK的方法有哪些,每种方法实现的原理是什么?APK安装和卸载过程中,系统数据发生了哪些变化?Android App端...
  • 源地址: Android应用安装有如下四种方式 1.系统应用安装――...4.第三方应用安装――通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面。     下载好的A
  • 看了一篇关于apk安装过程的文章,感觉很好,在这转载一下,供大家学习。 Android应用安装有如下四种方式 1.系统应用安装――开机时完成,没有安装界面 2.网络下载应用安装――通过market应用完成,没有安装界面...
  • Android apk安装过程

    千次阅读 2012-03-09 13:15:51
    通过将APK文件直接传到Android模拟器或Android手机中执行即可安装Android应用安装有如下四种方式 1. 系统应用安装――开机时完成,没有安装界面 2. 网络下载应用安装――通过market应用完成,没有安装界面 ...
  • 当我们的程序在被安装后再次重启系统时系统会自动创建我们的APK程序,在所有的APK程序都安装完后系统会最后安装Luncher2.apk 应用程序,Luncher2.apk就是我们的系统界面应用程序,它会检测系统已经安装的应用软件的...
  • paip.android APK安装方法大总结 作者Attilax , EMAIL:1466519819@qq.com 一般来说,我们安装软件,把APK复制到手机上,或者用PC端软件可进行安装。。但是系统应用除外。 1。安装至手机ROM...
  • android apk安装到模拟器 不显示

    千次阅读 2016-05-18 21:24:24
    问题android开发时,apk安装到模拟器,主菜单中不显示,但是通过search可以查询的到。 解决后来,我发现apk名字比较长是"this is firstactivity",改为"first activity"后,显示了。所以,推测是apk名字过长的缘故。
  • 开发 Android 应用后,一般都会安装到手机上去运行,了解应用是如何安装到手机上的,可以更好的理解应用的本质,理解应用是如何运行的,在自己开发的应用遇到一些问题时,会从更深层次去分析,快速定位找到原因。...
  • android APK 安装后显示名称

    千次阅读 2014-04-29 19:46:50
    通过修改AndroidManifest.xml中的android:label="@string/app_name"可以修改apk安装后的显示名称;
  • Android apk安装失败的原因

    千次阅读 2018-06-14 22:09:57
    签名和已安装版本不一致 低版本去覆盖高版本 第三种是打包方式问题: 注意:如果只勾选V2打出来的包是不完整的,所以V1和V2都得勾选;只勾选V2在真机上是跑不起来的...
  • 遇到这个问题 一般都是一头雾水 不知从何下手 解决办法: adb 进入系统 执行 pm install xxx.apk 就会报具体错误
  • android apk安装签名冲突错误解决

    千次阅读 2016-06-08 13:45:23
    一.error: INSTALL_FAILED_UPDATE_INCOMPATIBLE 实际未完全卸载应用。几个方法: 1:adb uninstall 包名完成卸载 2.手动卸载  adb shell($1:应用名称) ... rm -rf /data/dalvik-cache/data@app@$1*.apk
  • Android apk安装监听的几个广播

    千次阅读 2015-09-22 16:39:38
    <receiver android:name=".MyBroadcast" android:enabled="true" > <action android:name="android.intent.action.PACKAGE_ADDED"> <action android:name="android.intent.action.PACKAGE_CHANGED"> <action ...
  • 有时候在安装apk的时候会出现解析软件包出错 (Android studio)解决方法如下: 关闭Instant Run功能: File-Settings-...看下图: 将红色框内的勾取消。 如果还是不行,那么便在工程的gradle....
  • 如上图所示,安装完WebRTCDemo后,出现了2个完全一样的应用程序,其中一个为正常的,一个是不可用的。 原因 这是因为Android程序进行打包编译时,将所有的Manifext文件合并后,发现有多个Activity中存在以下Intent...
  • 在开发Android App后,升级JDK到1.7,遇到APK安装提示INSTALL_PARSE_FAILED_NO_CERTIFICATES错误! 解决方法如下: 使用jarsigner签名时加上参数 -digestalg SHA1 -sigalg MD5withRSA即可

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 598,347
精华内容 239,338
关键字:

安卓apk安装