Android NDK 学习之调用Java函数
本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件。
在Eclipse中添加配置NDK,路径如下Eclipse->Window->Preferences->Android->NDK ,选择NDK的路径,然后Apply即可。
新建一个名为AndroidJNI_MethodCall的Android工程,新建一个jni的文件夹,其目录下文件树列表如下:
├── jni
│ ├── Android.mk
│ ├── Application.mk
│ └── methodcall
│ ├── Android.mk
│ ├── logger.h
│ └── methodcall_jni.c
jni/Application.mk文件内容如下:
APP_ABI := all
jni/Android.mk,主要用来指定顺序执行所有子文件夹下面的makefile文件,内容如下:
include $(call all-subdir-makefiles)
jni/methodcall/Android.mk,主要用来指定需要编译出的动态库的名称,以及需要编译的源文件,内容如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := methodcall_jni
LOCAL_SRC_FILES := methodcall_jni.c LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)
jni/methodcall/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/methodcall/methodcall_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/MethodCall" JNIEXPORT void JNICALL native_Method(JNIEnv *env, jobject obj) {
/*jclass cls = (*env)->GetObjectClass(env, obj);
//在被给的类中方法执行一个查询。查询是依靠名字和方法的类型描述符。
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
if (NULL == mid) {
return ;
}
LOGI("In C \n");
//然后本地代码调用"CallVoidMethod"。"CallVoidMethod"调用一个实例方法,它返回一个 void类型。你传递一个对象(object),方法 ID 和实际参数
(*env)->CallVoidMethod(env, obj, mid);*/ jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "_callback", "()V");
if (NULL == mid) {
return ;
} LOGI("In C \n");
(*env)->CallStaticVoidMethod(env, cls, mid);
} /**
* Java和JNI函数绑定
*/
static JNINativeMethod method_table[] = {
{ "nativeMethod", "()V", (void*) native_Method },
}; /**
* 注册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; import android.util.Log; public class MethodCall {
public native void nativeMethod(); public void callback() {
Log.d("Test", "In Android");
} public static void _callback() {
Log.d("Test", "In Android static");
} static {
System.loadLibrary("methodcall_jni");
}
}
package com.clarck.jni; import android.app.Activity;
import android.os.Bundle; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); MethodCall methodCall = new MethodCall();
methodCall.nativeMethod();
}
}
执行Ctrl+B执行编译,运行工程即可。
Android NDK 学习之调用Java函数的更多相关文章
- Android NDK 学习之接受Java传入Object数组
本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...
- Android NDK 学习之接受Java传入的Int数组
本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...
- Android NDK 学习之接受Java传入的字符串
本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...
- Android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题
最近在移植网络摄像机里的p2p库到android平台,需要用到jni,最近在c线程了调用java函数的时候 出现一个问题,假如在同一个线程调用java函数是没问题的,但在一个c线程了调用java函数就 ...
- 一、Android NDK编程预备之Java jni简介
转自: http://www.eoeandroid.com/thread-264384-1-1.html 游戏开发 视频教程 博客 淘帖 论坛›eoe·Android应用开发区›Androi ...
- 三、Android NDK编程预备之Java jni入门创建C/C++共享库
转自: http://www.eoeandroid.com/thread-264971-1-1.html 应网友回复,答应在两天前要出一篇创建C/C++共享库的,但由于清明节假期,跟朋友出去游玩,丢手 ...
- 二、Android NDK编程预备之Java jni入门Hello World
转自: http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264543&fromuid=588695 昨天已经简要介绍了J ...
- Android NDK开发及调用标准linux动态库.so文件
源:Android NDK开发及调用标准linux动态库.so文件 预备知识及环境搭建 1.NDK(native development Kit)原生开发工具包,用来快速开发C.C++动态库,并能自动 ...
- Android开发学习必备的java知识
Android开发学习必备的java知识本讲内容:对象.标识符.关键字.变量.常量.字面值.基本数据类型.整数.浮点数.布尔型.字符型.赋值.注释 Java作为一门语言,必然有他的语法规则.学习编程语 ...
随机推荐
- 使用SoapUI发送Post请求
https://www.cnblogs.com/xiaowangzi1110/p/8544264.html 使用SoapUI发送Post请求 SoapUI作为一个开源的工具,其具备强大的功能.易用的界 ...
- asp中出现“错误 '80040e14' FROM 子句语法错误”原因
当你的sql语句中出现 “错误 '80040e14' FROM 子句语法错误.”错误时,请注意了,那有可能是你的表名的命名不规范造成的,比如你的表名是“user”那么这杨的表名是不行的,那么在sql语 ...
- mac QQ 语音或视频时其他声音变小的解决办法
在使用MacBook的时候,使用QQ视频的同时 看视频 听歌都会发现,QQ视频声音正常,其他软件的声音会很小很小.怎么解决呢,首先 开启QQ后,在视频之前: 1.打开终端输入以下命令. printf ...
- Linux strace追踪命令详解
strace介绍 strace命令是一个集诊断.调试.统计与一体的工具,我们可以使用strace对应用的系统调用和信号传递的跟踪结果来对应用进行分析,以达到解决问题或者是了解应用工作过程的目的.当然s ...
- Java以UTF-8格式读写及追加写文件示例
package test; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; im ...
- Python3 IO编程之操作文件和目录
如果我们要操作文件,目录,可以在命令行下面输入操作系统提供的各种命令来完成.比如ls,cp等命令 如果要在python程序中执行这些目录和文件的操作怎么办?其实操作系统提供的命令指示简单地调用了操作系 ...
- vue路由跳转取消上个页面的请求和去掉重复请求
vue路由跳转取消上个页面的请求和去掉重复请求 axios 的二次封装(拦截重复请求.异常统一处理) axios里面拦截重复请求
- certutil在传输payload中的新奇技巧
好久没更新博客了,最近在实习的过程中还是见识到不少东西. 不多说,直接开始正文. 首先说一下certutil在渗透测试中用到的特别多,下载文件,计算hash,以及base64编码等等. 在这里介绍ba ...
- MySQL的索引有哪些
一.索引是什么 索引,在MySQL中也叫“键(key)”,是存储引擎用于快速找到记录的一种数据结构.如果把数据库的一张表比作一本书,那索引则是这本书的目录,通过目录,我们能快速找到我们想要的主题所对应 ...
- ajax后台跳转无效的原因
Ajax只是利用脚本访问对应url获取数据而已,不能做除了获取返回数据以外的其它动作了.所以浏览器端是不会发起重定向的. 1)正常的http url请求,只有浏览器和服务器两个参与者.浏览器端发起一个 ...