How to add a View to an app from another app

泄露秘密 提交于 2019-12-04 13:30:24

First thing, it seems you don't need RemoteViews at all, you can instantiate the view in your process and attach them to the Activity.

Then you need to clarify with yourself one thing: do you need to load classes at runtime? This would be the case if you want to use new classes in your app without updating it. This is not trivial, you will be forced to use some already defined interfaces in your app or crawl your way through it with reflection. It would be a pain.

Another, much simpler option would be to download an xml layout for each of your views and associated with that a configuration file which could describe some behaviors. If you decide to load classes at runtime from an external plugin, you could go this way:

  • define a ViewCreator class inside a library
  • when you want to create a plugin you need to make an apk which contains one (or more?) of these ViewCreator class
  • in your app you then load the apk with DexClassLoader, find the ViewCreator class and instantiate it
  • the ViewCreator instance can then generate your View

This approach gives you a tremendous power, far beyond mere View instantiation, but it brings also a lot of complexity. If you're doing this for fun, well, I think you're on the right track, however I wouldn't recommend to do this for a commercial project. I created a sample repository with a minimal working example here.

The bulk of this approach is that you create a "plugins" library which will contain the common interfaces for your app and each plugin. In my sample, the library contains only one class:

public abstract class AbstractViewCreator {

    private final Context context;

    public AbstractViewCreator(Context context) {
        this.context = context;
    }

    public abstract View createView();

    protected Context getContext() {
        return context;
    }
}

Then you need to create a "plugin" app, in the sample is PluginA. This app must contain one implementation of AbstractViewCreator. Then the NiceApp needs to download the plugin apk, in the sample the apk is copied into the assets folder. After that you need to load the apk:

DexClassLoader dexClassLoader = new DexClassLoader(apkPath, codeCachePath, librariesPath, parentClassLoader);

then you need to load a class, you could derive the name of the class you want to load, for instance:

String className = "com.lelloman." + assetsFileName.replace(".apk", "").toLowerCase() + ".MyViewCreator");
Class fooClass = dexClassLoader.loadClass(className);

Then get the constructor and instantiate the ViewCreator via reflection

Constructor constructor = myClass.getConstructor(Context.class);
AbstractViewCreator creator = (AbstractViewCreator) constructor.newInstance(context);

then you can create your View

View viewFromPlugin = creator.createView();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!