Native Development Kit
下载NDK开发包
链接:http://developer.android.com/ndk/downloads/index.html
选择NDK r10e
android-ndk-r10e-windows-x86_64.exe
自解压文件大小400M,解压后3G+。
配置NDK环境变量
将ndk目录添加到系统环境变量path,然后在新打开的cmd输入ndk-build验证:
HelloJni
Eclipse安装ADT的时候,安装的有Android Native Development Tools,
导入位于android-ndk-r10e\samples\hello-jni的例子到Eclipse:
初始的目录结构:
然后打开cmd,切换到HelloJni项目目录:
执行ndk-build进行编译:
完成后回到Eclipse刷新HelloJni目录,发现增加了obj文件夹,里面有各个架构对应的.so库文件,如下图:
然后运行工程:
注意到上面执行ndk-build时,编译了很多架构,时间会长一些,如果只想编译我们需要的arm,可以将项目jni目录下的Application.mk文件的以下内容进行注释:
#APP_ABI := all
清除上次的编译:
ndk-build clean
再次ndk-build,很快完成:
第一个NDK项目
1.新建Android项目
在MainActivity里创建一个native方法:
public static native String getStringFromC();
2.创建jni目录
3.编写java层native方法
4.生成JNI头文件
- javah
cmd切换到项目目录,然后执行:
javah -classpath bin/classes -d jni com.zms.hellondk.MainActivity
javah -classpath bin/classes;D:\Android\sdk\platforms\android-22\android.jar -d jni com.zms.hellondk.MainActivity
这样比较麻烦,也可以: 添加android.jar到环境变量:D:\Android\sdk\platforms\android-22\android.jar
可以看到jni目录下生成了.h头文件:
格式如下:
然后在jni目录下创建我们自己的c文件:
hello.c
#include<stdio.h>
#include<stdlib.h>
#include"com_zms_hellondk_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_zms_hellondk_MainActivity_getStringFromC(
JNIEnv env, jclass jclass) {
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
然后在jni目录下创建Android.mk文件:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := HelloNdk
LOCAL_SRC_FILES := hello.c #对哪个c文件进行编译
include $(BUILD_SHARED_LIBRARY)
然后进入cmd切换到工程目录进行编译:
注意,MainActivity里要写加上loadLibrary,引号里是Module名,static区声明的代码会先于onCreate方法执行:
package com.zms.hellondk;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends Activity {
public static native String getStringFromC();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textFromJni = (TextView) findViewById(R.id.textFromJni);
textFromJni.setText(getStringFromC());
}
static {
System.loadLibrary("HelloNdk");
}
}
否则会出现以下错误:
(- -,不要问我是怎么知道的)
NDK相关概念
- NDK的应用场景
- 代码的保护(Java代码容易被反编译,C/C++库)
- 代码复用性:多数开源库用C/C++编写(如OpenCV,FFmpeg等)
- 便于移植(在其他嵌入式平台上再次使用,如iOS)
- 交叉编译
使用工具在一个平台编译生成另一个平台可执行的代码。
- JNI(Java Native Interface)
是Java平台标准的一部分,允许Java代码和其他语言代码进行交互
- 链接库(静态,动态)
- 静态链接库
- 动态链接库
- mk配置文件(make)参数
- ndk开发包目录