@linux1s1s
2017-08-22T11:21:47.000000Z
字数 6398
阅读 1811
AndroidNDK 2017-08
本文从开发NDK的基本流程出发,一步一步完整的记录整个NDK开发过程。
进入工程配置NDK路径

配置gradle.properties
新增一行:
android.useDeprecatedNdk=true

使用Android Studio新建项目HelloNDK,在MainActivity中简单添加几行代码如下:
package ndk.hello.com.hellondk;import android.app.Activity;import android.os.Bundle;import android.widget.Toast;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Toast.makeText(this, test(), Toast.LENGTH_SHORT).show();}public static String test() {String result = null;try {result = jni_test();} catch (UnsatisfiedLinkError error) {error.printStackTrace();}return result;}private static native String jni_test();}
使用javah自动生成头文件,打开终端,进入main目录,如下:

因为javah需要生成的class文件,所以需要run一下项目,然后我们可以在一下目录中找到对应的MainActivity.class文件。

MainActivity.class文件的绝对路径:
H:\workspace\Native\HelloNDK\app\build\intermediates\classes\debug
类完整包名:
ndk.hello.com.hellondk.MainActivity
SDK绝对路径:
H:\Android\sdk\platforms\android-25\android.jar
javah -d jni -classpath H:\Android\sdk\platforms\android-25\android.jar;H:\workspace\Native\HelloNDK\app\build\intermediates\classes\debug ndk.hello.com.hellondk.MainActivity
如图所示:

简要说明:
-d后面的jni表示生成头文件的具体目录名称
-classpath后面接两个内容,用;号隔开。
- 分号第一部分表示使用的
android.jar绝对路径,如果不加该部分,则会出现某些android中的类找不到,比如android.content.Context等- 分号第二部分表示需要生成头文件的具体类,这里要指定该类所在的绝对路径,注意,决定路径+全包名,中间有空格
执行javah以后,会在如图所示目录中自动生成头文件,该文件不需要修改。

