NDK 的开发流程
1、NDK开发所需要的工具
windows 需要在windows下的环境 把c代码打包成 手机能用的函数库 首先模拟手机的环境 1 NDK .sh linux 批处理文件 .bat windows 头文件 stdio.h 编译器 interface 库函数 连接器 class 实现类 由于ndk有很多linux的批处理文件 最早基于linux开发 2 工具2 cygdriver 模拟linux系统环境 (windows操作系统) linux系统的模拟器 linux 把所有设备都生成了一个文件 3 cdt 为了方便在eclipse开发c代码 让c代码高亮显示 c/c++ developer tools
4 adt android developer tools 交叉编译 怎么用java代码调用c代码 生成的文件存放在armeabi (表示 arme cpu anroid binary interface)目录下
开发过程中进行将java和C进行交互的函数主要参考自NDK的安装文件下的jni.h文件中去查找对应的方法
2、具体开发步骤
- 定义一个c方法的接口 相当于在java代码中定义了一个接口 接口的实现方法是C语言实现的
1 public native String helloWorldFromC();
- 实现C代码
1 //方法名 严格按照jni的规范
2 jstring Java_com_example_helloworldformc_MainActivity_helloWorldFromC(JNIEnv* env,jobject obj)
- 生成 .mk文件 andrond.mk 告诉编译器 如何把c代码打包成函数库
1 Anroid.mk 文件
2 LOCAL_PATH := $(call my-dir) // 返回当前c代码目录
3 include $(CLEAR_VARS) // 清楚了所有 已local 开头的配置文件 唯独不清楚LOCAL_PATH
4
5 LOCAL_MODULE := hello // 库函数的名字 严格遵守makefile 格式 lib .so 如果前面加lib 不会自动生成了
6 LOCAL_SRC_FILES := Hello.c
7 include $(BUILD_SHARED_LIBRARY) // 加入库函数
- 把c代码 打包成函数库 用到了安装的环境cygdriver
- 在java代码中 引入库函数,一般用静态代码块引入
1 static{
2 System.loadLibrary("hello");// 注意事项 去掉前面的lib 后面的.so
3 }
- 使用方法
1 String res = helloWorldFromC() ;
3、JNI常见错误
1 错误1 忘记方法的参数 2 错误2 203-28 03:41:56.758: E/AndroidRuntime(821): java.lang.UnsatisfiedLinkError: Native method not found: com.example.error.DemoActivity.helloWorld:()Ljava/lang/String; 3 错误3 一般没有日志打印 直接报错工程停止 一般c代码有运行错误 4 错误4 在交叉编译的工具链上报错 c代码有编译错误 比如 一些函数没有声明 一些类型没有声明 少符号 5 错误5 没有Android.mk 文件 6 错误6 Android.mk 文件有错 ,一般以mk开头的报错 7 错误7 引用别人.so 函数库 需要你自己native方法对应类的包名 和之前打包成.so函数库的包名一致
4、自动生成 java本地方法对应的c代码的方法名 javah 指令 +全类名,相当于头文件
1.6 class C:workspaceHelloWorldFromC2binclasses 1.7 src C:workspaceHelloWorldFromC2src
5、C语言回调java方法
java代码开发好了 一个方法 C会掉java代码 javap -s 打印方法的签名 注意要cd到 C:workspaceHelloWorldFromC2binclasses 传全类名 通过反射 调用java代码
1 /*
2 Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider");
3 Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{});
4 declaredMethod.invoke(forName.newInstance(), new Object[]{});
5 */
6
7 ///jclass (*FindClass)(JNIEnv*, const char*);
8 jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
9 // jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
10 // 方法签名 参数和返回值
11 jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V");
12 // void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
13 (*env)->CallVoidMethod(env,jobject,methodId);
- 干货|机器学习:Python实现聚类算法之K-Means
- 美团点餐—listview内部按钮点击事件
- C4C和CRM里获取当前登录用户分配的Organization Unit信息
- 使用Excel调用ABAP系统的函数
- 如何计算并测量ABAP及Java代码的环复杂度Cyclomatic complexity
- 漫谈版本控制系统
- 带你零基础入门express
- 动态控制C4C UI元素的显示和隐藏
- 深度学习(deep learning)发展史
- 遗传算法简述
- Spark详解03Job 物理执行图Job 物理执行图
- 干货|Kotlin入门第一课:从对比Java开始
- Spark详解04Shuffle 过程Shuffle 过程
- Spark详解02Job 逻辑执行图Job 逻辑执行图
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter基础widgets教程-FittedBox篇
- muduo Dispatcher消息分发器 通过多态和模板进行向上类型转换
- Flutter基础widgets教程-FloatingActionButton篇
- VBS基础篇 - 对象(3) - FileSystemObject对象
- vbs 实现文件夹拷贝--采用堆栈不递归
- vbs - 一个简单的栈 -- 只能存储类对象
- Flutter基础widgets教程-FlutterLogo篇
- 配置压缩版mysql 5.7以上版本
- nutz 自定义sql的使用
- nutz 中 子模块 参数的使用。
- java向mysql插入数据乱码问题解决
- java向数据库中插入中文出现乱码
- Flutter基础widgets教程-FractionallySizedBox篇
- 关于myeclipse控制台输出中文乱码的问题
- nutz 自定义查询 分页 取值