Android:从 C++ Native Activity 调用 Java 类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10184527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 23:58:03  来源:igfitidea点击:

Android: calling Java class from C++ Native Activity

javacandroid-ndknative-activity

提问by NoAngel

Java code:

爪哇代码:

    package local.ttt;

    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Typeface;

    public class Text2Bitmap {
        static Bitmap getBitmap(String text,int fontsize) {
            Paint paint=new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.WHITE);
            paint.setTextSize(fontsize);
            paint.setAntiAlias(true);
            paint.setTypeface(Typeface.DEFAULT);

            int outwidth=(int)Math.round(paint.measureText(text));
            Bitmap bitmap=Bitmap.createBitmap(outwidth,fontsize,Bitmap.Config.ALPHA_8);

            Canvas canvas=new Canvas(bitmap);
            canvas.drawText(text,0,fontsize-1,paint);

            return bitmap;
        }
    }

C source:

C源:


            ...
            MY_ASSERT(vm_cached!=NULL);
            JNIEnv* env;
            jint res=vm_cached->AttachCurrentThread(&env,NULL);
            MY_ASSERT(res==0);
            jclass activityClass=env->FindClass("android/app/NativeActivity");
            MY_ASSERT(activityClass!=NULL);
            jmethodID getClassLoader=env->GetMethodID(activityClass,"getClassLoader","()Ljava/lang/ClassLoader;");
            MY_ASSERT(getClassLoader!=NULL);
            MY_ASSERT(nativeActivityObjHnd!=NULL);
            jobject cls=env->CallObjectMethod(nativeActivityObjHnd,getClassLoader);
            jclass classLoader=env->FindClass("java/lang/ClassLoader");
            MY_ASSERT(classLoader!=NULL);
            jmethodID findClass=env->GetMethodID(classLoader,"loadClass","(Ljava/lang/String;)Ljava/lang/Class;");
            MY_ASSERT(findClass!=NULL);
            jstring strClassName=env->NewStringUTF("Llocal/ttt/Text2Bitmap;");
            jclass text2bitmapClass=(jclass)env->CallObjectMethod(cls,findClass,strClassName); //fails here
            MY_ASSERT(text2bitmapClass!=NULL);
            res=vm_cached->DetachCurrentThread();
            MY_ASSERT(res==0);
            ...

it fails with:

它失败了:

W/dalvikvm(5614): dvmFindClassByName rejecting 'Llocal/ttt/Text2Bitmap;'
W/dalvikvm(5614): threadid=9: thread exiting with uncaught exception (group=0x4002d560)
E/AndroidRuntime(5614): FATAL EXCEPTION: Thread-10
E/AndroidRuntime(5614): java.lang.ClassNotFoundException: Llocal/ttt/Text2Bitmap; in loader dalvik.system.PathClassLoader[.]
E/AndroidRuntime(5614):     at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)
E/AndroidRuntime(5614):     at java.lang.ClassLoader.loadClass(ClassLoader.java:551)
E/AndroidRuntime(5614):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
E/AndroidRuntime(5614):     at dalvik.system.NativeStart.run(Native Method)

Any hint what I'm doing wrong, please?

请提示我做错了什么?

采纳答案by Mārti?? Mo?eiko

Don't mess with java class loader. Use this code:

不要乱用 java 类加载器。使用此代码:

MY_ASSERT(vm_cached!=NULL);

JNIEnv* env;
jint res = vm_cached->AttachCurrentThread(&env,NULL);
MY_ASSERT(res==0);

jclass t2bClass = env->FindClass("local/ttt/Text2Bitmap");
MY_ASSERT(t2bClass!=NULL);

jmethodID getBitmap = env->GetStaticMethodID(t2bClass, "getBitmap","(Ljava/lang/String;I)Landroid/graphics/Bitmap;");
MY_ASSERT(getBitmap!=NULL);

jstring text = ...;
int fontsize = ...;
jobject bitmap = env->CallStaticObjectMethod(t2bClass, getBitmap, text, fontsize);
MY_ASSERT(bitmap!=NULL);

// process bitmap here
// ...

res=vm_cached->DetachCurrentThread();
MY_ASSERT(res==0);

回答by Youssef G.

Not sure what is causing your error (you do not indicate where the lines are, or the particular line where you are having difficulty debugging), but I will go ahead and point out a few quick mistakes I see.

不确定是什么导致了您的错误(您没有指出行的位置,或者您在调试时遇到困难的特定行),但我会继续指出我看到的一些快速错误。

One first mistake is you need to use CallStaticObjectMethodsince you are calling a static method. Your jmethodid findClasshas a methodID, not a class, which is misleading and wrong. You also have two parameters, but you seem to be only passing one parameter.

第一个错误是您需要使用,CallStaticObjectMethod因为您正在调用静态方法。你jmethodid findClass有一个methodID,而不是一个类,这是误导和错误的。您还有两个参数,但您似乎只传递了一个参数。

Basically, you need:

基本上,您需要:

(env)->GetStaticMethodID(jclass,"method name", "Parameter list")

(env)->GetStaticMethodID(jclass,"method name", "Parameter list")

--jclass is the class reference --"method name" is the name of the method IN quotes --"Parameter list" is the list of parameters, which you need to look up syntax.

--jclass 是类引用 --"method name" 是方法名 IN 引号 --"Parameter list" 是参数列表,需要查语法。

Skipping a few things...To call your stuff you need:

跳过一些事情......要调用你需要的东西:

(env)->CallStaticObjectMethod(jclass,jmid,parameter1,parameter2)

(env)->CallStaticObjectMethod(jclass,jmid,parameter1,parameter2)

--jclass is once again the class that has the static method. --jmid is the java method id which you get from the function above. --parameter1 and parameter2 are the parameters required for the java method.

--jclass 再次成为具有静态方法的类。--jmid 是您从上面的函数中获得的 java 方法 ID。--parameter1和parameter2是java方法需要的参数。

Lastly, I think this may just be preference, but I would not attach the thread to the JVM until you have all the necessary information to make the jump into the JVM.

最后,我认为这可能只是偏好,但在您拥有跳转到 JVM 的所有必要信息之前,我不会将线程附加到 JVM。