You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发:基于Package Visibility实现App B无感加载App A的库

分步实现流程:基于Package Visibility的跨App无感知库加载

一、配置App A(库宿主)

  • 确定App A的包名(例如com.example.libraryhost),将需要共享的库(自定义工具类、第三方SDK、原生so等)放入APK的assets、res/raw或libs目录,保证APK可正常安装。
  • (可选)在AndroidManifest.xml中声明自定义权限,限制只有授权App能访问:
    <permission android:name="com.example.libraryhost.PERMISSION_ACCESS_LIBRARY"
        android:protectionLevel="normal" />
    

二、配置App B的Package Visibility

  • 在App B的AndroidManifest.xml中添加包可见性声明,让系统允许B获取App A的安装信息:
    <queries>
        <package android:name="com.example.libraryhost" />
    </queries>
    
  • (可选)如果App A声明了自定义权限,在App B中添加权限引用:
    <uses-permission android:name="com.example.libraryhost.PERMISSION_ACCESS_LIBRARY" />
    

三、App B中动态加载App A的库

1. 获取App A的APK路径

通过PackageManager获取App A的安装路径:

PackageManager pm = getPackageManager();
try {
    ApplicationInfo appInfo = pm.getApplicationInfo("com.example.libraryhost", 0);
    String apkPath = appInfo.sourceDir; // App A的APK绝对路径
} catch (PackageManager.NameNotFoundException e) {
    // 处理App A未安装的异常,比如静默引导安装或提示用户
    e.printStackTrace();
}

2. 加载Dex类库

使用DexClassLoader加载APK中的dex文件,需指定App B的私有缓存目录用于解压dex:

File dexCacheDir = getCacheDir();
DexClassLoader dexLoader = new DexClassLoader(
    apkPath,
    dexCacheDir.getAbsolutePath(),
    null, // 若有so库,可指定so目录路径
    getClassLoader() // 父类加载器,保证类加载优先级
);

// 加载并调用目标类
try {
    Class<?> targetClass = dexLoader.loadClass("com.example.libraryhost.utils.MyUtils");
    Object instance = targetClass.getDeclaredConstructor().newInstance();
    Method method = targetClass.getMethod("doBusinessLogic");
    method.invoke(instance);
} catch (Exception e) {
    e.printStackTrace();
}

3. 加载原生SO库

若App A包含so库,需先将so从APK解压到App B私有目录,再加载:

// 解压APK中的so文件
ZipFile zipFile = new ZipFile(apkPath);
ZipEntry soEntry = zipFile.getEntry("lib/armeabi-v7a/libmylib.so");
if (soEntry != null) {
    InputStream is = zipFile.getInputStream(soEntry);
    File soDestFile = new File(getDir("libs", MODE_PRIVATE), "libmylib.so");
    FileOutputStream os = new FileOutputStream(soDestFile);
    
    byte[] buffer = new byte[1024];
    int len;
    while ((len = is.read(buffer)) != -1) {
        os.write(buffer, 0, len);
    }
    os.close();
    is.close();
    zipFile.close();
    
    // 加载so库
    System.load(soDestFile.getAbsolutePath());
}

四、实现无感知体验优化

  • 启动检查:App B启动时先判断App A是否安装,未安装则静默触发安装(需申请安装权限),避免用户感知。
  • 缓存复用:第一次加载后,将解压的dex/so缓存到私有目录,后续启动直接读取缓存,减少耗时。
  • API封装:把跨App加载逻辑封装成单例工具类,对外暴露和App B本地库一致的接口,业务代码无需感知库来源。

五、关键注意事项

  • 版本兼容:确保App A和App B的minSdkVersion匹配,处理不同Android版本的类加载差异。
  • 权限控制:所有文件操作使用App B私有目录,避免权限错误。
  • 混淆配置:App A中需要被加载的类,要在混淆规则中排除,防止混淆后无法反射调用。
  • 签名校验:让App A和App B使用同一签名,代码中验证签名,防止恶意App冒充库宿主。

内容的提问来源于stack exchange,提问作者Muthyam Sriram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:12:49