探讨:如何在NDK中呼叫Java的class

 更新时间:2013年05月31日 10:18:00   作者:  
本篇文章是对如何在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的类,第一步当然要有一个Java的类,这个类是我自行建立
要产生一个文字的Bitmap,技术上没什么复杂性,建立Paint,建立Bitmap然后用Canvas将文字写入
在Canvas的drawText中,会使用FontMetrics的值来写入文字,所以利用fm.ascent让文字往上对齐
复制代码 代码如下:

// 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_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中创建一个Java的实体类
这段代码是我的CloudBox中创建文字纹理的代码
mid = g_env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I");
int width = g_env->CallIntMethod(g_textmgr, mid, textImage);
其中这两行,GetMethodID先取得该类的方法
在GetMethodID中第一参数是Java 类对象。第二个参数是参数(或方法名),第三个参数是该参数(或方法)的签名。
那要如何取得方法的签名呢?
我们要利用Javap -s TextManager这个指令来做

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



辛苦了这么久,我的CloudBox终于能显示文字了!!!!!!

相关文章

  • java Collection集合接口的介绍和使用详解

    java Collection集合接口的介绍和使用详解

    这篇文章主要为大家介绍了java Collection集合接口的介绍和使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 如何修改覆盖spring boot默认日志策略logback详解

    如何修改覆盖spring boot默认日志策略logback详解

    这篇文章主要给大家介绍了关于如何修改覆盖spring boot默认日志策略logback的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-10-10
  • 在SpringBoot项目中实现读写分离的流程步骤

    在SpringBoot项目中实现读写分离的流程步骤

    SpringBoot作为一种快速开发框架,广泛应用于Java项目中,在一些大型应用中,数据库的读写分离是提升性能和扩展性的一种重要手段,本文将介绍如何在SpringBoot项目中优雅地实现读写分离,并通过适当的代码插入,详细展开实现步骤,同时进行拓展和分析
    2023-11-11
  • JAVA 文件监控 WatchService的示例方法

    JAVA 文件监控 WatchService的示例方法

    本篇文章主要介绍了JAVA 文件监控 WatchService的示例方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • 在IDEA中配置Maven镜像的最新方法

    在IDEA中配置Maven镜像的最新方法

    这篇文章主要给大家介绍了关于在IDEA中配置Maven镜像的最新方法,Maven是一个流行的Java项目构建工具,它依赖于互联网上的Mave中央仓库来下载和管理项目依赖库,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • 详解spring集成mina实现服务端主动推送(包含心跳检测)

    详解spring集成mina实现服务端主动推送(包含心跳检测)

    本篇文章主要介绍了详解spring集成mina实现服务端主动推送(包含心跳检测),具有一定的参考价值,与兴趣的可以了解一下
    2017-09-09
  • json-lib将json格式的字符串,转化为java对象的实例

    json-lib将json格式的字符串,转化为java对象的实例

    下面小编就为大家带来一篇json-lib将json格式的字符串,转化为java对象的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • Spring session实现Session共享

    Spring session实现Session共享

    本文主要介绍了Spring session实现Session共享,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Java基础学习之字符缓冲流的应用

    Java基础学习之字符缓冲流的应用

    这篇文章主要为大家详细介绍了Java基础中的字符缓冲流的相关应用,例如复制Java文件等,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一
    2022-09-09
  • Java 生成随机验证码图片的示例

    Java 生成随机验证码图片的示例

    这篇文章主要介绍了Java 生成随机验证码图片的示例,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-10-10

最新评论