NDK
就是Android
的Java
代码去调用C/C++
代码NDK
的本质就是JNI
JNI
就是Java
调用C/C++
代码的一套编码规范
D:\tz\android\NDK笔记\android-ndk-r12\platforms\android-21\arch-arm\usr\include\jni.h 这个目录下有对应的 规范
NDK
技术基于JNI
cygwin
(Linux
环境)游戏引擎 cocos2d Unity3D
OpenGL 2d 3d图像引擎
OpenCV 图像识别 Face++(How old you ?)
本地安装 Daval
Shalls
1. 如果没有本地安装文件的话,就去www.cygwin.com
2. 下载完之后就 双击打开,选择Download Without Installing
3. 然后他就会下载所需要的东西了, 不需要全部安装,只要安装Daval
和Shalls
就可以了.
4. 然后再打开安装文件,选择从本地安装就可以了.
输入ndk-build
会提示:
-bash: ndk-build: 未找到命令
那跑到ndk
的目录下去看看有没有这个命令
cd .. --> cd .. --> cd cygdrive/ --> cd c --> cd develop/
--> Users/LZQ/Desktop/NDK_Learning/android-ndk-r12/build --> ndk-build
(还是提示未找到命令,这就奇怪了,按理说应该是有的,反正我是试了很久都不行)
解决方法: 找到cygwin
的安装目录C:\cygwin64\home\LZQ\.bash_profile
在文件尾部加上
export ANDROID_NDK_HOME=/cygdrive/c/Users/LZQ/Desktop/NDK_Learning/android-ndk-r12/build
export PATH=$ANDROID_NDK_HOME:$PATH
重新打开cygwin
, 输入ndk-build
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
/cygdrive/c/Users/LZQ/Desktop/NDK_Learning/android-ndk-r12/build/core/build-local.mk:151: *** Android NDK: Aborting 。 停止。
这样就表示配置OK
.
CDT
高亮显示C
关键字
C
是弱类型语言(不规范)
// 本地方法
/** * 返回一个字符串 * @return */
public native String getText();
#include <jni.h>
#include <string.h>
// jobject 就是当前调用本地方法的对象,就代表 MainActivity的对象
// 如果方法是static ,就要写成jclazz , 就代表当前的类
jstring Java_com_example_hellondk1_MainActivity_getText(JNIEnv* env,jobject obj){
// NewStringUTF 一个产生UTF编码格式的字符串函数
return (*env)->NewStringUTF(env,"hello ndk!"); // (**env).NewStringUTF()
}
建立一个jni
文件夹
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello // 库的名称
LOCAL_SRC_FILES := hello.c // 需要编译的文件
include $(BUILD_SHARED_LIBRARY)
编译C文件报错
1. Android NDK: Host 'awk' tool is outdated
. –> 直接删除android-ndk-r7\prebuilt\windows\bin\awk.exe文件
2. Android NDK: WARNING: APP_PLATFORM android-23 is larger than android:minSdkVersi
–>在jni目录下创建Application.mk, 然后添加APP_PLATFORM := android-8 ,8替换为你项目的最小版本号
3. /bin/sh: NUL: Permission denied
–>原因是编译的目录放在C盘,移动到其他盘编译即可
[arm64-v8a x86_64 mips64 armeabi-v7a armeabi x86 mips] Cygwin : Generating dependency file converter script
[arm64-v8a] Compile : hello <= hello.c
[arm64-v8a] SharedLibrary : libhello.so
[arm64-v8a] Install : libhello.so => libs/arm64-v8a/libhello.so
[x86_64] Compile : hello <= hello.c
[x86_64] SharedLibrary : libhello.so
[x86_64] Install : libhello.so => libs/x86_64/libhello.so
[mips64] Compile : hello <= hello.c
[mips64] SharedLibrary : libhello.so
[mips64] Install : libhello.so => libs/mips64/libhello.so
[armeabi-v7a] Compile thumb : hello <= hello.c
[armeabi-v7a] SharedLibrary : libhello.so
[armeabi-v7a] Install : libhello.so => libs/armeabi-v7a/libhello.so
[armeabi] Compile thumb : hello <= hello.c
[armeabi] SharedLibrary : libhello.so
[armeabi] Install : libhello.so => libs/armeabi/libhello.so
[x86] Compile : hello <= hello.c
[x86] SharedLibrary : libhello.so
[x86] Install : libhello.so => libs/x86/libhello.so
[mips] Compile : hello <= hello.c
[mips] SharedLibrary : libhello.so
[mips] Install : libhello.so => libs/mips/libhello.so
生成so动态库(libhello.so) ,会自动 加上 前面lib前缀 后面.so后缀
// 加载动态库
static{
System.loadLibrary("hello");
}
以上的使用时在cygwin
加上eclipse
的情况下进行调用的过程,cygwin
有好几个优点就是可以明确看到编译过程中的错误,有提示,其实在as接触的不深不太清楚,现在就在说说在as
上面是怎么实现的,毕竟现在的主流是as
1.首先是配置环境了,当然这个也很简单,其实就是下载ndk bundle,如下图
当你下载完成之后,你的local.properties
也会配置好。如下图
2.在AS中新建一个Project
。然后新建一个class
为JNIUtils
当然也可以直接写在MainActivity
中,
public class JNIUtils {
static {
System.loadLibrary("MyTestJNI"); //这个其实是对应4、的 build.gradle,后面你会看到
}
public native String getCLanguageString();
}
3.然后在MainActivity中
public class MainActivity extends AppCompatActivity {
public TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.tv);
JNIUtils jni = new JNIUtils();
tv.setText(jni.getCLanguageString());
}
}
4.然后在build.gradle中配置
defaultConfig {
......
ndk{
moduleName "MyTestJNI" //生成的so名字
}
}
5.然后在main
包下新建一个jni
目录,然后开始写C
,简单点,不做复杂逻辑,如下, 名字随便叫,我叫jnitest.c
#include <jni.h>
#include <string.h>
// jobject 就是当前调用本地方法的对象,就代表 MainActivity的对象
// 如果方法是static ,就要写成jclazz , 就代表当前的类
jstring Java_com_example_lzq_ndk1_JNIUtils_getCLanguageString(JNIEnv* env,jobject obj){
// NewStringUTF 一个产生UTF编码格式的字符串函数
return (*env)->NewStringUTF(env,"hello ndk fuck you!"); // (**env).NewStringUTF()
}
6.很简单就是buil
d工程,直接运行就可以了,当然你可能会遇到错误 《$USE_DEPRECATED_NDK=true》
,解决方法,直接在gradle.properties
中添加$USE_DEPRECATED_NDK=true
就OK
7.然后运行,在这之前,也许1中的getCLanguageString 会报错,不要紧是因为没有生成so文件。运行之后就不报错了.
so文件生成的路径在app/build/intermediates/ndk/