一、NDK与SDK以及JNI的区别
SDK(Standard Develop Kit)是Google提供的Android标准开发工具包,里面包含了完整的 API文档,各Android版本的开发库,Android的虚拟机以及Android的打包工具等,开发应用层项目用SDK足矣。众所周知Android所使用的应用层开发语言为java,所以没有iOS系统应用那么流畅, 虽然在本质上我们无法改变这个事实,随着Android内核及架构的进一步升级与优化这个流畅差距也在进一步缩小。
NDK(Native Develop Kit)是Google为Android进行本地开发而放出的一个本地开发工具, 包括Android的Native API、公共库以及编译工具, 值得注意的是NDK要在Android 1.5以上版本才能被支持。
JNI (Java Native Interface)是Java众多开发技术中的一门,意在利用本地代码,为Java程序提供 更高效,更灵活的拓展。应用场景包括:对运行效率敏感的算法实现、跨平台应用移植、调用系统的底层驱动、调用硬件等。如下图一,你也可以理解成JNI是NDK与SDK的桥梁。
图一
图二
二、NDK有神马用?
通过使用NDK进行开发编译,我们不仅可以提高我们的应用运行能力,而且还可以实现核心算法跨平台移植以及OpenCV交互处理、音频处理、调用驱动等(因为编译后生成的.so文件可以直接被本地调用而不需要经过DVM进行存取,无论在保密性还是在高效性方面都要比SDK更胜一筹)
二、Mac os x下配置 Android ndk
1、配置前,你必须已经安装了Android的开发环境。
2、到http://developer.android.com/tools/sdk/ndk/index.html这里下载最新的ndk。
3、1)开启终端,输入命令 pico .bash_profile
2)在终端中输入: export PATH=$PATH:/Users/marco/Documents/android-ndk-r8d
3)在终端中输入: A_NDK_ROOT=/Users/marco/Documents/android-ndk-r8d
4)在终端中输入:export A_NDK_ROOT
5)最后保存( control+X) 选 Y
4、开启你的Eclipse选则ADT偏好设置,点击NDK选项,然后导入你刚刚下载的ndk所在的路径,如下图:
然后大功告成,开支香槟庆祝下吧~0.0
三、案列详解
项目整体目录
如上图,ndk开发其实不是很难(基础入门来说0.0),和android sdk应用开发的区别可能在于多了个jni以及obj文件吧。
jni文件:存放你编写的c/c++文件以及Android.mk文件
Android.mk文件简介:Android.mk file用来向编译系统描述你的源代码。具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk file中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。
obj文件:该文件夹是通过编译你的jni下的c/c++文件后生成的,里面有动态链接库.so文件。
0.0好了废话不多说了,代码才是王道!
MainActivity.java
package com.example.mysimplendk;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView mTipsTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findView();
MyJNI jni = new MyJNI();
mTipsTxt.setText(jni.testMyNDK("hello"));
}
private void findView(){
mTipsTxt = (TextView)findViewById(R.id.mytext);
}
static{
System.loadLibrary("myjni");
}
}
MyJNI.java
package com.example.mysimplendk;
public class MyJNI {
/**
*
* <p>
* The MyJNI class
* </p>
* @author marco
*
*/
public native String testMyNDK(String tips);
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/mytext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := com_example_mysimplendk_MyJNI.cpp //LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。
LOCAL_MODULE := myjni //LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。
include $(BUILD_SHARED_LIBRARY)
com_example_mysimplendk_MyJNI.cpp
#include <stdio.h>
#include <stdlib.h>
#include "com_example_mysimplendk_MyJNI.h"
JNIEXPORT jstring JNICALL Java_com_example_mysimplendk_MyJNI_testMyNDK
(JNIEnv *e, jobject j,jstring str) {
//jstring是JNI中对应于String的类型,但是和基本类型不同的是,jstring不能直接当作C++的string用。
//jint则对应于int类型
const char *number = e->GetStringUTFChars(str, 0);
char test[200] = "";
strcpy(test, number);
strcat(test, " world");
e->ReleaseStringUTFChars(str, number);
return e->NewStringUTF(test);
}
关于com_example_mysimplendk_MyJNI.cpp的头文件生成办法如下:
1)开启终端,cd /Users/marco/Workspaces1/Java2/MySimpleNDK/src(你的项目src文件所在的路径)
2)在终端输入:javac com/example/myjni/JNI.java (JNI.java文件就是你所需要通过jni去调用c/c++的那个类,以native为标示符)
3)在终端输入:javah -jni com.example.myjni.JNI
4)刷新项目列表,就会看到你所生成的头文件(注:.cpp文件必须与头文件命名一致)
Finally:编译生成obj文件
1)开启终端,cd /Users/marco/Workspaces1/Java2/MySimpleNDK(你的项目所在的路径)
2)在终端输入:ndk-build
3)大功告成可以洗洗刷刷碎觉了。然后运行项目就会看到hello world了^—^
与在windows系统下ndk开发相比,mac要简单多了,windows下要装模拟linux的软件进行编译,而mac则不需要,直接在终端编译即可生成.so文件,可能是因为mac的内核是unix的缘故吧