Android 从源码解读 Apk 的安装过程 ,阿里技术专家

}

}, null);

}

这里点击安装按钮进去 startInstall() 方法,失败的情况咱就不看了,继续往下走着。

startInstall()

private void startInstall() {

// 启动子Activity,安装应用程序

Intent newIntent = new Intent();

newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,

mPkgInfo.applicationInfo);

newIntent.setData(mPackageURI);

newIntent.setClass(this, InstallInstalling.class);

newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);

startActivity(newIntent);

finish();

}

startInstall 调用即使启用了一个新的Activity–>InstallInstalling。会把安装包的信息通过 Intent 传递到 InstallInstalling 这个 Activity。

InstallInstalling


frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

/**

* Send package to the package manager and handle results from package manager. Once the

* installation succeeds, start {@link InstallSuccess} or {@link InstallFailed}.

This has two phases: First send the data to the package manager, then wait until the package

* manager processed the result.

*/

public class InstallInstalling extends AlertActivity {

}

在这个页面点击安装时,InstallInstalling 的作用主要是向 PMS 发送包信息以及处理回调。 这有两个阶段:

  • 首先将数据发送给 PackageManager ;

  • 等待 PackageManager 处理结果(InstallSuccess 或 InstallFailed)。

看到 Activity 当然是先从 onCreate() 开始了

onCreat()

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

ApplicationInfo appInfo = getIntent()

.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);

//要安装的包的 URI

mPackageURI = getIntent().getData();

if (“package”.equals(mPackageURI.getScheme())) {

try {

//注释1:安装现有包

getPackageManager().installExistingPackage(appInfo.packageName);

//安装成功页面

launchSuccess();

} catch (PackageManager.NameNotFoundException e) {

//安装失败页面

launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);

}

} else {

//注释2:没有现有包

//根据 mPackageURI 创建一个对应的 File

final File sourceFile = new File(mPackageURI.getPath());

//显示应用信息 icon,应用名

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.setPackage(getPackageName());

broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

PendingIntent pendingIntent = PendingIntent.getBroadcast(

InstallInstalling.this,

mInstallId,

broadcastIntent,

PendingIntent.FLAG_UPDATE_CURRENT);

// 调用 PackageInstaller.Session 的 commit 方法,进行安装

session.commit(pendingIntent.getIntentSender());

mCancelButton.setEnabled(false);

setFinishOnTouchOutside(false);

} else {

getPackageManager().getPackageInstaller().abandonSession(mSessionId);

if (!isCancelled()) {

launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);

}

}

}

}

其他没啥好看的,咱么看看具体的session.commit

PackageInstaller.commit()


public void commit(@NonNull IntentSender statusReceiver) {

try {

mSession.commit(statusReceiver, false);

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

mSession 就是 IPackageInstallerSession 。这说明要通过 IPackageInstallerSession 来进行进程间的通信,最终会调用PackageInstallerSession 的 commit 方法

PackageInstallerSession


frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

public class PackageInstallerSession extends IPackageInstallerSession.Stub {

}

commit()

@Override

public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {

if (hasParentSessionId()) {

throw new IllegalStateException(

"Session " + sessionId + " is a child of multi-package session "

+ mParentSessionId +  " and may not be committed directly.");

}

if (!markAsSealed(statusReceiver, forTransfer)) {

return;

}

//return true 多个包

if (isMultiPackage()) {

}

dispatchStreamValidateAndCommit();

}

dispatchStreamValidateAndCommit()

private void dispatchStreamValidateAndCommit() {

// 通过 Handler 处理消息事件

mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();

}

mHandler()

Handler mHandler = new Handler(looper, mHandlerCallback);

private final Handler.Callback mHandlerCallback = new Handler.Callback() {

@Override

public boolean handleMessage(Message msg) {

switch (msg.what) {

case MSG_STREAM_VALIDATE_AND_COMMIT:

handleStreamValidateAndCommit();

break;

}

return true;

}

};

handleStreamValidateAndCommit()

private void handleStreamValidateAndCommit() {

PackageManagerException unrecoverableFailure = null;

// 这将跟踪会话和任何子项是否已通过验证并准备好进入下一安装阶段

boolean allSessionsReady = false;

try {

allSessionsReady = streamValidateAndCommit();

} catch (PackageManagerException e) {

unrecoverableFailure = e;

}

//多包,不是多包直接过

if (isMultiPackage()) {

}

if (!allSessionsReady) {

return;

}

// 通过 Handler 处理MSG_INSTALL消息事件

mHandler.obtainMessage(MSG_INSTALL).sendToTarget();

}

mHandler()

Handler mHandler = new Handler(looper, mHandlerCallback);

private final Handler.Callback mHandlerCallback = new Handler.Callback() {

@Override

public boolean handleMessage(Message msg) {

switch (msg.what) {

case MSG_INSTALL:

handleInstall();

break;

}

return true;

}

};

handleInstall()

private void handleInstall() {

//return true 会话被再次启用。

if (params.isStaged) {

mStagingManager.commitSession(this);

destroyInternal();

dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, “Session staged”, null);

return;

}

//安装 APEX 包,则返回 true。

if (isApexInstallation()) {

destroyInternal();

dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,

“APEX packages can only be installed using staged sessions.”, null);

return;

}

// 对于 multiPackage 会话,读取锁外的子会话,

// 因为读取持有锁的子会话可能会导致死锁 (b/123391593)。

List childSessions = getChildSessionsNotLocked();

try {

synchronized (mLock) {

//接下来咱们就看看这个方法。

installNonStagedLocked(childSessions);

}

} catch (PackageManagerException e) {

final String completeMsg = ExceptionUtils.getCompleteMessage(e);

Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);

destroyInternal();

dispatchSessionFinished(e.error, completeMsg, null);

}

}

