美文网首页工具使用指南Android
Android之静默安装接口对比分析

Android之静默安装接口对比分析

作者: 锄禾豆 | 来源:发表于2022-01-15 12:34 被阅读0次

    简介

    分析静默安装新老接口的对比。
    源码:
    7.1
    

    分析

    老接口A:
    PackageManager.installPackage(
                Uri packageURI,
                PackageInstallObserver observer,
                @InstallFlags int flags,
                String installerPackageName);
                
    新接口B:
    PackageInstaller packageInstaller = PackageManager.getPackageInstaller();
    SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
    int sessionId = packageInstaller.createSession(sessionParams);//创建会话id
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);//创建会话
    
    final InputStream in = new FileInputStream(file);
    final long sizeBytes = file.length();
    final OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes);//打开会话写操作
    try {
        int c;
        while ((c = in.read(buffer)) != -1) {
            out.write(buffer, 0, c);//往会话中写数据
            if (sizeBytes > 0) {
                final float fraction = ((float) c / (float) sizeBytes);
                session.addProgress(fraction);
            }
        }
        session.fsync(out);//会话数据同步
    } finally {
        IoUtils.closeQuietly(in);
        IoUtils.closeQuietly(out);
    }
    
    Intent broadcastIntent = new Intent(BROADCAST_ACTION);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
                        InstallAppProgress.this /*context*/,
                        sessionId,
                        broadcastIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
    session.commit(pendingIntent.getIntentSender());//提交数据
    
    对比:
    A 实现简单  结果监听直接采用observer    数据通过系统直接写到data/app/包名/base.apk
    B 实现复杂  结果监听通过PendingIntent   数据先保存在/data/app/vmt{sessiondi}.tmp,再写到/data/app/包名/base.apk
    
    注:
    B 涉及了委托模式和会话模式的运用
    A 写入base.apk采用了DefaultContainerService.apk拷贝业务
    
    SessionParams需要一个模式参数:
    MODE_FULL_INSTALL:新的apk会替换旧的apk的模式。
    MODE_INHERIT_EXISTING:新的apk继承旧的apk.
    

    原理

    老接口A:
    PackageManager.installPackage --> PackageManagerService.installPackageAsUser
    
    新接口B:
    PackageManager --> PackageInstaller (PackageInstaller.Session.commmit) --> PackageInstallSession --> PackageManagerService.installStage
    
    对比AMS实现:原理一样,只是传进来的参数B比A更加丰富
    A: mHandler INIT_COPY
            final Message msg = mHandler.obtainMessage(INIT_COPY);
            final VerificationInfo verificationInfo = new VerificationInfo(
                    null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
            final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
                    installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
                    null /*packageAbiOverride*/, null /*grantedPermissions*/,
                    null /*certificates*/);
            params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
            msg.obj = params;
    
            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installAsUser",
                    System.identityHashCode(msg.obj));
            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                    System.identityHashCode(msg.obj));
    
            mHandler.sendMessage(msg);
            
    B: mHandler INIT_COPY
            final VerificationInfo verificationInfo = new VerificationInfo(
                    sessionParams.originatingUri, sessionParams.referrerUri,
                    sessionParams.originatingUid, installerUid);
    
            final OriginInfo origin;
            if (stagedDir != null) {
                origin = OriginInfo.fromStagedFile(stagedDir);
            } else {
                origin = OriginInfo.fromStagedContainer(stagedCid);
            }
    
            final Message msg = mHandler.obtainMessage(INIT_COPY);
            final InstallParams params = new InstallParams(origin, null, observer,
                    sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
                    verificationInfo, user, sessionParams.abiOverride,
                    sessionParams.grantedRuntimePermissions, certificates);
            params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
            msg.obj = params;
    
            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
                    System.identityHashCode(msg.obj));
            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                    System.identityHashCode(msg.obj));
    
            mHandler.sendMessage(msg);
    

    adb查询

    adb shell dumpsys package installs
    采用新接口安装的业务,通过此命令可查询apk安装的相关信息
    

    相关文章

      网友评论

        本文标题:Android之静默安装接口对比分析

        本文链接:https://www.haomeiwen.com/subject/bputhrtx.html