Android JNI开发提高篇

有关JNI的开发技术,我们继续围绕Android平台进行,JNI可以支持C或C++,从目前为止我们写过的JNI代码均为C实现的,即文件名为.C而C++的和这些有什么不同呢? Android平台上的JNI一般使用C还是C++编写呢?

Android平台在中间层和大部分的类库的底层使用了C++的开发方式,后缀为.cpp,比如Android Framework、OpenCore、Webkit、SQLite等等。使用C++好处就是可以使用很多库但目前Android不支持STL,我们知道C表示字符串都是字符数组,但C++可以使用类似string这样的类型表示。

1. 代码上编写C和C++有啥区别

这里Android123就以将Java的unicode字符串转为jni中的utf8,然后再返回一个jstring类型为例子,可以看到jni和java之间字符串的转换方法。

C的实现:

JNIEXPORT jstring JNICALL Java_Android123_CwjC (JNIEnv *env, jobject obj, jstring string) 
{
   const char *strUTF = (*env)->GetStringUTFChars(env, string, 0);
   char szBuffer[255];
   strcpy(szBuffer, strUTF);
  (*env)->ReleaseStringUTFChars(env, string, strUTF);
  return (*env)->NewStringUTF(env, szBuffer);
}

C++的实现:

JNIEXPORT jstring JNICALL Java_Android123_CwjCpp (JNIEnv *env, jobject obj, jstring string)
{
  const char *strUTF = env->GetStringUTFChars(string, 0);
  char szBuffer[255];
  strcpy(szBuffer, strUTF);
env->ReleaseStringUTFChars(string, strUTF);
return env->NewStringUTF(szBuffer);
}

我们加粗了主要区别的关键字,可以看到C++的代码更简练。

2. JNI操作数组代码

JNI中处理数组通用对象为jobjectArray 当然常规的类型比如整形为jintArray,布尔型为jbooleanArray,但没有出现jstringArray这样的类型,有关字符数组的处理我们将在下次的 Android JNI开发进阶篇 详细说明 。处理数组时我们需要考虑数组的长度不能为0才能继续操作,不然就会有访问越界等问题,在JNI中提供了通用类型的GetArrayLength函数。我们从Java传入一个以整形数组,在JNI中将每个元素相加为例返回一个整形告诉Java运算的结果。

JNIEXPORT jint JNICALL Java_Android123_CwjTest (JNIEnv *env, jobject obj, jintArray array) 
{
  int sum = 0;
  jsize length = (*env)->GetArrayLength(env, array);  //获取数组长度

if(length==0)   //防止异常发生,如果是空的需要返回了
     return 0;
  
  jint *pointer = (*env)->GetIntArrayElements(env, array, 0); //获取数组指针
  for (int i=0; i<length; i++)
  { 
     sum += pointer[i]; //相加每个数组元素
  }
  (*env)->ReleaseIntArrayElements(env, array, pointer, 0); //释放内存,这个不能忘了
  return sum;
}

如何在JNI中构造一个数组呢?  Android开发网给大家一个简单的示例,返回一个整形数组:

JNIEXPORT jobjectArray JNICALL
Java_Android123_CwjTest2(JNIEnv *env, jclass clazz)
{
jobjectArray result; //定义返回对象
  
jclass intArrayClazz = (*env)->FindClass(env, "[I"); //查找整形数组
if (intArrayClazz == NULL)
{
  return NULL; 
}
result = (*env)->NewObjectArray(env, size, intArrayClazz, NULL); //构造一个新的数组对象
if (result == NULL) 
{
  return NULL;  
}

for (int i = 0; i < 10 ; i++)  //循环10次
{
  jint szBuffer[256]; 
  int j;
  
  jintArray newIntArray = (*env)->NewIntArray(env, 10); //构造10个整形数组
  if (newIntArray == NULL)
  {
   return NULL;  
  }
  for (j = 0; j < 10 ; j++) //10个
  {
   szBuffer[j] = i + j;
  }
  (*env)->SetIntArrayRegion(env, newIntArray, 0, 10, szBuffer); //设置长度为10个
  (*env)->SetObjectArrayElement(env, result, i, newIntArray);
  (*env)->DeleteLocalRef(env, newIntArray);
}
return result;
}

3.  JNI中有关异常的处理

JNI中抛出异常没有try...catch这样的,而是直接抛出错误

方法1:  使用ThrowNew,比如IOException类发生了FileNotFound

(*env)->ThrowNew(env,(*env)->FindClass("java/io/IOException"),"CWJLog Error, IOException");

方法2:  使用Throw,自己构造

jclass clazz = (*env)->FindClass(env, "java/io/IOException");
  jmethodID methodId = (*env)->GetMethodID(env, clazz, "<init>", "()V");
  jthrowable throwable = (*env)->NewObject(env, clazz, methodId);

(*env)->Throw(env, throwable);

/**
* @author 张兴业
* 邮箱:xy-zhang#163.com
* android开发进阶群:278401545
*
*/

