本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件。

在Eclipse中添加配置NDK,路径如下Eclipse->Window->Preferences->Android->NDK ,选择NDK的路径,然后Apply即可。

新建一个名为AndroidJNI_CathcThrow的Android工程,新建一个jni的文件夹,其目录下文件树列表如下:

├── jni
│   ├── Android.mk
│   ├── Application.mk
│   └── catchthrow
│      ├── Android.mk
│      ├── catchthrow_jni.c
│      └── logger.h

jni/Application.mk文件内容如下:

APP_ABI := all

jni/Android.mk,主要用来指定顺序执行所有子文件夹下面的makefile文件,内容如下:

include $(call all-subdir-makefiles)

jni/catchthrow/Android.mk,主要用来指定需要编译出的动态库的名称,以及需要编译的源文件,内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE     := catchthrow_jni
LOCAL_SRC_FILES := catchthrow_jni.c LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)

jni/catchthrow/logger.h 主要用来在JNI层打印日志,内容如下:

#include <jni.h>
#include <android/log.h> /**
* 定义log标签
*/
#define TAG "jni_logger" /**
* 定义info信息
*/
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) /**
* 定义debug信息
*/
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) /**
* 定义error信息
*/
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

jni/catchthrow/catchthrow_jni.c,主要用来注册绑定java函数和native函数,以及java函数在c中相应函数的具体实现, 内容如下:

#include "logger.h"

#ifndef NULL
#define NULL ((void *) 0)
#endif /**
* 获取数组的大小
*/
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) /**
* 指定要注册的类,对应的完整的java类名
*/
#define JNIREG_CLASS "com/clarck/jni/CatchThrow" /**
* 返回成员实例域
*/
JNIEXPORT void JNICALL native_catchThrow_doit(JNIEnv *env, jobject obj) {
jthrowable exc;
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V"); if (NULL == mid) {
return ;
}
(*env)->CallVoidMethod(env, obj, mid);
exc = (*env)->ExceptionOccurred(env);
if (exc) {
jclass newExcCls;
(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);
newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
if (newExcCls == NULL) {
return ;
}
(*env)->ThrowNew(env, newExcCls, "thrown from C code");
}
} /**
* Java和JNI函数绑定
*/
static JNINativeMethod method_table[] = {
{ "doit", "()V", (void*) native_catchThrow_doit },
}; /**
* 注册native方法到java中
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods) {
jclass clazz;
clazz = (*env)->FindClass(env, className);
if (clazz == NULL) {
return JNI_FALSE;
} if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < ) {
return JNI_FALSE;
} return JNI_TRUE;
} /**
* 调用注册方法
*/
int register_ndk_load(JNIEnv* env) {
return registerNativeMethods(env, JNIREG_CLASS, method_table,
NELEM(method_table));
} JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return result;
} register_ndk_load(env); //返回jni的版本
return JNI_VERSION_1_4;
}

接着在Project中右键Android Tools->Add Native Support,最后java层调用如下:

package com.clarck.jni;

public class CatchThrow {
public native void doit() throws IllegalArgumentException; public void callback() throws NullPointerException {
throw new NullPointerException("CathcThrow.callback");
} static {
System.loadLibrary("catchthrow_jni");
}
}
package com.clarck.jni;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); CatchThrow c = new CatchThrow();
try {
c.doit();
} catch (Exception e) {
Log.d("Test", "In Java: \n \t" + e);
}
}
}

执行Ctrl+B编译,然后运行即可。

最新文章

  1. Permutation Sequence
  2. 【USACO 2.4】Overfencing(bfs最短路)
  3. ACM 字符串 题目整理
  4. python生成汉字图片字库
  5. iOS dispatch_source_t的理解
  6. Mongo数据模型
  7. Unsupervised Learning: Use Cases
  8. Planner – 项目管理软件
  9. 占成本85% SSD深度选购教你如何看颗粒
  10. 一个RPC的demo
  11. OBJECT-ORIENTED
  12. Java获取异常堆栈信息
  13. SpringMVC源码分析--容器初始化(四)FrameworkServlet
  14. Handler基本运行机制
  15. cpu的组成及分工
  16. CCF2014032窗口(C语言)
  17. Dynamic Binding
  18. python 正则表达式的使用
  19. 整理JavaScript循环数组和对象的方法
  20. RabbitMQ介绍及安装部署

热门文章

  1. 002-guava String 操作
  2. QThread: Destroyed while thread is still running
  3. docker镜像的导入导出
  4. RabbitMQ 入门教程(PHP版) 第一部分:Hello World
  5. ios开发注意事项小总结
  6. spring 传播行为与数据库事务ACID
  7. Codeforces Round #556 (Div. 2) D. Three Religions 题解 动态规划
  8. RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现)
  9. 知识点-Spark小节
  10. LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14