android-使用DexClassLoader与动态加载的库进行交互

android-使用DexClassLoader与动态加载的库进行交互,第1张

概述我正在使用DexClassLoader类从SD卡在运行时加载jar文件finalStringlibPath=Environment.getExternalStorageDirectory()+"est.jar";finalFiletmpDir=getDir("dex",0);finalDexClassLoaderclassloader=newDexClassLoader(lib

我正在使用DexClassLoader类从SD卡在运行时加载jar文件

  final String libPath = Environment.getExternalStorageDirectory() +     "/test.jar";        final file tmpDir = getDir("dex", 0);        final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getabsolutePath(), null, this.getClass().getClassLoader());        final Class<Object> classtoload = (Class<Object>) classloader.loadClass("org.shlublu.androID.sandBox.MyClass");        final Object myInstance  = classtoload.newInstance();        final Method doSomething = classtoload.getmethod("doSomething");        doSomething.invoke(myInstance);

在我的jar文件中,我正在打印一些运行良好的日志.现在我要执行的 *** 作是从jar文件中打印Toast.在执行此 *** 作时,我得到的异常是java.lang.reflect.InvocationTargetException.我知道为什么我们得到这个异常,其背后的原因是在打印吐司时使用它的上下文中的nullpointer异常.所以它不是重复的

What could cause java.lang.reflect.InvocationTargetException?

原因是

  java.lang.NullPointerException: Attempt to invoke virtual method      'androID.content.Context androID.content.Context.getApplicationContext()' on a null object reference 

jar文件中的代码是

public class MyClass extends Activity {@OverrIDeprotected voID onCreate(Bundle savedInstanceState) {    // Todo auto-generated method stub    super.onCreate(savedInstanceState);}public voID doSomething() {    Toast.makeText(getApplicationContext(), "MyClass: doSomething() called.", Toast.LENGTH_LONG).show();    Log.e(MyClass.class.getname(), "MyClass: doSomething() called.");}}

任何人都可以帮助我实现这一目标.任何帮助将不胜感激.

编辑:
我想做的是我有一个自己的图书馆,很多客户正在使用…我想要的是从用户的SD卡中加载我的图书馆.我想在需要时更新该图书馆没有用户的知识,也没有任何版本更新.库包含很少的接口,片段和活动.所以现在我能够从sd卡加载我的库并可以调用基本功能.现在的主要挑战是从库中实现接口并调用在其中使用了上下文的函数.

涉及此类 *** 作的任何示例或提示将大有帮助.

解决方法:

我看到两种解决方法,具体取决于您愿意做什么:

>如果MyClass必须是一个活动

必须使用startActivity()或任何变体来正确启动一个Activity.它也必须在清单中声明.因此,只有当您所有的MyClass变体都具有相同的签名时,以下才起作用.

我假设您的启动代码位于一个Activity中.加载classtoload之后,您可以执行以下 *** 作:

final file tmpDir = getDir("dex", 0);final String libPath = Environment.getExternalStorageDirectory() + "/test.jar";final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getabsolutePath(), null, this.getClass().getClassLoader());try {    final Class<Object> classtoload = (Class<Object>) classloader.loadClass("org.shlublu.androID.sandBox.MyClass");    // CHANGED: THIS STARTS PROPERLY YOUR ACTIVITY ONCE THE CLASS LOADED    final Intent intent = new Intent(this, classtoload);    startActivity(intent); } catch (ClassNotFoundException e) {    // handle that Exception properly here}

现在以某种方式更改doSomething(),使其使用新Activity的基础上下文而不是getApplicationContext().然后例如从MyClass.onCreate()调用它,然后看它是否有效:

public class MyClass extends Activity {    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        doSomething(); // CHANGED: just as an example    }    private voID doSomething() {        // CHANGED: Now the following line uses 'this' instead of `getApplicationContext()`        Toast.makeText(this, "MyClass: doSomething() called.", Toast.LENGTH_LONG).show();         Log.d(MyClass.class.getname(), "MyClass: doSomething() called.");    }}

其余的-什么时候调用doSomething(),为什么等等…-完全取决于您愿意做什么.

>如果MyClass只需要显示一个Toast

在这种情况下,无需创建另一个活动. doSomething()只需接收适当的上下文即可显示Toast.

如下更改MyClass:

public class MyClass {    private voID doSomething(Context ctx) {        Toast.makeText(ctx, "MyClass: doSomething() called.", Toast.LENGTH_LONG).show();        Log.d(MyClass.class.getname(), "MyClass: doSomething() called.");    }}

并假设您是从Activity运行的,请更改您的启动代码以将其传递给doSomething():

final file tmpDir = getDir("dex", 0);final String libPath = Environment.getExternalStorageDirectory() + "/test.jar";final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getabsolutePath(), null, this.getClass().getClassLoader());try {    final Class<Object> classtoload = (Class<Object>) classloader.loadClass("org.shlublu.androID.sandBox.MyClass");    // CHANGED: LOADS THE METHOD doSomething(Context). EXECUTES IT WITH this AS AN ARGUMENT    final Class[] args = new Class[1];    args[0] = Context.class;    final Method doSomething = classtoload.getmethod("doSomething", args);    final Object myInstance  = classtoload.newInstance();    doSomething.invoke(myInstance, this);    } catch (ClassNotFoundException e) {    // handle that Exception properly here}
总结

以上是内存溢出为你收集整理的android-使用DexClassLoader与动态加载的库进行交互全部内容,希望文章能够帮你解决android-使用DexClassLoader与动态加载的库进行交互所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1092893.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-28
下一篇 2022-05-28

发表评论

登录后才能评论

评论列表(0条)

保存