installNonStagedLocked()

@GuardedBy(“mLock”)

private void installNonStagedLocked(List childSessions)

throws PackageManagerException {

final PackageManagerService.ActiveInstallSession installingSession =

makeSessionActiveLocked();

if (installingSession == null) {

return;

}

//return true 多个包

if (isMultiPackage()) {

List<PackageManagerService.ActiveInstallSession> installingChildSessions =

new ArrayList<>(childSessions.size());

mPm.installStage(installingChildSessions);

} else {

mPm.installStage(installingSession);

}

}

这里不管不管怎么样都会调用 mPm.installStage(installingChildSessions);

mPm 就是系统服务 PackageManagerService。

PackageManagerService


frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub

implements PackageSender {

}

installStage()

installStage 方法就是正式开始 apk 的安装过程。这个过程包括两大步:

1、拷贝安装包;

2、装载代码。

void installStage(ActiveInstallSession activeInstallSession) {

final Message msg = mHandler.obtainMessage(INIT_COPY);

//把之前传入的 sessionParams 安装信息,及其它信息封装成 InstallParams

final InstallParams params = new InstallParams(activeInstallSession);

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);

}

void installStage(List children)

throws PackageManagerException {

final Message msg = mHandler.obtainMessage(INIT_COPY);

final MultiPackageInstallParams params =

new MultiPackageInstallParams(UserHandle.ALL, children);

params.setTraceMethod(“installStageMultiPackage”)

.setTraceCookie(System.identityHashCode(params));

msg.obj = params;

Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, “installStageMultiPackage”,

System.identityHashCode(msg.obj));

Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, “queueInstall”,

System.identityHashCode(msg.obj));

mHandler.sendMessage(msg);

}

MultiPackageInstallParams:多包安装的容器,指的是一起提交的所有安装会话和参数。

这两个方法很详细就是把之前传入的 sessionParams 安装信息及其它信息封装成 InstallParams(MultiPackageInstallParams)。

mHandler 发送的消息 INIT_COPY 从名字上就知道是去初始化复制。

mHandler()

class PackageHandler extends Handler {

PackageHandler(Looper looper) {

super(looper);

}

public void handleMessage(Message msg) {

try {

doHandleMessage(msg);

} finally {

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

}

}

void doHandleMessage(Message msg) {

switch (msg.what) {

case INIT_COPY: {

HandlerParams params = (HandlerParams) msg.obj;

if (params != null) {

if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);

Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, “queueInstall”,

System.identityHashCode(params));

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “startCopy”);

params.startCopy();

Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

}

break;

}

}

}

}

HandlerParams.startCopy()

private abstract class HandlerParams {

/** User handle for the user requesting the information or installation. */

private final UserHandle mUser;

String traceMethod;

int traceCookie;

final void startCopy() {

if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);

handleStartCopy();

handleReturnCode();

}

abstract void handleStartCopy();

abstract void handleReturnCode();

}

startCopy(),里面有两个抽象方法,咱只能去找他的实现类 InstallParams 里面的这两个方法了。

InstallParams

