/**
* 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.
*
* Throws {@link PackageManager.NameNotFoundException} if there is no
* application with the given package name.
*
* 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, one of {@link #CONTEXT_INCLUDE_CODE}
* or {@link #CONTEXT_IGNORE_SECURITY}.
*
* @return A Context for the application.
*
* @throws java.lang.SecurityException
* @throws PackageManager.NameNotFoundException if there is no application with
* the given package name
*/
Override
public Context createPackageContext(String packageName, int flags)
throws PackageManager.NameNotFoundException {
if (packageName.equals(“system”) || packageName.equals(“android”)) {
final ContextImpl context = new ContextImpl(mMainThread.getSystemContext());
context.mBasePackageName = mBasePackageName;
return context;
}
LoadedApk pi =
mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags);
if (pi != null) {
ContextImpl c = new ContextImpl();
c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
c.init(pi, null, mMainThread, mResources, mBasePackageName);
if (c.mResources != null) {
return c;
}
}
// Should be a better exception.
throw new PackageManager.NameNotFoundException(
“Application package “ + packageName + ” not found”);
}
主要作用是:创建其它程序的Context,通过创建的这个Context,就可以访问该软件包的资源,甚至可以执行其它软件包的代码。
使用:
- <span class="keyword">try</span> {
- Context c = createPackageContext(<span class="string">“com.dolphin.demo”</span>, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
- } <span class="keyword">catch</span> (SecurityException e) {
- e.printStackTrace();
- } <span class="keyword">catch</span> (Exception e) {
- e.printStackTrace();
- }
通常一个软件是不能创建其它程序的Context的,除非它们拥有相同的用户ID与签名。用户ID是一个字符串标识,在程序的AndroidManifest.xml文件的manifest标签中指定,格式为android:shareUserId=”**”。安装在设备中的每一个apk程序,Android系统会给其分配一个单独的用户空间,其中android:shareUserId就是对应一个Linux用户ID,并且为它创建一个沙箱,以防止与其它应用程序产生影响。用户ID 在应用程序被安装到设备中时分配。通过SharedUserid,拥有同一个Userid的多个APK可以配置成运行在同一个进程中,所以默认就是可以互相访问任意数据,也可以配置成运行在不同的进程中, 同时可以访问其APK的数据目录下的资源(图片,数据库和文件),就像访问本程序的数据一样。
经常的用途:
如经常一些应用提供的换皮肤功能,实现方法大致有两种:
1)把需要替换的资源图片打包好之后,放在客户端指定的目录下面,切换皮肤,查找相应的资源时,直接切换资源查找的路径到该打包文件中对应的资源路径即可。
2)把需要替换的资源,放在一个空的android 应用程序的drawable-**目录下面即可,编译,运行该apk,查找资源时,就需要用到createPackageContext获取对应包名的Context实例,然后通过context来查找对应的资源。查找时,也有两种方式:
2.1)通过ID来查找资源图片;
2.2)通过资源Name,反推出资源ID,然后查找对应的资源图片;
💬 评论