Android Studio 之ndk

前言

本文只涉及在Android Studio(以下簡稱as)中ndk的使用,基本不涉及原理性講解。

ndk&cmake

在最新的as中 使用ndk,都是通過配置cmake腳本實現的。

CMake是個開源的跨平臺自動化建構系統,它用配置文件控制建構過程(build process)的方式和Unix的Make相似,只是CMake的配置文件取名爲CmakeLists.txt——[bing網典]

cmake最大的特點就是跨平臺,可以根據不同平臺生成相應的腳本,在linux下生成 .sh文件,windows下就就可以生成.bat文件,當然 我們編譯so庫也可以生成makefile文件,但是cmake直接使用的腳本文件是需要自己編寫的。就生成as中生成so來說,大致流程就是cmake通過cmakelist腳本生成makefile腳本,ndk使用make工具執行.mk腳本,即使用相應的編譯或其他工具執行真正的操作。
對於較小型 且無跨平臺需求的項目 ,直接通過.mk文件編譯就可以了。

準備

在使用ndk開發前,需要做些前期準備
ndk配置
在project structure中
這裏寫圖片描述
若尚未下載,點擊Download下載即可.
javah命令配置
javah就是將使用native方法的類生成c或c++的頭文件,
當然,如果對jni的語法已經非常熟悉可以忽略此操作.
在as的setting中 進入External Tools:
這裏寫圖片描述
可以直接複製
JDKPath /bin/javah
-classpath . -jni -o ModuleFileDir \src\main\jni$Prompt FileClass ModuleFileDir$\src\main\java
配置完以後 就可以看到

創建工程

正常方式創建一個android 工程。創建完成後在在main下新建一個jni文件夾。
創建jni文件夾

創建我們的加載動態庫的類,並添加調用本地方法的api。

public class NativeTest {

    public native String getNativeText(String name);
    public native int getNativeNum(int num1,int num2);
    static {
        System.loadLibrary("ndk_test");
    }

}

通過javah動態生成.h文件,執行javah命令後,會在在jni文件夾裏創建一個.h文件,文件名 可以自定義.
這裏寫圖片描述
編寫.c或 .cpp文件,導入.h文件,並實現頭文件中聲明的方法.

編寫makefile文件
這裏寫圖片描述

下面就是配置gradle文件了,直接貼gradle文件

//
// Created by gqs on 2016/10/26.
//
#include <jni.h>
#include <string.h>
#include "jni_test.h"


/**

* 工具方法

* 作用: 把java中的string 轉化成一個c語言中的char數組

* 接受的參數 envjni環境的指針

* jstr 代表的是要被轉化的java的string 字符串

* 返回值 : 一個c語言中的char數組的首地址 (char 字符串)

*/

char* jstring2CStr(JNIEnv* env, jstring jstr)

{
    char* rtn = NULL;
    jclass clsstring = (*env)->FindClass(env,"java/lang/String");

    jstring strencode = (*env)->NewStringUTF(env,"GB2312");

    jmethodID mid =

            (*env)->GetMethodID(env,clsstring,"getBytes","(Ljava/lang/String;)[B");

// String.getByte("GB2312");

    jbyteArray barr=

            (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);

    jsize alen = (*env)->GetArrayLength(env,barr);

    jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);

    if(alen > 0)

    {

        rtn = (char*)malloc(alen+1); //"\0"

        memcpy(rtn,ba,alen);

        rtn[alen]=0;

    }

    (*env)->ReleaseByteArrayElements(env,barr,ba,0); //

    return rtn;

}

JNIEXPORT jstring JNICALL Java_com_gqs_ndkdemo_NativeTest_getNativeText
  (JNIEnv *env, jobject obj, jstring name)
  {
      char  str[50];
      char *hello = "Hello ";
      strcpy (str,hello);
      char* cstr = jstring2CStr(env,name);
      strcat(str,cstr);//拼接兩個字符串  
      return (*env)->NewStringUTF(env,str);
  }

/*
 * Class:     com_gqs_ndkdemo_NativeTest
 * Method:    getNativeNum
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_gqs_ndkdemo_NativeTest_getNativeNum
  (JNIEnv *env, jobject obj, jint num1, jint num2)
  {

return num1+ num2;
  }
apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.1"
    defaultConfig {
        applicationId "com.gqs.ndkdemo"
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        ndk{
        //生成so庫的名稱 要和Android.mk文件指定的一直
            moduleName "jni_test"
            //生成支持不同cpu類型的動態庫
            abiFilters "armeabi","armeabi-v7a","x86"
        }
    }
    externalNativeBuild {
        ndkBuild {
        //配置makefile文件路徑
            path 'src/main/jni/Android.mk'
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    testCompile 'junit:junit:4.12'
}

OK ,下面就可以直接運行了,good luck!
代碼下載:http://download.csdn.net/detail/gqs519/9672544

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章