1.背景
在进行插件解耦化开发时,为了减轻宿主APP的负担,会适当将某些定制性Feature的代码剥离出去,改为以另外一个apk/jar的形式定制化集成. 本质上该部分代码还是需要运行在宿主APP进程中. 有时候需要用到宿主APP外的Context上下文.
2.简单用法
简单用法如下:
Context pluginContext = context.createPackageContext(包名, Context.CONTEXT_INCLUDE_CODE);
但是遗憾的是会抛出SecurityException, 原因是不推荐这种做法,让一个外包的代码插入到一个宿主apk里边来执行,有很大的安全风险.
2.1 运行报错
报错log如下:
07-04 15:27:13.166 7507 7507 D PreFragment: java.lang.SecurityException: Requesting code from com.xsq.testdemo (with uid 10191) to be run in process com.start.testdemo (with uid 10185)
07-04 15:27:13.166 7507 7507 D PreFragment: at android.app.ActivityThread.getPackageInfo(ActivityThread.java:2866)
07-04 15:27:13.166 7507 7507 D PreFragment: at android.app.ActivityThread.getPackageInfo(ActivityThread.java:2840)
07-04 15:27:13.166 7507 7507 D PreFragment: at android.app.ContextImpl.createPackageContextAsUser(ContextImpl.java:2745)
07-04 15:27:13.166 7507 7507 D PreFragment: at android.app.ContextImpl.createPackageContext(ContextImpl.java:2730)
07-04 15:27:13.166 7507 7507 D PreFragment: at android.content.ContextWrapper.createPackageContext(ContextWrapper.java:1092)
07-04 15:27:13.166 7507 7507 D PreFragment: at android.content.ContextWrapper.createPackageContext(ContextWrapper.java:1092)
07-04 15:27:13.166 7507 7507 D PreFragment: at com.start.testdemo.utils.Utils.testPathClassLoader(Utils.java:208)
2.2报错代码追踪
2.2.1 API声明
/Sdk/sources/android-33/android/content/Context.java
/**
* Return a new Context object for the given application name. This
* Context is the same as what the named application gets when it is
* launched, containing the same resources and class loader. Each call to
* this method returns a new instance of a Context object; Context objects
* are not shared, however they share common state (Resources, ClassLoader,
* etc) so the Context instance itself is fairly lightweight.
*
* <p>Throws {@link android.content.pm.PackageManager.NameNotFoundException} if there is no
* application with the given package name.
*
* <p>Throws {@link java.lang.SecurityException} if the Context requested
* can not be loaded into the caller's process for security reasons (see
* {@link #CONTEXT_INCLUDE_CODE} for more information}.
*
* @param packageName Name of the application's package.
* @param flags Option flags.
*
* @return A {@link Context} for the application.
*
* @throws SecurityException
* @throws PackageManager.NameNotFoundException if there is no application with
* the given package name.
*/
public abstract Context createPackageContext(String packageName,
@CreatePackageOptions int flags) throws PackageManager.NameNotFoundException;
/**
* Flag for use with {@link #createPackageContext}: include the application
* code with the context. This means loading code into the caller's
*