前言
本文只涉及在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 FileClassModuleFileDir$\src\main\java
配置完以后 就可以看到
创建工程
正常方式创建一个android 工程。创建完成后在在main下新建一个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