打开文件看看自动生成的头文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class ndk_hello_com_hellondk_MainActivity */#ifndef _Included_ndk_hello_com_hellondk_MainActivity#define _Included_ndk_hello_com_hellondk_MainActivity#ifdef __cplusplusextern "C" {#endif#undef ndk_hello_com_hellondk_MainActivity_BIND_ABOVE_CLIENT#define ndk_hello_com_hellondk_MainActivity_BIND_ABOVE_CLIENT 8L#undef ndk_hello_com_hellondk_MainActivity_BIND_ADJUST_WITH_ACTIVITY#define ndk_hello_com_hellondk_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L#undef ndk_hello_com_hellondk_MainActivity_BIND_ALLOW_OOM_MANAGEMENT#define ndk_hello_com_hellondk_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L#undef ndk_hello_com_hellondk_MainActivity_BIND_AUTO_CREATE#define ndk_hello_com_hellondk_MainActivity_BIND_AUTO_CREATE 1L#undef ndk_hello_com_hellondk_MainActivity_BIND_DEBUG_UNBIND#define ndk_hello_com_hellondk_MainActivity_BIND_DEBUG_UNBIND 2L#undef ndk_hello_com_hellondk_MainActivity_BIND_EXTERNAL_SERVICE#define ndk_hello_com_hellondk_MainActivity_BIND_EXTERNAL_SERVICE -2147483648L#undef ndk_hello_com_hellondk_MainActivity_BIND_IMPORTANT#define ndk_hello_com_hellondk_MainActivity_BIND_IMPORTANT 64L#undef ndk_hello_com_hellondk_MainActivity_BIND_NOT_FOREGROUND#define ndk_hello_com_hellondk_MainActivity_BIND_NOT_FOREGROUND 4L#undef ndk_hello_com_hellondk_MainActivity_BIND_WAIVE_PRIORITY#define ndk_hello_com_hellondk_MainActivity_BIND_WAIVE_PRIORITY 32L#undef ndk_hello_com_hellondk_MainActivity_CONTEXT_IGNORE_SECURITY#define ndk_hello_com_hellondk_MainActivity_CONTEXT_IGNORE_SECURITY 2L#undef ndk_hello_com_hellondk_MainActivity_CONTEXT_INCLUDE_CODE#define ndk_hello_com_hellondk_MainActivity_CONTEXT_INCLUDE_CODE 1L#undef ndk_hello_com_hellondk_MainActivity_CONTEXT_RESTRICTED#define ndk_hello_com_hellondk_MainActivity_CONTEXT_RESTRICTED 4L#undef ndk_hello_com_hellondk_MainActivity_MODE_APPEND#define ndk_hello_com_hellondk_MainActivity_MODE_APPEND 32768L#undef ndk_hello_com_hellondk_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING#define ndk_hello_com_hellondk_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L#undef ndk_hello_com_hellondk_MainActivity_MODE_MULTI_PROCESS#define ndk_hello_com_hellondk_MainActivity_MODE_MULTI_PROCESS 4L#undef ndk_hello_com_hellondk_MainActivity_MODE_NO_LOCALIZED_COLLATORS#define ndk_hello_com_hellondk_MainActivity_MODE_NO_LOCALIZED_COLLATORS 16L#undef ndk_hello_com_hellondk_MainActivity_MODE_PRIVATE#define ndk_hello_com_hellondk_MainActivity_MODE_PRIVATE 0L#undef ndk_hello_com_hellondk_MainActivity_MODE_WORLD_READABLE#define ndk_hello_com_hellondk_MainActivity_MODE_WORLD_READABLE 1L#undef ndk_hello_com_hellondk_MainActivity_MODE_WORLD_WRITEABLE#define ndk_hello_com_hellondk_MainActivity_MODE_WORLD_WRITEABLE 2L#undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DIALER#define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DIALER 1L#undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DISABLE#define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DISABLE 0L#undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL#define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L#undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL#define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L#undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SHORTCUT#define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SHORTCUT 2L#undef ndk_hello_com_hellondk_MainActivity_RESULT_CANCELED#define ndk_hello_com_hellondk_MainActivity_RESULT_CANCELED 0L#undef ndk_hello_com_hellondk_MainActivity_RESULT_FIRST_USER#define ndk_hello_com_hellondk_MainActivity_RESULT_FIRST_USER 1L#undef ndk_hello_com_hellondk_MainActivity_RESULT_OK#define ndk_hello_com_hellondk_MainActivity_RESULT_OK -1L/** Class: ndk_hello_com_hellondk_MainActivity* Method: jni_test* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_ndk_hello_com_hellondk_MainActivity_jni_1test(JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif
接下来我们手动写一个C文件,实现头文件中声明的方法
C/C++文件对照头文件的方法,增加简单实现即可。
#include "ndk_hello_com_hellondk_MainActivity.h"/** Class: ndk_hello_com_hellondk_MainActivity* Method: jni_test* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_ndk_hello_com_hellondk_MainActivity_jni_1test(JNIEnv *env, jclass c){return (*env)->NewStringUTF(env, "Hello NDK");}
上面完成以后,如果 没有 在gradle.properties中配置
新增一行:
android.useDeprecatedNdk=true
直接运行项目会报如下错误

build.gradle文件生成so新增配置生成so文件

android {compileSdkVersion 25buildToolsVersion "25.0.2"defaultConfig {applicationId "ndk.hello.com.hellondk"minSdkVersion 15targetSdkVersion 25versionCode 1versionName "1.0"testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"ndk {moduleName "hellondk"abiFilters "armeabi", "armeabi-v7a", "x86"stl "stlport_static"}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}debug {jniDebuggable true}}}
run一下项目,即可生成so文件,如下所示:

我们将上面生成的so文件,直接拿到别的工程中使用即可,这里为了演示方法,直接放在当前项目中演示(项目中的jni目录可以直接 删除,直接用so文件即可)

运行项目,在启动进入首屏后会弹出Toast,上面显示Hello NDK 表示成功。(请读者自行测试)
