@linux1s1s
2017-08-22T19:21:47.000000Z
字数 6398
阅读 1492
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 {
@Override
protected 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 __cplusplus
extern "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 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "ndk.hello.com.hellondk"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
moduleName "hellondk"
abiFilters "armeabi", "armeabi-v7a", "x86"
stl "stlport_static"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
jniDebuggable true
}
}
}
run一下项目,即可生成so文件,如下所示:
我们将上面生成的so文件,直接拿到别的工程中使用即可,这里为了演示方法,直接放在当前项目中演示(项目中的jni目录可以直接 删除,直接用so文件即可)
运行项目,在启动进入首屏后会弹出Toast,上面显示Hello NDK 表示成功。(请读者自行测试)