Android Studio下的配置及案例
1、设置ndk的路径
local.properties:
ndk.dir=D\:\\Android\\android-ndk-r10
2、创建本地native方法
package com.test.www.dnktest;
...
public class JniTest {
public native String getStringFromJNI();
}
3、生成.h头文件
a、Build –> Make Project, 生成.class文件
b、点开as的Terminal标签,输入一下命令进入class文件的根目录
D:\Android\STUDIO_APP\DNKTest>cd app\build\intermediates\classes\debug
c、执行javah命令, 生成.h文件
D:\Android\STUDIO_APP\DNKTest\app\build\intermediates\classes\debug> javah -jni com.test.www.dnktest.JniTest
d、输入dir命令,查看文件列表,此时会发现在根目录下多了一个.h文件。
D:\Android\STUDIO_APP\DNKTest\app\build\intermediates\classes\debug 的目录
2016/01/31 14:15 <DIR> .
2016/01/31 14:15 <DIR> ..
2016/01/31 13:59 <DIR> android
2016/01/31 13:59 <DIR> com
2016/01/31 14:15 530 com_test_www_dnktest_JniTest.h
1 个文件 530 字节
4 个目录 44,837,101,568 可用字节
打开com_test_www_dnktest_JniTest.h如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_www_dnktest_JniTest */
#ifndef _Included_com_test_www_dnktest_JniTest
#define _Included_com_test_www_dnktest_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_www_dnktest_JniTest
* Method: getStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_test_www_dnktest_JniTest_getStringFromJNI
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
4、编写C/C++代码
a、在工程的DNKTest\app\src\main目录下新建一个名字为jni的目录,然后将刚才的 .h拷贝一份过来重命名为JniTest.h。在jni目录下新建一个c文件,名称随意。如JniTest.c。编辑完成代码。
#include "JniTest.h"
JNIEXPORT jstring JNICALL Java_com_test_www_dnktest_JniTest_getStringFromJNI
(JNIEnv *env, jobject obj){
return (*env)->NewStringUTF(env, "This is my first jni test example");
}
5、配置build.gradle
在defaultConfig中加入ndk配置,如下
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.test.www.dnktest"
minSdkVersion 19
targetSdkVersion 23
versionCode 1
versionName "1.0"
ndk {
moduleName "jniTest" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库
}
}
...
}
注意gradle编译时有时会提示需要在gradle.properties配置android.useDeprecatedNdk=true,加上即可
6、静态初始化so库
package com.test.www.dnktest;
...
public class JniTest {
static {
System.loadLibrary("jniTest");
}
public native String getStringFromJNI();
}
7、调用native方法
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv_textview);
JniTest jniTest = new JniTest();
String str = jniTest.getStringFromJNI();
tv.setText(str);
}
}
一切准备就绪了,编译运行,发现还是回报莫名其妙的ndk错误,在网上找了一些资料说这是NDK在Windows下一个bug,当编译单一c/c++文件时as会出错,解决办法就是再添加一个空的.c文件就行了。
再次编译运行,结果出来了:
Eclipse下的配置及案例
1、配置ndk
2、新建一个Android工程NDKTest,在工程上右键点击Android Tools->Add Native Support:
点击完成后发现:
eclipse自动帮我们创建好了目录和Android.mk。
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jniTest
LOCAL_SRC_FILES := jniTest.cpp
include $(BUILD_SHARED_LIBRARY)
3、类似上面Android studio的2、3、4步,生成.h文件,并编写.c代码
a、进入NDKTest工程classes目录,执行javah -jni * 生成.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_ndktest_JniTest */
#ifndef _Included_com_example_ndktest_JniTest
#define _Included_com_example_ndktest_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_ndktest_JniTest
* Method: getStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_ndktest_JniTest_getStringFromJNI
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
b、将.h头文件拷贝一份到jni目录下,并编写完成c代码。Eclipse有个好处就是编写jni可以代码提示。
// 记得要引入jniTest.h头文件
#include <jniTest.h>
JNIEXPORT jstring JNICALL Java_com_example_ndktest_JniTest_getStringFromJNI
(JNIEnv *env, jobject obj) {
env->NewStringUTF("this is my first eclipse jni example");
}
4、静态加载so库
注意这里的Library库名和Android.mk文件中配置的LOCAL_MODULE的名字要一致。
package com.example.ndktest;
public class JniTest {
static {
System.loadLibrary("jniTest");
}
public native String getStringFromJNI();
}
5、调用native方法
package com.example.ndktest;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv_textview);
JniTest jniTest = new JniTest();
String str = jniTest.getStringFromJNI();
tv.setText(str);
}
}
6、编译NDK
工程右键,选择Properties->C/C++,去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd
这里的NDKROOT是在Environment中配置的
注意,默认情况下,只会编译生成armeabi类型的so库,要想生成armeabi-v7a类型的库,需要加Application.mk配置文件:
运行结果: