代码之家  ›  专栏  ›  技术社区  ›  RickNotFred

android,如何使用dexclassloader动态替换活动或服务

  •  17
  • RickNotFred  · 技术社区  · 16 年前

    我正试着做类似的事情 stackoverflow posting 是的。我想做的是从SD卡中读取活动或服务的定义。为了避免清单权限问题,我在.apk中创建了此活动的shell版本,但在运行时尝试将其替换为SD卡上驻留的同名活动。不幸的是,我可以使用dexclassloader从SD卡加载活动类定义,但是原始的类定义是执行的。有没有办法指定新的类定义替换旧的类定义,或者有没有办法在不实际提供包中所需活动的情况下避免清单权限问题?代码示例:

        ClassLoader cl = new DexClassLoader("/sdcard/mypath/My.apk",
                getFilesDir().getAbsolutePath(),
                null,
                MainActivity.class.getClassLoader());
    
        try {
            Class<?> c = cl.loadClass("com.android.my.path.to.a.loaded.activity");
            Intent i = new Intent(getBaseContext(), c);
            startActivity(i);
        }
        catch (Exception e) {
    

    发射互联网 com.android.my.path.to.a.loaded.activity 指定于 /sdcard/mypath/My.apk ,它启动静态加载到项目中的活动。

    1 回复  |  直到 9 年前
        1
  •  15
  •   rdb    13 年前

    通过dexclassloader启动一个活动将是非常棘手的,因为您没有安装apk,所以没有什么可以处理您的意图。

    您的平台apk中应该有相同的activity类,并在androidmanifest.xml中声明它。然后,您应该将当前的类加载器更改为所需的dexclassloader。因此,它将启动你的插件apk。(注意:“platform apk”是指手机中已经安装的应用程序,而“plugin apk”是指存储在SD卡中的APK文件。)

    平台的应用程序应该如下所示:

    public static ClassLoader ORIGINAL_LOADER;
    public static ClassLoader CUSTOM_LOADER = null;
    
    @Override
    public void onCreate() {
        super.onCreate();
        try {
            Context mBase = new Smith<Context>(this, "mBase").get();
    
            Object mPackageInfo = new Smith<Object>(mBase, "mPackageInfo")
                    .get();
            //get Application classLoader
            Smith<ClassLoader> sClassLoader = new Smith<ClassLoader>(
                    mPackageInfo, "mClassLoader");
            ClassLoader mClassLoader = sClassLoader.get();
            ORIGINAL_LOADER = mClassLoader;
    
            MyClassLoader cl = new MyClassLoader(mClassLoader);
            //chage current classLoader to MyClassLoader
            sClassLoader.set(cl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    class MyClassLoader extends ClassLoader {
        public MyClassLoader(ClassLoader parent) {
            super(parent);
        }
    
        @Override
        public Class<?> loadClass(String className)
                throws ClassNotFoundException {
            if (CUSTOM_LOADER != null) {
                try {
                    Class<?> c = CUSTOM_LOADER.loadClass(className);
                    if (c != null)
                        return c;
                } catch (ClassNotFoundException e) {
                }
            }
            return super.loadClass(className);
        }
    }
    

    有关更多代码,请访问 https://github.com/Rookery/AndroidDynamicLoader

    我正在阅读android源代码,以便找到一个更优雅的方法来实现这个特性。如果你有任何想法,请随时与我联系。