class InstallParams extends HandlerParams {

/*

* 调用远程方法来获取包信息和安装位置值。

* 如果需要,根据默认策略覆盖安装位置,然后根据安装位置创建安装参数。

*/

public void handleStartCopy() {

int ret = PackageManager.INSTALL_SUCCEEDED;

// 表示文件已下载,不需要再次下载。

if (origin.staged) {

// 设置安装标志位,决定是安装在手机内部存储空间还是 sdcard 中

if (origin.file != null) {

installFlags |= PackageManager.INSTALL_INTERNAL;

} else {

throw new IllegalStateException(“Invalid stage location”);

}

}

// 判断安装位置

final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;

final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;

PackageInfoLite pkgLite = null;

//解析给定的包并返回最少的细节。

pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,

origin.resolvedPath, installFlags, packageAbiOverride);

if (DEBUG_INSTANT && ephemeral) {

Slog.v(TAG, "pkgLite for install: " + pkgLite);

}

/*

* 如果我们的可用空间太少,请在放弃之前尝试释放缓存。

*/

if (!origin.staged && pkgLite.recommendedInstallLocation

== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {

// TODO: 释放目标设备上的磁盘空间

final StorageManager storage = StorageManager.from(mContext);

//返回给定路径被(Environment.getDataDirectory())认为存储空间不足的可用字节数。

final long lowThreshold = storage.getStorageLowBytes(

Environment.getDataDirectory());

//返回:-1 计算安装包大小有错误

//返回其他:安装包大小。

final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(

origin.resolvedPath, packageAbiOverride);

if (sizeBytes >= 0) {

try {

//用于权限提升。

mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);

pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,

origin.resolvedPath, installFlags, packageAbiOverride);

} catch (InstallerException e) {

Slog.w(TAG, “Failed to free cache”, e);

}

}

/*

* 缓存删除了我们下载安装的文件。

* 用于存储错误

*/

if (pkgLite.recommendedInstallLocation

== PackageHelper.RECOMMEND_FAILED_INVALID_URI) {

pkgLite.recommendedInstallLocation

= PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;

}

}

//安装返回码

if (ret == PackageManager.INSTALL_SUCCEEDED) {

//指定推荐的安装位置。 可以是其中之一

//RECOMMEND_INSTALL_INTERNAL 安装在内部存储上,

//RECOMMEND_INSTALL_EXTERNAL 安装在外部媒体上,

//RECOMMEND_FAILED_INSUFFICIENT_STORAGE 用于存储错误,

//或 RECOMMEND_FAILED_INVALID_APK 解析错误。

int loc = pkgLite.recommendedInstallLocation;

}

//创建安装参数

final InstallArgs args = createInstallArgs(this);

mVerificationCompleted = true;

mIntegrityVerificationCompleted = true;

mEnableRollbackCompleted = true;

mArgs = args;

if (ret == PackageManager.INSTALL_SUCCEEDED) {

final int verificationId = mPendingVerificationToken++;

// 执行安装包验证(除非我们只是简单地移动装包)。

if (!origin.existing) {

}

//INSTALL_ENABLE_ROLLBACK 的标志参数以指示应为此安装启用回滚。

if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {

// TODO(ruhler) b/112431924: 在“move”的情况下不要这样做?

final int enableRollbackToken = mPendingEnableRollbackToken++;

Trace.asyncTraceBegin(

TRACE_TAG_PACKAGE_MANAGER, “enable_rollback”, enableRollbackToken);

mPendingEnableRollback.append(enableRollbackToken, this);

Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK);

enableRollbackIntent.putExtra(

PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,

enableRollbackToken);

enableRollbackIntent.putExtra(

PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,

mSessionId);

enableRollbackIntent.setType(PACKAGE_MIME_TYPE);

enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

//允许在启动完成前发送广播。 在早期启动中提交分阶段会话的 apk 部分时需要这样做。 回滚管理器在启动过程中足够早地注册其接收器,以免错过广播。

// 在早期启动中提交分阶段会话的 apk 部分时需要这样做。

// 回滚管理器在启动过程中足够早地注册其接收器,以免错过广播。

enableRollbackIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

mContext.sendOrderedBroadcastAsUser(enableRollbackIntent, UserHandle.SYSTEM,

android.Manifest.permission.PACKAGE_ROLLBACK_AGENT,

new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

// 等待回滚启用的持续时间,以毫秒为单位

long rollbackTimeout = DeviceConfig.getLong(

DeviceConfig.NAMESPACE_ROLLBACK,

PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,

DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS);

if (rollbackTimeout < 0) {

rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS;

}

final Message msg = mHandler.obtainMessage(

ENABLE_ROLLBACK_TIMEOUT);

msg.arg1 = enableRollbackToken;

msg.arg2 = mSessionId;

mHandler.sendMessageDelayed(msg, rollbackTimeout);

}

}, null, 0, null, null);

