一、NDK開發介紹。
分析Android框架不難發現,Android是基于Linux的開源操作系統。也就是說Android的底層是基于C實現的,但是Android SDK是基于Java實現的。這就意味著Android應用程序在運行時,Android虛擬機會實現Java與C語言之間的調用(Java調C我們稱之為JNI)。 其實自Android平臺從誕生起,就已經支持C、C++開發。雖說基于Android SDK進行開發的第三方應用都必須使用Java語言。但這并不等同于“第三方應用只能使用Java”。在Android SDK首次發布時,Google就宣稱其虛擬機Dalvik支持JNI編程方式,也就是第三方應用完全可以通過JNI調用自己的C動態庫,即在Android平臺上,“Java+C”的編程方式是一直都可以實現的。
不過,Google也表示,使用原生SDK編程相比Dalvik虛擬機也有一些劣勢,Android SDK文檔里,找不到任何JNI方面的幫助。即使第三方應用開發者使用JNI完成了自己的C動態鏈接庫(so)開發,但是so如何和應用程序一起打包成apk并發布?這里面也存在技術障礙。比如程序更加復雜,兼容性難以保障,無法訪問Framework API,Debug難度更大等。開發者需要自行斟酌使用。
于是NDK就應運而生了。。。
NDK的發布,使“Java+C”的開發方式終于轉正,成為官方支持的開發方式。NDK將是Android平臺支持C開發的開端。
使用NDK開發的好處:
1.代碼的保護:由于apk的java層代碼很容易被反編譯,而C/C++庫反匯難度較大,所以可以起到保護核心代碼的作用。
2.可以方便地使用現存的開源庫。大部分現存的開源庫都是用C/C++代碼編寫的。
3.提高程序的執行效率。將要求高性能的應用邏輯使用C開發,從而提高應用程序的執行效率。
4.便于移植。用C/C++寫得庫可以方便在其他的嵌入式平臺上再次使用。
二、NDK開發環境搭建
1.創建普通的Android項目工程。
2.在項目的根目錄中創建jni目錄,該目錄用來存放編譯so文件所需要的源文件(C/C++ mk文件)
2. 創建Builder,Project->Properties->Builders->New->Program
2.1創建Builder
2.2 設置Main標簽
2.3 設置Refresh標簽
2.4 設置Build標簽,設置完成之后點擊OK即可設置完畢。
3.在工程中創建java文件(src目錄下),聲明native方法。
package com.example.day_34_ndk_helloworld;
public class NDKBridge {
public static native String helloWorld();
}
4.使用javah工具將聲明了native方法的class文件轉換成(.h)文件。javah工具在jdk的安裝目錄bin目錄下。需要時可以直接配置javah的環境變量。
添加完環境變量后,在DOS命令行進入工程文件夾中包的上一級目錄。
執行下列命令就可以生成頭文件:
javah -jni com.ex ample.day_34_ndk_helloworld.NDKBridge
注意:1.javah 使用的命令
2.javah 使用的命令的選項 (生成JNI樣式的頭文件)
3.com.example.day_34_ndk_helloworld.NDKBridge 本地方法源文件的包名和類名(我的電腦上是這樣的)。
5.執行javah命令后會在包的同一級目錄生成一個H文件。直接將其拷貝到工程文件中的jni目錄下。
6.根據H文件中的函數聲明,在jni目錄下創建C文件(注意文件名除了后綴不一樣,其他都是一樣的)。
#include "com_example_day_34_ndk_helloworld_NDKBridge.h"
#include
#include
#ifdef __cplusplus
extern "C"
{
#endif
JNIEXPORT jstring JNICALL Java_com_example_day_134_1ndk_1helloworld_NDKBridge_helloWorld (JNIEnv *env, jclass arg)
{
return (*env)->NewStringUTF(env, "hello world from jni");
}
#ifdef __cplusplus
}
#endif
7.在jni目錄創建Android.mk文件,制作編譯清單。NDK會根據Android.mk中的清單編譯成so文件。
#include "com_example_day_34_ndk_helloworld_NDKBridge.h"
#include
#include
#ifdef __cplusplus
extern "C"
{
#endif
JNIEXPORT jstring JNICALL Java_com_example_day_134_1ndk_1helloworld_NDKBridge_helloWorld (JNIEnv *env, jclass arg)
{
return (*env)->NewStringUTF(env, "hello world from jni");
}
#ifdef __cplusplus
}
#endif
8.在java層中,加載so文件,并調用native方法。
package com.example.day_34_ndk_helloworld;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button btn;
private TextView tv;
static{
System.loadLibrary("MyNDKDemo");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.bt_get_str_from_jni);
tv = (TextView) findViewById(R.id.tv);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
tv.setText(NDKBridge.helloWorld());
}
});
}
}
效果圖:
至此NDK的開發環境就已經搭建完畢,關于Android中NDK開發的一些細節我們會在后續的講解中跟大家介紹。