Android: вызов Java-класса из C++ Native Activity
Java-код:
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 источник:
...
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);
...
это терпит неудачу с:
W / dalvikvm (5614): dvmFindClassByName отклоняет 'Llocal/ttt/Text2Bitmap;' W/dalvikvm(5614): threadid=9: поток завершается с необработанным исключением (группа =0x4002d560) E/AndroidRuntime(5614): ИСКЛЮЧИТЕЛЬНОЕ ИСКЛЮЧЕНИЕ: Thread-10 E/AndroidRuntime(5614): java.lang.ClassNotFoundException: Llocal/ttt/Text2Bitmap; в загрузчике dalvik.system.PathClassLoader[.] E/AndroidRuntime(5614): в dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240) E/AndroidRuntime(5614): на java.lang.ClassLoader.loadClass(ClassLoader.java:551) E/AndroidRuntime(5614): на java.lang.ClassLoader.loadClass(ClassLoader.java:511) E/AndroidRuntime(5614): в dalvik.system.NativeStart.run(собственный метод)
Любой намек, что я делаю не так, пожалуйста?
2 ответа
Не связывайтесь с загрузчиком классов 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);
Не уверен, что является причиной вашей ошибки (вы не указываете, где находятся строки или конкретная строка, в которой вы испытываете затруднения при отладке), но я продолжу и укажу на несколько быстрых ошибок, которые я вижу.
Первая ошибка - вам нужно использовать CallStaticObjectMethod
так как вы вызываете статический метод. Ваш jmethodid findClass
имеет methodID, а не класс, что вводит в заблуждение и неправильно. У вас также есть два параметра, но вы, кажется, передаете только один параметр.
В основном вам нужно:
(env)->GetStaticMethodID(jclass,"method name", "Parameter list")
--jclass - ссылка на класс -"имя метода" - это имя метода IN в кавычках -"Список параметров" - это список параметров, которые вам нужны для поиска синтаксиса.
Пропустив несколько вещей... Чтобы назвать свои вещи, вам нужно:
(env)->CallStaticObjectMethod(jclass,jmid,parameter1,parameter2)
--jclass снова класс, который имеет статический метод. --jmid - это идентификатор метода java, который вы получаете из функции выше. --parameter1 и parameter2 - параметры, необходимые для метода java.
Наконец, я думаю, что это может быть просто предпочтением, но я не буду присоединять поток к JVM, пока у вас не будет всей необходимой информации для перехода в JVM.