• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android应用程序安装过程浅析

Android应用程序安装过程浅析

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android应用程序开发,android应用程序,android退出应用程序,android应用程序框架,android应用程序设计等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android应用程序安装过程浅析


我们知道在android中,安装应用是由PackageManager来管理的,但是我们发现PackageManager是一个抽象类,他的installPackage方法也没有具体的实现。那在安装过程中是怎么执行的呐?

调用方

查看代码可以知道ApplicationPackageManager是直接继承自PackageManager的,所以最终代码会调用ApplicationPackageManager下的installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,String installerPackageName),而在installPackage里面又调用了installCommon。

installCommon的实现如下:

 private void installCommon(Uri packageURI,
            PackageInstallObserver observer, int flags, String installerPackageName,
            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
        if (!"file".equals(packageURI.getScheme())) {
            throw new UnsupportedOperationException("Only file:// URIs are supported");
        }
        if (encryptionParams != null) {
            throw new UnsupportedOperationException("ContainerEncryptionParams not supported");
        }

        final String originPath = packageURI.getPath();
        try {
            mPM.installPackage(originPath, observer.getBinder(), flags, installerPackageName,
                    verificationParams, null);
        } catch (RemoteException ignored) {
        }
    }

可以看到在installCommon最终调用了mPm.installPackage那mPm又是什么?可以发现mPM是一个IPackageManager,他在是ApplicationPackageManager的构造函数中传入的,那是什么时候调用构造函数的呐?在ContextImpl中调用getPackageManager时会进行调用,传入的pm在是ActivityThread中创建的。

    @Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }

ActivityThread.getPackageManager()的代码如下:

public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
            return sPackageManager;
        }
        IBinder b = ServiceManager.getService("package");
        //Slog.v("PackageManager", "default service binder = " + b);
        sPackageManager = IPackageManager.Stub.asInterface(b);
        //Slog.v("PackageManager", "default service = " + sPackageManager);
        return sPackageManager;
    }

从上面可以看到IPackageManager是进程间通信的客户端, 首先是IPackageManager是通过IPackageManager.aidl文件生成,同时生成了存根类IPackageManager.Stub,代理类:IPackageManager.Stub.Proxy,他是IBinder类型,那远端又是谁呐?远端就是PackageManagerService,PackageManagerService继承自IPackageManager.Stub,因此最终的调用都是通过aidl由PackageManagerService执行。因此我们主要来看看PackageManagerService中的执行过程。

安装方式

主要有两种方式:
1:系统启动后扫描安装,会调用PackageManagerService的scanPackageLI函数,
2:应用市场安装,应用市场下载后会默认调用PackageManagerService的intallPackage函数,改函数最终也会调用到scanPackageLI,因此只需要分享第二种

流程图

我们可以大致看看代码调用的过程,流程图如下:
这里写图片描述

执行过程

由于PackageManager最终是由PackageManagerService来执行的

 @Override
public void installPackage(String originPath, IPackageInstallObserver2 observer,
        int installFlags, String installerPackageName, VerificationParams verificationParams,
        String packageAbiOverride) {
    installPackageAsUser(originPath, observer, installFlags, installerPackageName,
            verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
}

主要传递了6个参数:

1,originPath,安装包的位置,他必须是file类型活在content的URI类型。传递这里的是一个string类型。

2,observer,是一个IPackageInstallObserver类型,回调通知调用者安装完成

3,installFlags,他的值是INSTALL_FORWARD_LOCK,INSTALL_REPLACE_EXISTING,INSTALL_ALLOW_TEST三个中的一个,INSTALL_FORWARD_LOCK表示安装过程中是否锁定,INSTALL_REPLACE_EXISTING表示是否替换安装包,INSTALL_ALLOW_TEST是否测试安装包,如果有改标志,manifest必须配置android:testOnly

4,installerPackageName,安装包包名

5,verificationParams,代表验证参数用于验证包安装。

6,packageAbiOverride,一般传null

该函数调用了installPackageAsUser函数,installPackageAsUser函数如下:

@Override
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
        int installFlags, String installerPackageName, VerificationParams verificationParams,
        String packageAbiOverride, int userId) {
    mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);

    final int callingUid = Binder.getCallingUid();
    enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");

    if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
        try {
            if (observer != null) {
                observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
            }
        } catch (RemoteException re) {
        }
        return;
    }

    if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
        installFlags |= PackageManager.INSTALL_FROM_ADB;

    } else {
        // Caller holds INSTALL_PACKAGES permission, so we're less strict
        // about installerPackageName.

        installFlags &= ~PackageManager.INSTALL_FROM_ADB;
        installFlags &= ~PackageManager.INSTALL_ALL_USERS;
    }

    UserHandle user;
    if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
        user = UserHandle.ALL;
    } else {
        user = new UserHandle(userId);
    }

    // Only system components can circumvent runtime permissions when installing.
    if ((installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
            && mContext.checkCallingOrSelfPermission(Manifest.permission
            .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
        throw new SecurityException("You need the "
                + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
                + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
    }

    verificationParams.setInstallerUid(callingUid);

    final File originFile = new File(originPath);
    final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);

    final Message msg = mHandler.obtainMessage(INIT_COPY);
    msg.obj = new InstallParams(origin, null, observer, installFlags, installerPackageName,
            null, verificationParams, user, packageAbiOverride, null);
    mHandler.sendMessage(msg);
}

该函数主要做了以下操作,第一强制获取权限,如果被拒绝则退出执行,接着设置installFlags参数,最后一步发送了一个what为INIT_COPY的message,参数为InstallParams,记住该参数,后面还会多次用到,看what的名称INIT_COPY,看起来是表达初始化并且拷贝,那是不是真是这样呐?我们去看看这个操作,这个操做是PackageHandler来执行的,PackageHandler继续字Handler,那我们来具体看看执行代码:

case INIT_COPY: {
    HandlerParams params = (Handl



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android程序中--不能改变的事情,android程序--改变
  • Android应用程序安装过程浅析
  • Android应用程序内存泄漏介绍
  • Android应用开发必备的20条技能
  • Android程序版本更新--通知栏更新下载安装,android程序版本

相关文章

  • 2017-05-26设计五(六)大原则,设计原则
  • 2017-05-26[Android]Animation 动画介绍和实现,androidanimation
  • 2017-05-26自定义控件(一),自定义控件(
  • 2017-05-26Linux动态链接库加载失败一例
  • 2017-05-26java 接口的作用和好处,java接口好处
  • 2017-05-26Android网络编程(一)HTTP协议原理
  • 2017-05-26【lushengduan】01、搭建安卓App开发环境 编写程序HelloWorld,lushengduan安卓
  • 2017-05-26想要在launcher中模拟按home键。,launcherhome
  • 2017-05-228.1.2 Android中的13种Drawable小结 Part 2
  • 2017-05-26深入了解Kotlin的必备书籍,深入了解kotlin必备

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • ViewPager和Fragment的组合使用,viewpagerfragment
    • 4.2.2 Service进阶
    • 安卓第二天笔记-数据保存,安卓第二天笔记保存
    • 4.3.1 BroadcastReceiver牛刀小试
    • android开发,权限获取,android开发权限
    • Android 判断当前语言环境是否是中文环境,android中文
    • Android登录客户端,验证码的获取,网页数据抓取与解析,HttpWatch基本使用
    • Android中隐藏顶部状态栏的那些坑,android顶部状态栏
    • android学习第一天(android的介绍和基础):,android第一天
    • 几个常用的adb命令,常用adb命令

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有