Application.getApplicationInfo()

2023-08-24  本文已影响0人  行走中的3卡

基于ActivityThread 中一些常用的知识点记录
的拓展,分析一下通过 ActivityThread 获取 applicationInfo 对象的差异。
applicationInfo 包含当前应用的大部分信息,因此是个很重要的部分

1. ActivityThread.currentApplication().getApplicationInfo()

获取到应用进程的loadedApk对象的 applicationInfo
Application -> ContextWrapper -> ContextImpl 成员变量 mLoadedApk.getApplicationInfo

2. ActivityThread.currentApplication().getBaseContext().createPackageContextAsUser(packageName, 0, new UserHandle(userId)).getApplicationInfo()

获取到缓存的loadedApk的 applicationInfo

a.先获取context (根据activityThread / loadedApp 新建一个)
Application -> ContextWrapper.getBaseContext -> ContextImpl.createPackageContextAsUser()
这时会通过 ActivityThread.getPackageInfo() 查找缓存中的loadedApp, 然后再创建 ContextImpl

b.在获取applicationInfo 对象

3. 总结:

(1) (2) 最终都是通过 ContextImpl.getApplicationInfo(), 差异就在于他们可能是不同的对象,
导致 mPackageInfo 即 loadedApp 对象是不一样的, 例如前者是 应用进程 最新的, 而后者 是 ActivityThread缓存中的(mResourcePackages)

//ContextImpl.java
class ContextImpl extends Context {
    @UnsupportedAppUsage
    final @NonNull LoadedApk mPackageInfo;

   @Override
    public ApplicationInfo getApplicationInfo() {
        if (mPackageInfo != null) {
            return mPackageInfo.getApplicationInfo();
        }
        throw new RuntimeException("Not supported in system context");
    }
}

// LoadedApk.java
public final class LoadedApk {
    @UnsupportedAppUsage
    private ApplicationInfo mApplicationInfo;
    @UnsupportedAppUsage
    public ApplicationInfo getApplicationInfo() {
        return mApplicationInfo;
    }
}

注意:
(1) ActivityThread.currentApplication().getBaseContext() 确保的是当前进程调用的,即userId 一致.
(2) context.createApplicationContext(mApplication,Context.CONTEXT_RESTRICTED)
这里的 context 不一定的是和mApplication(applicationInfo) 同一个userId的, 所以可能导致无法从 ActivityThread的缓存中取LoadedApk的对象

上一篇 下一篇

猜你喜欢

热点阅读