时间: 2024-11-08 23:12:25

Android JNI开发提高篇的相关文章

Android应用开发提高篇(1)-----获取本地IP

链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/21/2361802.html 一.概述 习惯了Linux下的网络编程,在还没用智能机之前就一直想知道怎么得到手机的IP地址(玩智能机之前我是不搞手机应用的).好了,得知Android是基于Linux内核的,那么不就可以利用之前学的Linux下的网络编程方法来获取IP了吗?呵呵,其实这是比较底层的方法,在Android上,完全可以利用Java的API来实现,而且实现的代码非常简单.下面的实现只可

Android应用开发提高篇(6)-----FaceDetector(人脸检测)

链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/10/2388776.html 一.概述 初次看到FaceDetector这个类时,心里想:Android真的很强大.但直到我实际应用它的时候,心情从高山跌倒了谷底(看实现中的结果就知道了),再仔细看看官方文档,才知道这个类是API LEVEL1的,我就晕了,这就说明这个类很早就有了,但为什么到现在还没有得到改善呢.写这篇文章的目的还有一个,就是想强调一下用SurfaceView来画图的时候,要

Android应用开发提高篇(4)-----Socket编程(多线程、双向通信)(转载)

转自:http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 一.概述 关于Socket编程的基本方法在基础篇里已经讲过,今天把它给完善了.加入了多线程,这样UI线程就不会被阻塞:实现了客户端和服务器的双向通信,只要客户端发起了连接并成功连接后那么两者就可以随意进行通信了. 二.实现 在之前的工程基础上进行修改就可以了. MyClient工程的main.xml文件不用修改,只需要修改MyClientActivity.java文件

Android应用开发提高篇(2)-----文本朗读TTS(TextToSpeech)

链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/26/2368696.html 一.概述 TextToSpeech,就是将文本内容转换成语音,在其他的一些应用中经常可以看到.这个功能还是挺强大的,但是用户利用它来编写应用却很简单. 二.要求 能够将文本内容转换成语音并朗读出来:可以一次全部朗读出来,也可以边写边读:可以将文本保存为语音文件. 三.实现 新建工程MySpeak,修改/res/layout/main.xml文件,在里面添加一个Ed

Android应用开发提高篇(5)-----Camera使用

链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/06/2382679.html 一.概述 Camera是手机的一个很重要的设备,可以说现在的每一部手机上都有.回想当时在Linux搞摄像头编程真的要捏一把汗.有人会说在Linux下装个opencv就可以通过它的函数来使用摄像头啦,但我并没有这么做,我还是用最原始的方法(V4L2)实现了.之前研究过Android关于摄像头这部分的源码,毫无疑问,Android关于摄像头底层的实现用的也是V4L2.

Android jni开发有哪些常见的错误

我们在Android jni开发中,特别是对于刚入门学习Android jni开发的同学来说,往往会遇到很多错误,这里总结了我们经常遇见的错误.这些错误,你是否经常遇到. 错误1:java.lang.UnsatisfiedLinkError: Native method not found: 本地方法没有找到 1.本地函数名写错 2.忘记加载.so文件 没有调用System.loadlibrary 错误2:findLibrary returned null 1.System.loadLibrar

Android应用开发进阶篇-场景文字识别

由于研究生毕业项目需要完成一个基于移动终端的场景文字识别系统,虽然离毕业尚早,但出于兴趣的缘故,近一段抽时间完成了这样一套系统.基本的架构如下: 客户端:Android应用实现拍摄场景图片,大致划出感兴趣文字区域,通过socket通信上传服务器端识别; 服务器端:Python server进行socket通信监听,连通后调用文字识别引擎(exe可执行程序),将识别结果返回; 下面是系统运行示例图: 1. 客户端 包含两个Activity,: MainActivity主界面如上图左1,选择拍摄后调

Android JNI入门第一篇——HelloJni

android支持使用NDK开发C程序,关于配置NDK环境问题应该不用再赘述了,这个网上有很多,这里通过一篇实例来讲述简单的JNI开发,大家可以参考这篇文章(Get Your Eclipse-Integrated NDK On!)搭建Eclipse编译C语言为so文件的开发环境. native方法实现步骤如下: 1.在Java中声明native()方法,然后编译(javac): 2.用javah产生一个.h文件: 3.编写包含.h文件的c文件 4.编译c文件 5.使用编译成功的so文件. 第一步

Android应用开发基础篇(12)-----Socket通信(转载)

转自:http://www.devdiv.com/android_socket_-blog-258060-10594.html 一.概述 网络通信无论在手机还是其他设备上都应用得非常广泛,因此掌握网络编程是非常有必要的,而我觉得socket编程是网络编程的基础.在进入正题之前,先介 绍几点网络知识,一:socket编程有分TCP和UDP两种,TCP是基于连接的,而UDP是无连接的:二:一个TCP连接包括了输入和输出两条独立的 路径:三:服务器必须先运行然后客户端才能与它进行通信.四:客户端与服务