Android 从源码解读 Apk 的安装过程 ,一招彻底弄懂

PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);

mAlert.setIcon(as.icon);

if (savedInstanceState != null) {

//咱们第一次仅savedInstanceState==null

//安装包的会话 ID

mSessionId = savedInstanceState.getInt(SESSION_ID);

//我们等待的安装事件的 ID

mInstallId = savedInstanceState.getInt(INSTALL_ID);

//重新登记结果;如果结果是在 Activtiy 被销毁时交付的,则可能会立即回调

try {

//添加一个观察者。如果此id已存在事件,请在此调用内回调。

// 向 InstallEventReceiver 注册一个观察者

// InstallEventReceiver 是一个 BroadcastReceiver,可以通过 EventResultPersister 接收到所有的安装事件

// 这里事件会回调给 this::launchFinishBasedOnResult

InstallEventReceiver.addObserver(this, mInstallId,

this::launchFinishBasedOnResult);

} catch (EventResultPersister.OutOfIdsException e) {

// Does not happen

}

} else {

//咱们第一次仅savedInstanceState==null

//创建 SessionParams,它用来携带会话的参数

PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(

PackageInstaller.SessionParams.MODE_FULL_INSTALL);

params.setInstallAsInstantApp(false);

params.setInstallReason(PackageManager.INSTALL_REASON_USER);

File file = new File(mPackageURI.getPath());

try {

// 对 APK 进行轻量级的解析,并将解析的结果赋值给 SessionParams 相关字段

PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);

params.setAppPackageName(pkg.packageName);

params.setInstallLocation(pkg.installLocation);

params.setSize(

PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));

} catch (PackageParser.PackageParserException e) {

} catch (IOException e) {

}

try {

// 向 InstallEventReceiver 注册一个观察者返回一个新的 mInstallId

// InstallEventReceiver 是一个 BroadcastReceiver,可以通过 EventResultPersister 接收到所有的安装事件

// 这里事件会回调给 this::launchFinishBasedOnResult

mInstallId = InstallEventReceiver

.addObserver(this, EventResultPersister.GENERATE_NEW_ID,

this::launchFinishBasedOnResult);

} catch (EventResultPersister.OutOfIdsException e) {

launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);

}

try {

//PackageInstaller 的 createSession

//方法内部会通过 IPackageInstaller 与 PackageInstallerService进行进程间通信,

//最终调用的是 PackageInstallerService 的 createSession 方法来创建并返回 mSessionId

mSessionId = getPackageManager().getPackageInstaller().createSession(params);

} catch (IOException e) {

launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);

}

}

mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);

//监听会话的更改并更新进度条

mSessionCallback = new InstallSessionCallback();

}

}

NameNotFoundException:当找不到给定的包、应用程序或组件名称时,将引发此异常。

在 onCreate() 方法中,首先执行一些初始化操作,比如获取 mInstallId、mSessionId以及监听回调 mSessionCallback 。接下来看看 onStart() 。

onStart()

@Override

protected void onStart() {

super.onStart();

//设置回话监听回调

getPackageManager().getPackageInstaller().registerSessionCallback(mSessionCallback);

}

onResume()

@Override

protected void onResume() {

super.onResume();

//This is the first onResume in a single life of the activity

if (mInstallingTask == null) {

//PackageInstaller:提供在设备上安装、升级和删除应用程序的能力。

//这包括支持打包为单个“整体”APK 的应用程序或打包为多个“拆分”APK 的应用程序。

PackageInstaller installer = getPackageManager().getPackageInstaller();

//安装Session的详细信息

PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);

if (sessionInfo != null && !sessionInfo.isActive()) {

//创建mInstallingTask并启动

mInstallingTask = new InstallingAsyncTask();

mInstallingTask.execute();

} else {

// 安装完成后我们会收到广播

//mCancelButton不允许点击

mCancelButton.setEnabled(false);

//Activity.setFinishOnTouchOutside():设置此活动在其窗口边界外触摸

setFinishOnTouchOutside(false);

}

}

}

InstallingAsyncTask

/**

* Send the package to the package installer and then register a event result observer that

* will call {@link #launchFinishBasedOnResult(int, int, String)}

*/

private final class InstallingAsyncTask extends AsyncTask<Void, Void,

PackageInstaller.Session> {

volatile boolean isDone;

@Override

protected PackageInstaller.Session doInBackground(Void… params) {

PackageInstaller.Session session;

try {

//打开现有Session

session = getPackageManager().getPackageInstaller().openSession(mSessionId);

} catch (IOException e) {

synchronized (this) {

isDone = true;

notifyAll();

}

return null;

}

//设置暂存此会话的当前进度(0-1z之间)。

session.setStagingProgress(0);

try {

File file = new File(mPackageURI.getPath());

//输入流in

try (InputStream in = new FileInputStream(file)) {

long sizeBytes = file.length();

//打开一个流以将 APK 文件写入会话。

try (OutputStream out = session

.openWrite(“PackageInstaller”, 0, sizeBytes)) {

byte[] buffer = new byte[1024 * 1024];

//写入文件

while (true) {

int numRead = in.read(buffer);

if (numRead == -1) {

session.fsync(out);

break;

}

if (isCancelled()) {

session.close();

break;

}

//将 APK 文件通过 IO 流的形式写入到 PackageInstaller.Session 中

out.write(buffer, 0, numRead);

if (sizeBytes > 0) {

float fraction = ((float) numRead / (float) sizeBytes);

session.addProgress(fraction);

}

}

}

}

return session;

} catch (IOException | SecurityException e) {

Log.e(LOG_TAG, “Could not write package”, e);

session.close();

return null;

} finally {

synchronized (this) {

isDone = true;

notifyAll();

}

}

}

@Override

protected void onPostExecute(PackageInstaller.Session session) {

if (session != null) {

//包已下载好,设置安装提交广播

Intent broadcastIntent = new Intent(BROADCAST_ACTION);

broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);

broadcastIntent.set

  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值