安卓篱笆

标题: Android安卓JNI/NDK开发(一) [打印本页]

作者: GuiTarvvm2098    时间: 2017-11-30 04:04
标题: Android安卓JNI/NDK开发(一)
[attach]401[/attach]

eclipse下使用JNI

1. 在项目根目录下创建jni文件夹 ,与src同级

2. 在jni文件中创建一个c文件后缀名为.c

/****这就是创建一个jni的native方法,用来调用c函数****/

3. 在java代码中,创建一个本地方法,名字随意,如helloFromc()方法,没有方法体,连大括号也不要。

但是必须加关键字native,表明该方法是本地方法,需要c语言来实现方法体。

public native String helloFromC();

/***这就是创建一个c函数,供native层来调用,所以名字很重要***/

4. 在jni文件夹中定义C语言写的函数实现这个方法,在c文件中添加<jni.h>头文件 ,这样才能识别jstring,env等那些东西

函数格式为

jni对应的返回值类型 Java_包名_方法名(两个必填参数){}

注意:数据类型不要搞错;

Java的j是大写;

包名里面的点最好都换成下划线

JNIEnv* env:是一个java虚拟即的地址指针,是个二级指针,因为env本来就是一个指针,再*一下就是二级指针

jobject obj:调用该c方法的对象,就这样照写

jstring Java_com_itheima_helloworld1_MainActivity_helloFromC(JNIEnv* env, jobject obj)//虽然本地native方法中helloFromc是无参方法,但是C语言中的必须加上这两个参数

5. 返回一个字符串,用c定义一个字符串

char* cstr = "hello from c";

6. 把c的字符串转换成java的字符串

jstring jstr = (*env)->NewStringUTF(env, cstr);

return jstr;

前面都是定义部分,定义好C语言后要编译,编译就需要用到ndk工具来进行编译,就要讲法ndk配置进环境变量 ,

配制方法就是把 路径:\android-ndk-r9b 加进path

7. 在jni中创建Android.mk文件 ,文件里面的内容:

LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VERS)

编译生成的类库起个名字

LOCAL_MODULE:=heihei//这里同样可以叫Hello

要编译的C语言文件

LOCAL_SRC_FILES:=Hello.c

include $(BUILD_SHARED_LIBRARY)

8. 在jni文件夹下打开cmd后执行ndk-build.cmd指令

9. java代码中加载so类库,调用本地方法。写在静态代码块中Static{loadLibrary(“库名”);}

-------------------mk文件详解start--------------

# $是调用编译工具链中的函数, 这里的作用是获取当前文件目录.

LOCAL_PATH := $(call my-dir)

# 清空并初始化编译工具链的变量.

# 注意: 会清空所有的LOCAL_变量, 但不会清空LOCAL_PATH的变量.

include $(CLEAR_VARS)

# 编译出来文件的名字, 编译系统会在名字前加lib前缀. 如果已经写lib, 不会再添加.

# 注意: 不可以加扩展名.

LOCAL_MODULE := atguigu

# 指定编译的源文件.如果多个源文件可以用空格连接起来

LOCAL_SRC_FILES := hello.c

# 指定编译文件类型

# 动态库(BUILD_SHARED_LIBRARY) 扩展名:.so 体积小.

# 静态库(BUILD_STATIC_LIBRARY) 扩展名:.a 体积大.

include $(BUILD_SHARED_LIBRARY)

----------------mk文件详解end------------------

AS下使用JNI(as版本1.5完美,其他版本有问题

1、在main下创建一个jni文件夹,与java同级

2、3、4、5、6和eclipse一样。

然后在project的gradle.properties中添加配置 android.useDeprecatedNdk=true ,为了兼容老版本

7、在app的build.gradle文件中的defaultConfig{}里面添加

ndk{

moduleName "Hello" //so文件: lib+moduleName+.so ,Hello就是后来要用的so库名

abiFilters "armeabi", "armeabi-v7a", "x86" //cpu的类型

}

然后build项目,使项目生成so文件,生成的so文件在app\build\intermediates\ndk\debug\lib下。

生成的链接库名叫“libHello.so”,当然我们也可以不写这段代码,也能编译生成so库,生成的名字是“libapp.so”,建议还是写上,不然多了就不行了

在这里我们会发现步骤7不同,as的少了创建mk文件这个步骤,其实as已经帮我们创建了,因为我们的在gradle文件中进行了配置

8、回到本地方法native那里,在写native方法之前加载so库,System.loadLibrary("Hello");通常这行代码写在代码块或静态代码块中。这样一样我们的native方法就会到Hello库中去找与之对应的c函数,其实我们更应该在创建native方法的时候就这样写,后面要build之前确定moudleName是否与我们加载的这个库名




欢迎光临 安卓篱笆 (http://www.okapk.cn/) Powered by Discuz! X3.2