NDK開發-簡介&環境搭建(Eclipse,Android Studio)

NDK簡介

NDK(Native Development Kit)是一套工具集,容許你在Android應用中嵌入c或c++。 java

使用NDK的好處主要有如下4點:android

  • 安全:因爲apk的java層代碼很容易被反編譯,而C/C++庫反匯難度較大。c++

  • 重用:能夠方便地使用現存的開源庫。大部分現存的開源庫都是用C/C++代碼編寫的。shell

  • 效率:將要求高性能的應用邏輯使用C開發,從而提升應用程序的執行效率。android-studio

  • 移植:用C/C++寫得庫能夠方便在其餘的嵌入式平臺上再次使用。安全


NDK關鍵詞

ndk-build:

這個shell構建腳本是NDK的核心。bash

  • 它決定須要去構建什麼
  • 生成二進制文件
  • 拷貝二進制文件到項目目錄

Native shared libraries:

本地共享庫,本地代碼通過編譯後生成的二進制文件.so``.dllmarkdown

Native static libraries:

本地靜態庫,用來鏈接其餘代碼庫架構

Java Native Interface (JNI):

Java平臺的重要特性,容許Java代碼和其餘本地語言進行交互,如c/c++app

Application Binary Interface (ABI)::

定義了二進制文件(尤爲是.so文件)如何運行在相應的系統平臺上。在Android系統上,每一種CPU架構對應一個ABI:
armeabi(默認),armeabi-v7a,x86,mips,arm64- v8a,mips64,x86_64。

Android.mk:

必備組件,在jni文件夾下,用來描述NDK構建系統。ndk-build腳本從該文件中讀取定義的模塊,名字和須要編譯的資源文件等。

Application.mk:

可選構建文件,和Android.mk同樣,放在jni目錄下,這個文件列舉和描述了你應用模塊所需的東西,如指定的ABIs編譯平臺,工具鏈等。


編寫NDK流程


Eclipse中NDK使用流程

  • 建立Android項目,建立java文件,並聲明本地方法

  • 編譯,獲得.class文件

  • 使用javah命令,生成jni目錄和.h頭文件

  • 在jni目錄下建立c/c++文件,引入頭文件,編寫本地方法的實現

  • 建立Android.mk,用來描述你要在jni目錄下生成的本地庫

  • 建立Application.mk(可選)來配置目標ABIs, toolchain, release/debug mode, STL等

  • 使用ndk-build腳本將c/c++文件編譯成本地庫.so

  • 打包,運行程序


Android Studio使用流程(Deprecated)

如今Anroid Studio已經支持全新的NDK使用,舊的方法已經被標爲廢棄。但新方法還在實驗階段,因此舊方法依舊重要!

建立java文件,並聲明本地方法

public class JNIHelper {
    public static native String getStringFromNative();
}

編譯,獲得.class文件

生成地址:YourApplication\app\build\intermediates\classes\debug

根據生成的class文件,利用javah 生成對應的 .h頭文件

打開termianl執行:
javah -d jni -classpath /Users/DeanGuo/TestNDK/app/build/intermediates/classes/debug com.dean.testndk. JNIHelper

成功後會生成一個jni目錄,目錄下會有一個com_dean_testndk_JNIHelper.h頭文件:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_dean_testndk_JNIHelper */

#ifndef _Included_com_dean_testndk_JNIHelper
#define _Included_com_dean_testndk_JNIHelper
#ifdef __cplusplus
extern "C" {
#endif
/* * Class: com_dean_testndk_JNIHelper * Method: getStringFromNative * Signature: ()Ljava/lang/String; */
JNIEXPORT jstring JNICALL Java_com_dean_testndk_JNIHelper_getStringFromNative
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

編寫c/c++文件,來實現頭文件中的方法

#include "com_dean_testndk_JNIHelper.h"

JNIEXPORT jstring JNICALL Java_com_dean_testndk_JNIHelper_getStringFromNative
  (JNIEnv * env, jobject jclass) {
    return (*env)->NewStringUTF(env, "return from native c");
  }

編譯生成.so文件

傳統方法是使用Android.mk,Application.mk進行配置,最後經過ndk-build腳原本生產.so本地庫。
使用Android Studio能夠將配置和執行腳本的工做都交給Gradle。

打開工程的build.gradle配置文件,在defaultConfig中添加ndk標籤用來配置.so的名字和abi架構,以下:

defaultConfig {
        applicationId "com.dean.testndk"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        ndk{
            moduleName "test"           //生成的so名字
            abiFilters "armeabi", "armeabi-v7a", "x86"  //指定abi體系結構下的so庫,不指定使用默認方案
            //  stl "stlport_shared"
            //  ldLibs "log", "z", "m"
            //  cFlags "-I/some/include/path"  
        }
    }

目前須要在grade.properties中添加android.useDeprecatedNdk=true(由於目前Android Studio推出了新的ndk支持,下一篇會講到)

生成好的so文件能夠在app/build/intermediates/ndk/debug/lib中看到。

編寫代碼,打包執行

本地庫已經生成,如今就經過代碼來加載使用了:

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("test");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("ndk_log : ", JNIHelper.getStringFromNative());
    }
}

執行後控制檯打印:I/ndk_log :: return from native c


總結:

相比Eclipse,使用Android Stuido更加直觀方便。「基本」能夠忽略Android.mk,Application.mk的編寫與配置。而新版的NDK支持將更增強大,將會在下一篇文章介紹。

相關文章
相關標籤/搜索