2

I am working on an Android application (under Android studio) that allows an user to run at run time a "Java android" code.

My first research help me to create a library from a "MyClass.java", understandable by the Android application.

  1. Use the command "Javac" to create the "MyClass.class" from "MyClass.java"

C:\Program Files\Android\Android Studio\jre\bin\javac -source 1.8 -target 1.8 -d "./" -classpath "C:\Users\user_account\AppData\Local\Android\Sdk\platforms\android-27\android.jar" -bootclasspath "C:\Program Files\Android\Android Studio\jre\jre\lib\rt.jar" "MyClass.java"

  1. Transform this "MyClass.class" into a Jar library with "Jar" command

C:\Program Files\Android\Android Studio\jre\bin\jar cvf "MyClass.jar" com/YourPackage/MyClass.class

  1. And finally translate it for Dalvik system with "dx" tool

call C:\Users\user_account\AppData\Local\Android\Sdk\build-tools\27.0.3\dx --dex --output "MyClass.dex" "MyClass.jar"

On the Android application I can call a method inside the library by :

final String libPath = Environment.getExternalStorageDirectory() + "/DexFile/MyClass.dex";
final File tmpDir = getDir("DexFile", 0);
DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader());
classToLoad = (Class<?>) classloader.loadClass("com.YourPackage.MyClass");

Object myInstance = classToLoad.newInstance();
Method mainMethod= classToLoad.getMethod("main");
mainMethod.invoke(myInstance);

A tricky things, this code doesn't work if you don't add some permission in your main :

 /**
 * Checks if the app has permission to write to device storage
 * <p>
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

And in your manifest :

     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

At this point I am able to call a method inside my custom library. But now I need to call a method of my main activity from the library. A simplify view of my problem is :

Diagram of my problem

First problem, what I need is an aberration from a library point a view, I want to attach and make a dependency between my library and my application. Because of that I didn't found anything that can help me. The only idea I have come with, is to pass an object argument to my "main()" and invoke a method inside this object, but that doesn't work :

package com.YourPackage;
public class MyClass{
    public void main(Object object){
        try{
            Class cls = obj.getClass();
            Method mainMethod = cls.getMethod("methodToCall",null);
            mainMethod.invoke(obj,null);
        }catch(Exception e){}
    }
}

If you have any idea to do this properly, I will be pleased to ear it.

Hope this post will at least help people working on "Dex" library... Sincerely, a little programmer


Thanks to this link How do I invoke a Java method when given the method name as a string? My solution works even it's not really clean. The reason my code doesn't work is because I stored the class object, if you do it directly the error disappear. If any explanation exist come and comment !

package com.YourPackage;
public class MyClass{
    public void main(Object obj){
        try{
            Method mainMethod = obj.getClass().getMethod("methodToCall");
            mainMethod.invoke(obj); // Works, invoke the right method
        }catch(Exception e){}
    }
}
Hanacket
  • 31
  • 5
  • Your working version looks as if `getClass()` is called statically, but `getClass()` is not a static method. Is this a typo? Did you mean to do `obj.getClass().getMethod`? – Dioxin Jun 08 '18 at 18:02
  • My bad, that's just a typo mistake. it's "object.getClass().getMethod("nameOfMethod");" – Hanacket Jun 11 '18 at 08:14

0 Answers0