右键moudle------>Link C++ Project with Gradle —>ndk-build 选择 Android.mk文件可以实现自动的c文件编译成.so文件
在app build.gradle里面会生成这样一个文件
externalNativeBuild {
ndkBuild {
path file('../jni/Android.mk')
}
}
所以项目中也可以直接配置Android.mk进行ndk的编译这样可以 不用手动的在jni目录下敲ndk-build.cmd命令,(AS项目中不会产生libs包和obj包):
此时也不用再app下添加libs包:
externalNativeBuild {
ndkBuild {
// 要按照JNI规范操作
path file('../jni/Android.mk')
}
}
手动编译时的包是这样的:
配合AS Gradle 用ndk-build编译时包的结构是这样:
很简洁吧:
-----------------------------------------------------------------------------------------------------------------------------------
ndk-build 文件是 Android NDK r4 中引入的一个 shell 脚本。其用途是调用正确的 NDK 构建脚本。其实最终还是会去调用 NDK 自己的编译工具。
那 CMake 又是什么呢。脱离 Android 开发来看,c/c++ 的编译文件在不同平台是不一样的。Unix 下会使用 makefile 文件编译,Windows 下会使用 project 文件编译。而 CMake 则是一个跨平台的编译工具,它并不会直接编译出对象,而是根据自定义的语言规则(CMakeLists.txt)生成 对应 makefile 或 project 文件,然后再调用底层的编译。
总结: CMake 则是一个跨平台的编译工具
在Android Studio 2.2 之后,工具中增加了 CMake 的支持,你可以这么认为,在 Android Studio 2.2 之后你有2种选择来编译你写的 c/c++ 代码。一个是 ndk-build + Android.mk + Application.mk 组合,另一个是 CMake + CMakeLists.txt 组合。
这2个组合与Android代码和c/c++代码无关,只是不同的构建脚本和构建命令
2、ABI 是什么
ABI(Application binary interface)应用程序二进制接口。不同的CPU 与指令集的每种组合都有定义的 ABI (应用程序二进制接口),一段程序只有遵循这个接口规范才能在该 CPU 上运行,所以同样的程序代码为了兼容多个不同的CPU,需要为不同的 ABI 构建不同的库文件。当然对于CPU来说,不同的架构并不意味着一定互不兼容。
armeabi设备只兼容armeabi;
armeabi-v7a设备兼容armeabi-v7a、armeabi
arm64-v8a设备兼容arm64-v8a、armeabi-v7a、armeabi;
X86设备兼容X86、armeabi; // 常用的模拟器是x86
X86_64设备兼容X86_64、X86、armeabi;
mips64设备兼容mips64、mips;
3.JNI中 java调C时将java中的字符串转成C字符串的工具:
/**
Java 字符串转换成c的字符串
*/
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");
jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
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_test_com_zh_testicbclient_JniUtils_JniUtil_encodeStr
(JNIEnv * env, jobject obj, jstring str,jint len){
// c语言的的字符串和Java语言的字符串不通用
char* cstr = Jstring2CStr(env,str);
// abc -- bcd;
int i;
for(i=0;i<len;i++){
*(cstr+i)+=1;
}
return (*env)->NewStringUTF(env,cstr);
};