mEnableRollbackCompleted = false;

}

}

mRet = ret;

}

@Override

void handleReturnCode() {

if (mVerificationCompleted

&& mIntegrityVerificationCompleted && mEnableRollbackCompleted) {

//INSTALL_DRY_RUN :installPackage 的标志参数,指示只应验证包而不应安装包。

if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {

}

if (mRet == PackageManager.INSTALL_SUCCEEDED) {

//注释1

mRet = mArgs.copyApk();

}

//注释2

processPendingInstall(mArgs, mRet);

}

}

}

}

注释1:mArgs 其实就是 InstallArgs ,而 InstallArgs 则是通过 createInstallArgs(this); 创建如下代码: createInstallArgs(this)

private InstallArgs createInstallArgs(InstallParams params) {

if (params.move != null) {

//处理现有已安装应用程序移动的逻辑。

return new MoveInstallArgs(params);

} else {

//处理新应用程序安装的逻辑,包括复制和重命名逻辑。

return new FileInstallArgs(params);

}

}

这里createInstallArgs 返回的是 FileInstallArgs 对象。

FileInstallArgs.copyApk()

拷贝部分

class FileInstallArgs extends InstallArgs {

private File codeFile;

private File resourceFile;

// Example topology:

// /data/app/com.example/base.apk

// /data/app/com.example/split_foo.apk

// /data/app/com.example/lib/arm/libfoo.so

// /data/app/com.example/lib/arm64/libfoo.so

// /data/app/com.example/dalvik/arm/base.apk@classes.dex

/** New install */

FileInstallArgs(InstallParams params) {

super(params);

}

/** Existing install */

FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {

super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,

null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,

PackageParser.SigningDetails.UNKNOWN,

PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT,

false, null /* parent */, DataLoaderType.NONE);

this.codeFile = (codePath != null) ? new File(codePath) : null;

this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;

}

//执行此处方法

int copyApk() {

try {

//就调用个doCopyApk(),接着往下看

return doCopyApk();

} finally {

}

}

private int doCopyApk() {

//表示文件已下载

if (origin.staged) {

if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");

//获取安装包路径

codeFile = origin.file;

resourceFile = origin.file;

return PackageManager.INSTALL_SUCCEEDED;

}

try {

final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;

//创建路径

final File tempDir =

mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);

codeFile = tempDir;

resourceFile = tempDir;

} catch (IOException e) {

Slog.w(TAG, "Failed to create copy file: " + e);

return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;

}

//将包复制到目标位置(origin.file.getAbsolutePath())。

//返回状态码。注释3

int ret = PackageManagerServiceUtils.copyPackage(

origin.file.getAbsolutePath(), codeFile);

if (ret != PackageManager.INSTALL_SUCCEEDED) {

Slog.e(TAG, “无法复制安装包”);

return ret;

}

final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath());

final File libraryRoot = new File(codeFile, LIB_DIR_NAME);

NativeLibraryHelper.Handle handle = null;

try {

handle = NativeLibraryHelper.Handle.create(codeFile);

// 将 apk 中的动态库 .so 文件也拷贝到目标路径中。

ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,

abiOverride, isIncremental);

} catch (IOException e) {

Slog.e(TAG, “Copying native libraries failed”, e);

ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;

} finally {

IoUtils.closeQuietly(handle);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后

由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
origin.file.getAbsolutePath(), codeFile);

if (ret != PackageManager.INSTALL_SUCCEEDED) {

Slog.e(TAG, “无法复制安装包”);

return ret;

}

final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath());

final File libraryRoot = new File(codeFile, LIB_DIR_NAME);

NativeLibraryHelper.Handle handle = null;

try {

handle = NativeLibraryHelper.Handle.create(codeFile);

// 将 apk 中的动态库 .so 文件也拷贝到目标路径中。

ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,

abiOverride, isIncremental);

} catch (IOException e) {

Slog.e(TAG, “Copying native libraries failed”, e);

ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;

} finally {

IoUtils.closeQuietly(handle);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-NwvjIPWf-1712605071300)]
[外链图片转存中…(img-xxfoWVX4-1712605071300)]
[外链图片转存中…(img-jdUde5rh-1712605071301)]
[外链图片转存中…(img-lrzm3iv6-1712605071301)]
[外链图片转存中…(img-yGMupXVS-1712605071302)]
[外链图片转存中…(img-MnIQkqIc-1712605071302)]
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-YGnMyxKo-1712605071303)]

最后

由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-MyFHXbq1-1712605071303)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值