探討:如何在NDK中呼叫Java的class
package com.clouddevelop.cloudbox;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
public class TextManager
{
public Bitmap create(String text, float size)
{
try
{
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(size);
paint.setAlpha(255);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setTextAlign(Paint.Align.LEFT);
paint.setAntiAlias(true);
float[] widths = new float[text.length()];;
paint.getTextWidths(text, widths);
float width = 0;
for(int i = 0 ;i < widths.length ; i++)
width += widths[i];
FontMetrics fm = paint.getFontMetrics();
int mFontHeight = (int) (Math.ceil(fm.descent - fm.top) + 2);
Bitmap textImg = Bitmap.createBitmap((int)width, mFontHeight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(textImg);
if(fm.ascent < 0)
c.drawText(text,0,(float)Math.abs(fm.ascent),paint);
else
c.drawText(text,0,fm.ascent* -1,paint);
return textImg;
}
catch (Exception e) { }
return null;
}
public int getWidth(Bitmap bmp) { return bmp.getWidth(); }
public int getHeight(Bitmap bmp) { return bmp.getHeight(); }
public void getPixels(Bitmap bmp, int[] pixels)
{
int w = bmp.getWidth();
int h = bmp.getHeight();
bmp.getPixels(pixels, 0, w, 0, 0, w, h);
}
public void close(Bitmap bmp)
{
bmp.recycle();
}
}
要在NDK中呼叫Java的類,第一步當(dāng)然要有一個(gè)Java的類,這個(gè)類是我自行建立
要產(chǎn)生一個(gè)文字的Bitmap,技術(shù)上沒什么復(fù)雜性,建立Paint,建立Bitmap然后用Canvas將文字寫入
在Canvas的drawText中,會(huì)使用FontMetrics的值來寫入文字,所以利用fm.ascent讓文字往上對(duì)齊
// declare
JNIEXPORT void JNICALL Java_com_clouddevelop_cloudbox_CloudRenderer_nativeTextInit
(JNIEnv* env, jclass cls, jobject textManager);
// implement
JNIEXPORT void JNICALL Java_com_clouddevelop_cloudbox_CloudRenderer_nativeTextInit
(JNIEnv* env, jclass cls, jobject textManager)
{
g_env = env;
g_textmgr = textManager;
jclass business_class = env->GetObjectClass(g_textmgr);
AndroidLog("initial textmanager success!");
}
接下來要在JNI中將JNIEnv存到全域變量中g(shù)_env
jobject getInstance(JNIEnv* env, jclass obj_class)
{
jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");
jobject obj = env->NewObject(obj_class, construction_id);
return obj;
}
GLuint createText(const char* text, float size,float* rWidth, float* rHeight)
{
if(g_env)
AndroidLog("g_env exist");
if(g_textmgr)
AndroidLog("g_textmgr exist");
jclass order_class = g_env->FindClass("com/clouddevelop/cloudbox/TextManager");
AndroidLog("FindClass succeed");
g_textmgr = getInstance(g_env, order_class);
jclass cls = g_env->GetObjectClass(g_textmgr);
AndroidLog("get class succeed");
jmethodID mid;
mid = g_env->GetMethodID(cls, "create",
"(Ljava/lang/String;F)Landroid/graphics/Bitmap;");
AndroidLog("get create succeed");
jstring data = g_env->NewStringUTF(text);
jobject textImage = g_env->CallObjectMethod(g_textmgr, mid, data,size);
AndroidLog("call create succeed");
g_env->DeleteLocalRef(data);
g_env->NewGlobalRef(textImage);
/* Get image dimensions */
mid = g_env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I");
int width = g_env->CallIntMethod(g_textmgr, mid, textImage);
AndroidLog("call getWidth succeed");
mid = g_env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I");
int height = g_env->CallIntMethod(g_textmgr, mid, textImage);
AndroidLog("call getHeight succeed");
*rWidth = width;
*rHeight = height;
/* Get pixels */
jintArray image_data = g_env->NewIntArray(width * height);
g_env->NewGlobalRef(image_data);
mid = g_env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V");
g_env->CallVoidMethod(g_textmgr, mid, textImage, image_data);
AndroidLog("call getPixels succeed");
jint *pixels = g_env->GetIntArrayElements(image_data, 0);
//Now generate the OpenGL texture object
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, (GLvoid*) pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
AndroidLog("generate texture succeed");
g_env->ReleaseIntArrayElements(image_data, pixels, 0);
g_env->DeleteGlobalRef(image_data);
/* Free image */
mid = g_env->GetMethodID(cls, "close", "(Landroid/graphics/Bitmap;)V");
g_env->CallVoidMethod(g_textmgr, mid, textImage);
AndroidLog("call close succeed");
g_env->DeleteGlobalRef(textImage);
return texture;
}
jobject getInstance(JNIEnv* env, jclass obj_class)
{
jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");
jobject obj = env->NewObject(obj_class, construction_id);
return obj;
}
上面這段代碼,是在native code中創(chuàng)建一個(gè)Java的實(shí)體類
這段代碼是我的CloudBox中創(chuàng)建文字紋理的代碼
mid = g_env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I");
int width = g_env->CallIntMethod(g_textmgr, mid, textImage);
其中這兩行,GetMethodID先取得該類的方法
在GetMethodID中第一參數(shù)是Java 類對(duì)象。第二個(gè)參數(shù)是參數(shù)(或方法名),第三個(gè)參數(shù)是該參數(shù)(或方法)的簽名。
那要如何取得方法的簽名呢?
我們要利用Javap -s TextManager這個(gè)指令來做

首先到.class所在的文件夾下,在我的范例中是在D:\CloudAndroid\CloudBox\CloudBoxAndroidGameApplication\bin\com\clouddevelop\cloudbox
然后鍵入javap -s TextManager就可以得到了,Signature就是我們要的簽名。

辛苦了這么久,我的CloudBox終于能顯示文字了!?。。。?!
相關(guān)文章
springboot啟動(dòng)后卡住無日志的幾種情況小結(jié)
這篇文章主要介紹了springboot啟動(dòng)后卡住無日志的幾種情況小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringMVC的注解@RequestMapping屬性及使用
這篇文章主要為大家介紹了SpringMVC注解@RequestMapping屬性及使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
java實(shí)現(xiàn)多線程之定時(shí)器任務(wù)
本篇文章主要介紹了java實(shí)現(xiàn)多線程之定時(shí)器任務(wù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02
spring自定義一個(gè)簡(jiǎn)單的Starter啟動(dòng)器
這篇文章主要介紹了spring自定義一個(gè)簡(jiǎn)單的Starter啟動(dòng)器,一個(gè) starter其實(shí)就是對(duì)一個(gè)功能的集成封裝,然后對(duì)外提供一個(gè)依賴,讓業(yè)務(wù)去使用,像我們熟悉的 Redis,mongo,mybatis 等均屬于,需要的朋友可以參考下2023-07-07
Java后端產(chǎn)生驗(yàn)證碼后臺(tái)驗(yàn)證功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java后臺(tái)產(chǎn)生驗(yàn)證碼后臺(tái)驗(yàn)證功能,本文文字結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
Spring計(jì)時(shí)器stopwatch使用詳解
這篇文章主要介紹了Spring計(jì)時(shí)器stopwatch使用詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08

