Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HEELP #131

Closed
suprohub opened this issue Oct 31, 2024 · 30 comments
Closed

HEELP #131

suprohub opened this issue Oct 31, 2024 · 30 comments

Comments

@suprohub
Copy link

10-31 19:45:41.736 10253 10253 F DEBUG : Abort message: 'JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.ClassNotFoundException: Didn't find class "org.astonbitecode.j4rs.api.dtos.InvocationArg"

@suprohub
Copy link
Author

i get this error on android

@suprohub
Copy link
Author

i use jni onload and attach thread but if i try create instance i get this error

@astonbitecode
Copy link
Owner

Something seems to be wrong with your classpath. It seems the j4rs classes are not found and cannot be loaded.

How do you setup your Android app? Is it a Java application that calls Rust native code?
If so, have you checked the example project here?

There should not be any classloading issues if:

  1. You specify the j4rs dependency in the Gradle (or Maven).
  2. You have a JNI_OnLoad where you set the JavaVM.
  3. You load the native library in Java.
  4. You attach the thread and create the InvocationArg.

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

Something seems to be wrong with your classpath. It seems the j4rs classes are not found and cannot be loaded.

How do you setup your Android app? Is it a Java application that calls Rust native code? If so, have you checked the example project here?

There should not be any classloading issues if:

1. You [specify](https://github.com/astonbitecode/j4rs-android-test/blob/58fb959dc83e8fa3d1dbfb3f073e2ee4c5c1c493/app/build.gradle#L37) the `j4rs` dependency in the Gradle (or Maven).

2. You have a `JNI_OnLoad` where you [set the `JavaVM`](https://github.com/astonbitecode/j4rs-android-test/blob/58fb959dc83e8fa3d1dbfb3f073e2ee4c5c1c493/j4rstestnative/src/lib.rs#L9).

3. You [load](https://github.com/astonbitecode/j4rs-android-test/blob/58fb959dc83e8fa3d1dbfb3f073e2ee4c5c1c493/app/src/main/java/com/example/j4rstest/RustFunctionCalls.java#L15) the native library in Java.

4. You [attach](https://github.com/astonbitecode/j4rs-android-test/blob/58fb959dc83e8fa3d1dbfb3f073e2ee4c5c1c493/j4rstestnative/src/lib.rs#L25) the thread and [create](https://github.com/astonbitecode/j4rs-android-test/blob/58fb959dc83e8fa3d1dbfb3f073e2ee4c5c1c493/j4rstestnative/src/lib.rs#L29) the `InvocationArg`.

not works

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

i attach tread, add this to dependencies, load libary and only crashes

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

                    if textedit.gained_focus() {
                        let jvm = Jvm::attach_thread().unwrap();
                        let instance = jvm.create_instance(
                            "pumpkin_egui_android.MainActivity",
                            InvocationArg::empty()
                        ).unwrap();
                        jvm.invoke(
                            &instance,
                            "openKeyboard",
                            InvocationArg::empty()
                        ).unwrap();
                    }

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

  public void openKeyboard() {
    InputMethodManager imm =
            (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm != null) {
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }
  }```

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

plugins {
    id 'com.android.application'
}

android {
    namespace "local.pumpkin_egui_android"
    compileSdk 33

    defaultConfig {
        applicationId "local.pumpkin_egui_android"
        minSdk 28
        targetSdk 33
        versionCode 1
        versionName "1"
    }

    buildTypes {
        debug
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'com.google.android.material:material:1.5.0'
    implementation "androidx.games:games-activity:2.0.2"
    implementation 'io.github.astonbitecode:j4rs:0.20.0'
}

@astonbitecode
Copy link
Owner

I have just tested the example using the latest j4rs without issues.

When do you call the System.loadLibrary?
At the time it is called, the JNI_OnLoad is called and you should have there:

j4rs::set_java_vm

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

I have just tested the example using the latest j4rs without issues.

When do you call the System.loadLibrary?
At the time it is called, the JNI_OnLoad is called and you should have there:

j4rs::set_java_vm

I call it from static in class, its needed for egui, set java vm i call too

@astonbitecode
Copy link
Owner

Do you maybe have some code to share?

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

Go to pumpkin egui

@astonbitecode
Copy link
Owner

astonbitecode commented Nov 1, 2024

I am having difficulties to understand the setup of the project.

I see that you define a MainActivity in your AndroidManifest, but using also game-activity.

How do you build your project, create the apk and run it?

EDIT: One more question: Have you verified that JNI_OnLoad is indeed called?

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

Cargo ndk then gradle build

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

Cargo ndk then gradle build
How verify what jni on load is called?

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

And i want help: what the bestethod: construct main activity for call method or inline method?

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

Like call all method code in rust

@suprohub
Copy link
Author

suprohub commented Nov 1, 2024

See makefile

@astonbitecode
Copy link
Owner

How verify what jni on load is called?

Using some logging I guess

construct main activity for call method or inline method?

As you see in the example project mentioned above, currently, the supported way is to implement the main activity in Java, use JNI_OnLoad and call the native method from Java to Rust.

I am also investigating "rust-only" ways, using native-activity, but there are currently classloading issues we need to overcome...

@suprohub
Copy link
Author

suprohub commented Nov 2, 2024

Yeah its setted

@suprohub
Copy link
Author

suprohub commented Nov 2, 2024

Screenshot_20241102-113524_Pumpkin server.png

@suprohub
Copy link
Author

suprohub commented Nov 2, 2024

I dont know what its wrong

@suprohub
Copy link
Author

suprohub commented Nov 2, 2024

2024-11-02-11-54-39-705.jpg
2024-11-02-11-54-32-465.jpg

@suprohub
Copy link
Author

suprohub commented Nov 2, 2024

But gradle build works

@suprohub
Copy link
Author

suprohub commented Nov 2, 2024

Any updates?

@suprohub
Copy link
Author

suprohub commented Nov 3, 2024

Helo?

@astonbitecode
Copy link
Owner

How does the app load the activity? Is the native activity used, or the activity you implemented?

You can open the apk and inspect:

  1. Which Activity is it used? (android:name element)
  2. Do j4rs classes exist inside .dex files? If the classes are not there, check if code shrinking is enabled. You should configure which code to keep in that case. Configuring proper keep rules is important because the code shrinker might otherwise remove classes, methods, or fields that are only used from JNI. (source)

@astonbitecode
Copy link
Owner

Implemented the ability to use j4rs along with android-activity.
I will soon update the README with instructions how to do it. In a nutshell, you should be able to pass to j4rs the JavaVM and the NativeActivity jobject and overcome the classloading issues:

let jvm = JvmBuilder::new()
        .with_java_vm(java_vm.clone())
        .with_classloader_of_activity_(activity_obj.clone())
        .build()?;

@astonbitecode
Copy link
Owner

For more details, please see this example project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants