探讨:如何在NDK中呼叫Java的class_Java编程

废话不多说,直接上码.......

复制代码 代码如下:

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终于能显示文字了!!!!!!

时间: 2024-10-25 20:00:17

探讨:如何在NDK中呼叫Java的class_Java编程的相关文章

探讨如何在Eclipse中过滤版本控制文件.svn

当我们使用版本管理工具的时候,比如 CVS.SVN或者harvest,都会在 checkout 到本地的源代码中发现很多代码之外的多余文件夹及文件,这些文件夹及文件对于版本管理工具而言非常重要,不能随便删除,但是在我们的项目开发中却显得有些碍手碍脚.在Eclipse中可以通过如下方式进行排除:方法一:"Project->Properties->Java Build Path",右侧的面板中的"Source"选项卡,展开"source folde

探讨:如何在ScrollView中嵌套ListView_Android

一.分析 1.最简单的布局:只有一个ListView 如果整个页面只有一个ListView的话,那么由于ListView本身带有滚动效果,所以当加载的数据超过页面显示的范围时,可以通过上下滑动来查看所有的item.因此这种情况下,不需要添加ScrollView. 2.其它布局A+ListView 这种情况下,如果布局A定义在ListView的前面,那么当布局A所占的比例较大,或者ListView加载的数据较多时,都会导致ListView显示不完全.同样,由于ListView自身可以滚动,因此仍然

如何在Oracle中使用Java存储过程(详解)

其实,这篇短文,我早就应该写了.因为,Java存储过程今后在各大数据库厂商中越来越流行,功能也越来越强大.这里以Oracle为例,介绍一下java存储过程的具体用法. 一.如何创建java存储过程? 通常有三种方法来创建java存储过程. 1.使用oracle的sql语句来创建: e.g. 使用create or replace and compile java source named "<name>" as 后边跟上java源程序.要求类的方法必须是public sta

探讨如何在Eclipse中过滤版本控制文件.svn_java

当我们使用版本管理工具的时候,比如 CVS.SVN或者harvest,都会在 checkout 到本地的源代码中发现很多代码之外的多余文件夹及文件,这些文件夹及文件对于版本管理工具而言非常重要,不能随便删除,但是在我们的项目开发中却显得有些碍手碍脚.在Eclipse中可以通过如下方式进行排除:方法一:"Project->Properties->Java Build Path",右侧的面板中的"Source"选项卡,展开"source folde

探讨如何在php168_cms中提取验证码_php技巧

复制代码 代码如下: <?phpfunction yzImg($nmsg){ if (function_exists('imagecreatetruecolor')){  $imstr[0]["s"]=$nmsg[0];  $imstr[1]["s"]=$nmsg[1];  $imstr[2]["s"]=$nmsg[2];  $imstr[3]["s"]=$nmsg[3];  //文件头...  header("

如何在Flash中处理Cookies?_编程10000问

testCookies.asp<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> ' 检查浏览器是否接受Cookies. <% strTest = Request.QueryString("CookieTest") If UCase(strTest) <> Ucase("true") Then Session(&qu

在Apache目录服务器中存储Java对象,第2部分:(上)

在 ApacheDS 中存储.搜索和检索 Java 对象 简介:在第 2 部分中将介绍如何在 Apache 目录服务器 (ApacheDS) 中存储 Java 对象, Bilal Siddiqui 将提供 9 个示例应用程序,演示在 第 1 部分 中学习的概念.除 了介绍使用 ApacheDS 存储.搜索.检索和修改 Java 对象的所有步骤之外,Bilal 还将在总结全文时提 供一个可重用的 Java 类,该类可以使用 LDAP 模式组件在 ApacheDS 中将这些功能组合在一起. 在 第

eclipse-在 android java.awt 中使用 java jdk

问题描述 在 android java.awt 中使用 java jdk 我在 android 程序中使用java.awt.polygon 类.在Java构建路径中添加了 Jave JRE System library jdk 1.7 但是在使用下面这段代码时 java.awt.Polygon polyGon = new Polygon(); 获得错误NoClassDefFoundError 如何在android中使用java类? 解决方案 java awt包只使用了2个类 一个是java.aw

如何在 vim 中更好的编辑 java 文件

这次介绍一下如何在 vim 中更好的编辑 java 文件.作者: camry.wu@gmail.com 1. javabrowser 编辑类文件时, 类资源树是个有用的东西, 可以把类的成员, 方法等等很直观的 显示出来. 在 vim 中也可以实现好像 vc, jbuilder 那样的类资源树, 当然比 那些会简单些, 不过也够好用的了. 就是用 javabrowser.vim 这个脚本实现的. 先到 vim online 去找到这个脚本文件.(在这还能找到许多有用的其他脚本) 然后在 goog