如需转载请标明出处 Average
http://blog.csdn.net/Average77/article/details/72961677
下载NDK
下载r7以上版本的Ndk,不需要安装Cygwin,已经内置模拟Linux环境,因此我们只需要下载一个NDK,就可以正常工作了.
然后只需要等待Ndk下载完成,下载到最后的时候多等一会,解压缩的时候有些慢,会显示Unzipping…
下载完成以后,记得打开Project Structure看一看有没有配置Ndk路径
按照如图所示打开后,显示如下界面,按照图示操作
配置环境变量
- 打开环境变量 (此电脑–>属性–>高级系统设置–>环境变量)
- 在下半部分的系统变量中找到path
- 在最后添加上ndk的路径,和刚才在as中配置的路径相同(如果adb的路径还没有配置,记得也配置一下)
或者按照这种模式,添加一个变量,在path中引用
- 打开环境变量 (此电脑–>属性–>高级系统设置–>环境变量)
- 在下半部分的系统变量中找到path
- 新建一个NDK_Root,下面写路径
- 在path最后写%NDK_ROOT%
注意:不要忘记分号,是英文的符号
如图所示:
然后在dos里测试一下
按windows+r,输入cmd进入窗口,输入ndk-build,显示如下界面即为成功,因为没有进入到工程中,所以提示不能找到应用工程文件夹,不影响后续使用
简单使用
- 新建一个工程,按照和以前创建工程相同的方式创建
- 新建一个jni文件夹
- 在jni下建这4个文件
- Android.mk中写如下内容,include之前放一个空行,否则可能会编译出错
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := str
LOCAL_SRC_FILES := str.cinclude $(BUILD_SHARED_LIBRARY)
其中 LOCAL_MODULE 和 LOCAL_SRC_FILES 的值是要自己改的, LOCAL_MODULE是自己建的so库的名字,LOCAL_SRC_FILES 是上图所示jni下建的c++的源文件的名字
* Application.mk中写如下内容
配置全部的cpu类型,写法如下
APP_ABI := all
配置部分cpu类型,写法如下,需要什么类型就写什么类型的,中间用空格隔开
APP_ABI := armeabi x86
- str.c是c++的Source File,此处以app中的key作为案例,实际开发中应该做一下加密,此处仅作为演示,代码如下
#include <stdio.h>
#include "str.h"
#include <jni.h>
//注意包名以及类名之间相连处,把点变成下划线
JNIEXPORT jstring JNICALL Java_com_zyy_ndktest_MainActivity_getKey
(JNIEnv *env, jclass obj,jint type)
//JNIEnv :代表java环境,通过这个环境可以调用java里的代码
//jint 就是 java 中的int类型
{
switch (type) {
case 1:
//返回的字符串
return (*env)->NewStringUTF(env, "12345678");
break;
case 2:
return (*env)->NewStringUTF(env, "00009998878");
break;
default:
return (*env)->NewStringUTF(env, "444566778");
break;
}
}
- str.h中代码如下,创建就能自动生成
#ifndef NDKTEST_STR_H
#define NDKTEST_STR_H
#endif //NDKTEST_STR_H
- 打开dos,使用cd命令依次进入jni目录下,输入ndk-build,出现以下情况就是成功
- 把当前生成的这个libs里的东西,copy到上面的libs里,并把这里的libs,obj,jni都删除掉
- 在gradle中添加一串代码,用于生成jniLibs
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
重新构建一下,切换成Android模式,能看到生成了一个jniLibs
在类中调用c/c++的方法,把方法设为native的
这个so库会在第一次使用MainActivity这个类的时候加载。(static代码块声明的代码会先于onCreate方法执行)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, getKey(1), Toast.LENGTH_SHORT).show();
}
static {
System.loadLibrary("str");
}
public native String getKey(int type);
}
这时候运行一下工程,因为传入的值为1,所以能够吐司出str.c中getkey方法下的case 1: 吐司出12345678;
注意:如果遇到很奇怪的bug,就clean一下,还有jni下的文件由于是复制过来的,编码可能会有问题,如果你看着代码没有任何问题,却偏偏报错,clean也没有用,就手敲一下
可怕的UnsatisfiedLinkError错误
运行有时候会看到这样一个错误反复出现,具体解决办法看这里