本博客只是搭建了jni编程所需要的环境,通过一个简单的例子展示了其流程,用于以后参考查阅,不涉及jni的复杂内容。
一、环境搭建
除了Android开发所需要的环境外还需要cmake、ndk。
1、现在sdk manager中安装cmake、ndk
2、在local.propertites中设置ndk路径ndk.dir=E\:\\DevTools\\Sdk\\ndk\\24.0.8215888
,其路径会自动同步到project structure中。
二、jni示例
1、在MainActivity同级目录下创建Java类
package com.example.myapplication1;
public class JniHello{
static {
System.loadLibrary("JniHello");
}
public static native String welcomeJniStudy();
}
2、创建javah和ndk通用工具
首先选择File->Settings->Tools->External Tools创建javah工具,其具体设置如下:
Program: E:\DevTools\Java\jdk1.8.0_162\bin\javah.exe
Arguments: -classpath . -jni -d E:\TestProjects\MyApplication1\app\src\main\jni $FileClass$
Working directory: E:\TestProjects\MyApplication1\app\src\main\java
然后创建ndk-build工具,具体设置如下:
Program:E:\DevTools\Sdk\ndk\24.0.8215888\build\ndk-build.cmd //安装ndk的路径
Arguments:
Working directory:E:\TestProjects\MyApplication1\app\src\main
3、通过通用工具javah生成C头文件
就会在jni文件夹下生成相应的c头文件
4、创建Android.mk和Application.mk
//Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS +=-lm
LOCAL_MODULE := JniHello
LOCAL_SRC_FILES =: JniHello.cpp # 实现c代码文件的名字
include $(BUILD_SHARED_LIBRARY)
//Application.mk
APP_MODULES := JniHello
APP_ABI := all
5、实现c头文件中的方法,文件命名为JniHello.cpp
文件内容为:
#include "com_example_myapplication1_JniHello.h"
JNIEXPORT jstring JNICALL Java_com_example_myapplication1_JniHello_welcomeJniStudy(JNIEnv *env, jclass jclass){
return env->NewStringUTF("welcome to study jni");
}
6、修改app下的build.gradle,在defaultConfig中添加如下内容
ndk{
moduleName "JniHello"
//abiFilters \"armeabi-v7a", "x86" //输出指定abi下的so库
}
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir "src/main/libs"
}
7、生成so文件
就会在libs文件夹下生成相应的so文件
8、在MainActivity.java中调用测试
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String str=new JniHello().welcomeJniStudy();
System.out.println("============="+str);
}
}
输出结果
05/06 18:33:35: Launching 'app' on Nexus 5 API 29.
Install successfully finished in 979 ms.
$ adb shell am start -n "com.example.myapplication1/com.example.myapplication1.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 16900 on device 'Nexus_5_API_29 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
D/libEGL: Emulator has host GPU support, qemu.gles is set to 1.
W/libc: Unable to set property "qemu.gles" to "1": connection failed; errno=13 (Permission denied)
W/RenderThread: type=1400 audit(0.0:35): avc: denied { write } for name="property_service" dev="tmpfs" ino=7421 scontext=u:r:untrusted_app:s0:c134,c256,c512,c768 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=0
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
W/.myapplication: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
I/System.out: =============welcome to study jni
D/HostConnection: HostConnection::get() New Host Connection established 0xd89bac30, tid 16931
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2