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
*
*/
Android JNI开发提高篇的更多相关文章
- Android应用开发提高篇(1)-----获取本地IP
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/21/2361802.html 一.概述 习惯了Linux下的网络编程,在还没用智能机之前就一直想 ...
- Android应用开发提高篇(6)-----FaceDetector(人脸检测)
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/10/2388776.html 一.概述 初次看到FaceDetector这个类时,心里想:And ...
- Android应用开发提高篇(4)-----Socket编程(多线程、双向通信)
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 一.概述 关于Socket编程的基本方法在基础篇里已经讲过,今天把 ...
- Android应用开发提高篇(5)-----Camera使用
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/06/2382679.html 一.概述 Camera是手机的一个很重要的设备,可以说现在的每一部 ...
- Android应用开发提高篇(3)-----传感器(Sensor)编程
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/29/2373420.html 一.概述 Android支持的传感器种类越来越多了,这确实是一件可 ...
- Android应用开发提高篇(2)-----文本朗读TTS(TextToSpeech)
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/26/2368696.html 一.概述 TextToSpeech,就是将文本内容转换成语音,在其 ...
- android 串口开发第二篇:利用jni实现android和串口通信
一:串口通信简介 由于串口开发涉及到jni,所以开发环境需要支持ndk开发,如果未配置ndk配置的朋友,或者对jni不熟悉的朋友,请查看上一篇文章,android 串口开发第一篇:搭建ndk开发环境以 ...
- JNI 开发基础篇:Android开发中os文件的探索
正题: android开发中,时长会遇到os文件的使用,那么os文件到底是什么?在这篇文章中会进行说明. .os文件在android中意味着C语言书写的方法,经android提供的ndk进行编译,从而 ...
- Android应用开发基础篇(1)-----Button
Android应用开发基础篇(1)-----Button 一.概述 Button,顾名思义就是按钮的意思,它主要的功能是响应用户按下按钮时的动作. 二.应用 新建一个工程, ...
随机推荐
- C学习之结构体
结构体(struct) 结构体是由基本数据类型构成的.并用一个标识符来命名的各种变量的组合,结构体中可以使用不同的数据类型. 1. 结构体说明和结构体变量定义 在Turbo C中, 结构体也是一种数据 ...
- C++学习之运算符重载的总结
C++学习之运算符重载的总结 运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用域不同类型的数据导致不同行为的发生,C++为运算符重载提供了一种方法,即运算符重载函数 ...
- 页面的拼装配置Appache SSI
O(∩_∩)O哈哈哈~今天又遇到了一个好东西,记录一下下哈~ 一个网站,有些页面的头部跟尾部是相同的,还在为总是复制,为错了一个小小点而需要改好多个页面烦恼吗?现在我知道怎么来偷懒了! 1.首先找到c ...
- h5的api dom全屏展示
下面是完整的例子,暂不做分析 <!DOCTYPE html> <html> <head> <title> FullScreen API 演示</t ...
- 解析Tensorflow官方PTB模型的demo
RNN 模型作为一个可以学习时间序列的模型被认为是深度学习中比较重要的一类模型.在Tensorflow的官方教程中,有两个与之相关的模型被实现出来.第一个模型是围绕着Zaremba的论文Recurre ...
- JConsole是什么
从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行.您可以轻松地使用 JConsole(或者,它更高端的 “ ...
- 假设将synthesize省略,语义特性声明为assign retain copy时,自己实现setter和getter方法
假设将synthesize省略,而且我们自己实现setter和getter方法时,系统就不会生成相应的setter和getter方法,还有实例变量 1,当把语义特性声明为assign时,setter和 ...
- java中File类详解
构造函数 代码如下: public class FileDemo { public static void main(String[] args){ //构造函数File(St ...
- chrome扩展小试
chorme 扩展 小试 官方文档 http://developer.chrome.com/extensions 非官方中文文档 http://docs.lmk123.com/getstarted.h ...
- iframe跨域通信方案
概述 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: 首先什么 ...