2

I know that we can call a normal Kotlin method in cpp using JNI, by using (env)->GetMethodID(class, Methodname, signatures) and (env)->CallVoidMethod(object, methodID, parameters)

but I'm unable to do the same for composable kotlin method when using jetpack compose. (env)->GetMethodID is returning null in this case.

I'm getting error:

java.lang.NoSuchMethodError: no non-static method "Lcom/example/jetpackcompose/MainActivity;.MessageCard(Ljava/lang/String;Ljava/lang/String;)V"

I also tried to invoke a composable method from a non-composable method and invoke the non-composable method from jni but that's also not possible because a composable method can only be invoked from another composable method.

Is there a way to invoke a composable kotlin method from jni?

MainActivity.kt

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        var str:String = stringFromJNI()
        MessageCardCpp()
    }
}

@Composable
fun MessageCard(author: String, body: String) {
    Row() {

        Image(painter = painterResource(R.drawable.sampleimage),
            contentDescription = "Sample Image",
            modifier = Modifier
                .size(80.dp)
                .clip(CircleShape)
        )

        Spacer(modifier = Modifier.width(8.dp))

        Column() {
            Text(author, fontSize = 30.sp)
            Spacer(modifier = Modifier.width(4.dp))
            Text(body, fontSize = 30.sp)
        }
    }
}

external fun stringFromJNI(): String
external fun MessageCardCpp()

companion object {
    // Used to load the 'jetpackcompose' library on application startup.
    init {
        System.loadLibrary("jetpackcompose")
    }
}
}

native-lib.cpp

extern "C" JNIEXPORT void JNICALL
Java_com_example_jetpackcompose_MainActivity_MessageCardCpp(JNIEnv *env, jobject thiz) {

jclass MainActivity = (env)->FindClass("com/example/jetpackcompose/MainActivity");

if(MainActivity == nullptr) {

    __android_log_print(ANDROID_LOG_DEBUG, "Demo", "%s", "GetClass returns Null");
    return;
}

jmethodID MessageCard = (env)->GetMethodID(MainActivity, "MessageCard","(Ljava/lang/String;Ljava/lang/String;)V");

if(MessageCard == nullptr) {

    __android_log_print(ANDROID_LOG_DEBUG, "Demo", "%s", "GetMethodID returns Null");
    return;
}

(env)->CallVoidMethod(thiz, MessageCard, env->NewStringUTF("Android JetPack"), env->NewStringUTF("Hello Cpp"));
}
0

1 Answer 1

2

I'm afraid your question is a non-starter. The @Composable annotation is processed by the Android Kotlin plugin at compile time simply by inspecting all method/function calls. The generated code no longer contains @Composable calls, but references to a graph that represents your application's layout and how to render it.

By contrast, the JNI code can only execute at runtime, so it is too late to call @Composable methods.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.