一、编译、连接、交叉编译:
编译:把一个源文件 源代码 翻译(编译)成一个二进制文件的过程
连接:把编译生成的二进制,根据操作系统,根据当前处理器的类型.把这个二进制文件转化成一个真正可以执行的二进制文件.
交叉编译: 在一个操作系统平台(一种cpu的平台)上 编译出来另外一个操作系统平台上(另外一种cpu上)可以运行的代码.
.c-> .exe
.c-> elf 可执行的二进制文件
交叉编译,借助于一个工具链,工具链可以模拟目标平台的一些环境,把编译后的二进制文件链接成一个目标平台下可以执行的二进制代码.
二、ndk开发步骤:
1.创建一个android工程
2.JAVA代码中写声明native 方法 public native String helloFromJNI();
3.创建jni目录,编写c代码,方法名字要对应
4.编写Android.mk文件
5.Ndk编译生成动态库
6.Java代码load 动态库.调用native代码
三、ndk 开发入门 案例:使用java调用底层c代码返回返回字符串。
1、创建一个android工程:
2、在DemoActivity类中定义一个 native方法:
public class DemoActivityextends Activity {
//声明本地native方法 注意没有方法体
public native String helloFromJNI();
}
3、在应用程序目录下创建一个jni目录:在内部写Hello.c 的c文件。C文件如下:
#include
#include
//c与java之间的映射的函数库:
//通过 包名_类名_方法名-完成 java-c代码的映射
//方法名固定写法:Java_包名_类名_本地方法名(JNIEnv* env, jobject obj)
jstring Java_cn_itcast_ndk_DemoActivity_helloFromC(JNIEnv*env,
jobject obj) {
//*env 得到了 JNIEnv
// 因为JNIEnv 是JNINativeInterface的指针类型
// **env 得到JNINativeInterface结构体
char* str = "hellofrom c";
// return (**env).NewStringUTF(env,str);
return (*env)->NewStringUTF(env,str);
}
4、在jni目录下 编写Android.mk文件:
该文件中指定要编译的源文件的名称和编译出来的可执行文件的名称。
内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#告诉编译器编译出来的可执行性文件叫什么名字
LOCAL_MODULE := Hello
#告诉编译器 编译的源文件的名称
LOCAL_SRC_FILES := Hello.c
include $(BUILD_SHARED_LIBRARY)
5、Ndk编译生成动态库:(交叉编译)
使用Cygwin 工具到达工程的jni目录下/cygdrive/g/androidSpace/myndk/jni
使用ndk-build命令生成一个libHello.so文件,该文件被放在当前工程下的libs/armeabi/目录下。
生成的libHello.so是一个linux系统下可执行的二进制文件。
6、使用Java代码load 动态库.调用native代码:
就是将可执行的二进制文件(.so的c代码库文件)加载到java虚拟机中:
在静态代码块使用 System.loadLibrary("");方法
public class DemoActivityextends Activity {
static{
//把 的c代码的库文件加载到java虚拟机里面
// 不要写so的前缀lib 也不要写扩展名.so
System.loadLibrary("Hello");
}
//声明本地native方法 注意没有方法体
public native StringhelloFromJNI();
@Override
public voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
}
//点击按钮的事件:
public void click(View v){
String str = helloFromJNI();
Toast.makeText(this, str, 1).show();
}
}
四、jdk使用javah工具生成 jni中c代码中的方法名:
在含有native方法的java源文件的目录下,下使用javac 将.java文件编译成.class文件,
再使用javah 就会在当前目录下 生成 .h文件 该文件中有生成对应的c的方法名。
G:\androidSpace\myndk\bin\classes>javah com.li.myndk.DemoActivity
五、在实际开发中的NDK的开发步骤:
1.创建一个android工程
2.JAVA代码中写声明native 方法 public native String helloFromJNI();
3.用javah工具生成头文件
来到 工程classes目录下执行javah 命令:javahcom.li.myndk.DemoActivity
命令为: javah 全类名
在classes目录下就生成com_li_myndk_DemoActivity.h文件
4. 在工程下创建jni目录,引入头文件,根据头文件实现c代码
将com_li_myndk_DemoActivity.h文件拷贝到jni目录下
编写Hello.c文件: 在.C文件中引入 .h文件。
#include
#include"cn_itcast_ndk2_DemoActivity.h"
char* str = "abc ";
// return (**env).NewStringUTF(env, str);
return (*env)->NewStringUTF(env, str);
}
5.编写Android.mk文件
6.Ndk编译生成动态库
7.Java代码load 动态库.调用native代码
六、ndk开发的常见错误:
1. 忘记写android.mk文件,或者路径不正确
Android NDK: Your APP_BUILD_SCRIPT pointsto an unknown file: ./jni/Android.mk
2. android.mk文件语法错误
jni/Android.mk:4: *** 遗漏分隔符 。 停止。
3. c代码的语法出现问题
make: ***[obj/local/armeabi/objs/Hello/Hello.o] Error 1
一般出现了error 1 错误 是c代码的语法出现了问题.
需要先去查看第一个error对应的内容
error: 'intt' undeclar