首页 > 系统 > Android > 正文

Android 中的CreatePackageContext()

2019-11-08 00:05:11
字体:
来源:转载
供稿:网友
[java] view plain copy PRint?在CODE上查看代码片/**      * 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 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, 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");      }   %20 %20主要作用是:创建其它程序的Context,通过创建的这个Context,就可以访问该软件包的资源,甚至可以执行其它软件包的代码。 %20   %20 %20使用: %20  [java] view%20plain copy print?try {         Context c = createPackageContext("com.dolphin.demo", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);     } catch (SecurityException e) {         e.printStackTrace();     } catch (Exception e) {         e.printStackTrace();     }   %20 %20通常一个软件是不能创建其它程序的Context的,除非它们拥有相同的用户ID与签名。用户ID是一个字符串标识,在程序的AndroidManifest.xml文件的manifest标签中指定,格式为android:shareUserId="**"。安装在设备中的每一个apk程序,Android系统会给其分配一个单独的用户空间,其中android:shareUserId就是对应一个linux用户ID,并且为它创建一个沙箱,以防止与其它应用程序产生影响。用户ID%20在应用程序被安装到设备中时分配。通过SharedUserid,拥有同一个Userid的多个APK可以配置成运行在同一个进程中,所以默认就是可以互相访问任意数据,也可以配置成运行在不同的进程中,%20同时可以访问其APK的数据目录下的资源(图片,数据库和文件),就像访问本程序的数据一样。 %20   %20 经常的用途: %20 如经常一些应用提供的换皮肤功能,实现方法大致有两种: %20 1)把需要替换的资源图片打包好之后,放在客户端指定的目录下面,切换皮肤,查找相应的资源时,直接切换资源查找的路径到该打包文件中对应的资源路径即可。 %20 2)把需要替换的资源,放在一个空的android%20应用程序的drawable-**目录下面即可,编译,运行该apk,查找资源时,就需要用到createPackageContext获取对应包名的Context实例,然后通过context来查找对应的资源。查找时,也有两种方式: %20 2.1)通过ID来查找资源图片; %20 %20 %20 [java] view%20plain copy print?Context context;           try {               context = createPackageContext("com.dolphin.demo", Context.CONTEXT_INCLUDE_CODE                       | Context.CONTEXT_IGNORE_SECURITY);               txvA.setText(context.getResources().getText(R.string.message));           } catch (NameNotFoundException e) {               e.printStackTrace();           }    %20 %20 %20   %20 2.2)通过资源Name,反推出资源ID,然后查找对应的资源图片; %20 [java] view%20plain copy print?派生到我的代码片/***       * @param clazz 目标资源的R.java       * @param className R.java的内部类,如layout,string,drawable...       * @param name 资源名称       * @return       */       private int getResourseIdByName(Class clazz, String className, String name) {           int id = 0;           try {                  Class[] classes = clazz.getClasses(); // 获取R.java里的所有静态内部类               Class desireClass = null;                  for (int i = 0; i < classes.length; i++) {                   if (classes[i].getName().split("//$")[1].equals(className)) {                     desireClass = classes[i];                       break;                   }               }               if (desireClass != null)                   id = desireClass.getField(name).getInt(desireClass);         } catch (IllegalArgumentException e) {               e.printStackTrace();           } catch (SecurityException e) {               e.printStackTrace();           } catch (IllegalaccessException e) {               e.printStackTrace();           } catch (NoSuchFieldException e) {               e.printStackTrace();           }              return id;       }               Context context;       try {           context = createPackageContext("com.dolphin.demo", Context.CONTEXT_INCLUDE_CODE                   | Context.CONTEXT_IGNORE_SECURITY);           Class cls = context.getClassLoader().loadClass("com.dolphin.demo.R"); // 获得目标apk的R类           txvA.setText(context.getResources().getText(getResourseIdByName(cls, "string", "message")));       } catch (NameNotFoundException e) {           e.printStackTrace();       } catch (ClassNotFoundException e) {           e.printStackTrace();       }        
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表