NDK的开发流程
我们这些做Android应用层的,大部分时间都是在使用Java编程,很少使用C/C++编程,对于NDK也了解的比较少,那么,现在就让我们来简单的了解一下NDK的开发流程吧。
一、下载并配置NDK
1 . 下载NDK,地址:http://developer.android.com/tools/sdk/ndk/index.html
2 . 解压,解压得到的文件夹可以移动到其他文件夹,接下来把它的路径加入到环境变量里就行了
- 使用ndk-build命令,检查下配置是否成功
二、在AndroidStudio配置项目的NDK环境
-
打开file->project structure,选择你所下载的ndk环境路径
- 在项目的gradle.properties文件末尾添加
android.useDeprecatedNdk=true
- 在module的build.gradle ->defaultConfig内添加如下代码
ndk {
moduleName "NdkJniDemo" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库
}
二、NDK的开发流程
1.声明一个native方法,编译项目
package com.soubu.jnidemo;
/**
* 作者:余天然 on 2017/4/19 下午4:31
*/
public class JniUtils {
public static native String getStringFormC();
}
2.查看是否生成了build/intermediates/classes/debug,有则打开Terminal,切换到此目录下,然后使用javah命令生成h文件
javah -jni com.wobiancao.ndkjnidemo.ndk.JniUtils
3.在main目录下新建jni目录,将生成的h文件复制到改此目录下,同时新建c文件或cpp文件实现h文件中的方法
复制的com_soubu_jnidemo_JniUtils.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_soubu_jnidemo_JniUtils */
#ifndef _Included_com_soubu_jnidemo_JniUtils
#define _Included_com_soubu_jnidemo_JniUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_soubu_jnidemo_JniUtils
* Method: getStringFormC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_soubu_jnidemo_JniUtils_getStringFormC
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
新建的ndkutils.c,需要自己实现具体的逻辑
//
// Created by 余天然 on 2017/4/19.
//
#include "com_soubu_jnidemo_JniUtils.h"
JNIEXPORT jstring JNICALL Java_com_soubu_jnidemo_JniUtils_getStringFormC(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, "这里是来自c的string");
}
4.编译项目,查看在build/intermediates/ndk目录下是否生成了so文件
6.在最初声明native类的地方,加载native库
package com.soubu.jnidemo;
/**
* 作者:余天然 on 2017/4/19 下午4:31
*/
public class JniUtils {
public static native String getStringFormC();
static {
System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
}
}
5.现在,我们就可以在Java中调用native方法了
package com.soubu.jnidemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv_msg);
tv.setText(JniUtils.getStringFormC());
}
}
三、JniLibs的引用流程
上面呢,我们还是直接引用的c文件,在调试好了c层的逻辑后,我们会将c文件打包成so文件。
一般情况下呢,我们是将so文件而不是c文件交给第三方使用。
这里呢,我新建一个jniLibs的module,通过so文件的方式,依赖刚才开发好的c层代码。
1.在main目录下新建jniLibs目录,将刚才编译时生成的so文件复制到该目录下
2.加载so文件,需要注意的是,加载so文件的包名、类名、方法名,一定要和之前开发时的保持一致,否则会报错:UnsatisfiedLinkError
这里,我新建的module的包名其实是jnilibs,而开发时的jnidemo,一定要注意保证依赖时和开发时的路径一致!
新建jnidemo包,保证路径一致。
package com.soubu.jnidemo;
/**
* 作者:余天然 on 2017/4/19 下午4:31
*/
public class JniUtils {
static {
System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
}
public static native String getStringFormC();
}
在jniLibs的包中,调用JniUtils的native方法
package com.soubu.jnilibs;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import com.soubu.jnidemo.JniUtils;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv_msg);
tv.setText(JniUtils.getStringFormC());
}
}
最后,奉上源码:GitHub-JNIDemo
其它
- 如何配置环境变量?
1 . 打开terminal(终端)
2 . 输入 vim ~/.bash_profile,回车
3 . 按英文键 i 进入编辑模式,在里面添加 export PATH=${PATH}:NDK路径
4 . 按esc键退出编辑模式,输入:wq(冒号键+英文键w+英文键q),回车。(:wq 表示 保存并退出)
5 . 输入source ~/.bash_profile,回车,以使前面的更改生效。