https://developer.android.google.cn/ndk/downloads/
选择 x64 的NDK软件:
https://dl.google.com/android/repository/android-ndk-r20-windows-x86_64.zip
https://developer.android.google.cn/studio/
选择 x64 的Android Studio
https://dl.google.com/dl/android/studio/install/3.5.0.21/android-studio-ide-191.5791312-windows.exe
下载好后,添加环境变量,添加好后记得重启下 Android Studio。
https://cmake.org/download/
如果报错说 cmake 找不到: Could not find method cmake() for arguments,就是cmake 编译工具没有找到。
参考 : https://blog.csdn.net/xiaoyu_93/article/details/53082088
在 JNI_Daemon2\app\src\main\java\com\android\jni_daemon\ 目录下新建文件 JNI.java
@ \JNI_Daemon2\app\src\main\java\com\android\jni_daemon\JNI.java
package com.android.jni_daemon;
public class JNI {
{
//加载动态链接库
System.loadLibrary("Hello");
}
//定义Native 方法, Java 调用对应的 C 代码
public native String sayHello();
}
在 \JNI_Daemon2\app\src\main\ 目录下新建 jni 目录:
@ \JNI_Daemon2\app\src\main\jni\Hello.c
// Created by Administrator on 2019/9/14.
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
// Java_全类名_方法名
// JNIEnv * env: 里面有很多方法
// jObject jobj: 谁调用了这个方法就是谁的实例
// 当前就是 JNI.this
jstring Java_com_android_jni_1daemon_JNI_sayHello(JNIEnv* env, jobject jobj){
//jstring (*NewStringUTF)(JNIEnv* , const char *)
char * text = "I am from C";
return (*env)->NewStringUTF(env, text);
}
由于最新的 Android Studio 中已经不支持 NDK 了,所以我们使用 cmake 来编译so库文件
修改:\JNI_Daemon2\app\build.gradle
@ \JNI_Daemon2\app\build.gradle
android {
compileSdkVersion 28
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.android.jni_daemon"
minSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//使用cmake 工具 ++++
externalNativeBuild {
cmake {
cppFlags ""
abiFilters "arm64-v8a", "armeabi-v7a", "x86" ,"x86_64" //CPU 的类型
}
}
//使用cmake 工具 ----
}
//使用cmake 工具 ++++
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
//使用cmake 工具 ----
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
增加cmake 所要编绎的文件: \JNI_Daemon2\app\CMakeLists.txt
@ \JNI_Daemon2\app\CMakeLists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
#CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
# 设置so文件名称. libHelo.so
Hello
# Sets the library as a shared library.
SHARED
# 设置这个so文件为共享.
# Provides a relative path to your source file(s).
# 设置这个so文件为共享.
src/main/jni/Hello.c)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
# 制定目标库.
Hello
# Links the target library to the log library
# included in the NDK.
${log-lib} )
打开文件: \JNI_Daemon2\app\src\main\java\com\android\jni_daemon\MainActivity.java
@ \JNI_Daemon2\app\src\main\java\com\android\jni_daemon\MainActivity.java
package com.android.jni_daemon;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String result = new JNI().sayHello(); // new 一个 JNI 对象,并调用其 sayHello() 方法
System.out.println("result=" + result); // 打印 log ,将 c 中返回的数据返回来
}
}
09-14 15:25:19.659 8546 8546 I zygote :
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener"
on path: DexPathList[[zip file "/data/app/com.android.jni_daemon-kihiF3BkpbXLfp0oUvewLQ==/base.apk"],
nativeLibraryDirectories=[/data/app/com.android.jni_daemon-kihiF3BkpbXLfp0oUvewLQ==/lib/x86,
/data/app/com.android.jni_daemon-kihiF3BkpbXLfp0oUvewLQ==/base.apk!/lib/x86, /system/lib, /vendor/lib]]
原因为 虚拟机的版本号 和 代码换版本号不一致,确保版本一致即可。
前面我们已经实现好了流程,在前面的基础上,我们再来新增一个方法:
sayGoodBye
代码修改如下:
@ \JNI_Daemon2\app\src\main\jni\Hello.c
在其中新增sayGoodBye的C语言实现代三:
jstring Java_com_android_jni_1daemon_JNI_sayGoodBye(JNIEnv * env, jobject jobj){
char *text = "From C 拜拜!";
return (*env)->NewStringUTF(env,text);
}
@ \JNI_Daemon2\app\src\main\java\com\android\jni_daemon\JNI.java
package com.android.jni_daemon;
public class JNI {
{
//加载动态链接库
System.loadLibrary("Hello");
}
//定义Native 方法, Java 调用对应的 C 代码
public native String sayHello();
public native String sayGoodBye();
}
@ \JNI_Daemon2\app\src\main\java\com\android\jni_daemon\MainActivity.java
package com.android.jni_daemon;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ViewDebug;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String result = new JNI().sayHello();
System.out.println("sayHello return result = " + result);
String i = new JNI().sayGoodBye();
System.out.println("sayGoodBye return result = " + i);
}
}
编译运行结果为:
2019-09-15 09:57:02.651 6743-6743/com.android.jni_daemon I/System.out: sayHello return result = I am from C
2019-09-15 09:57:02.651 6743-6743/com.android.jni_daemon I/System.out: sayGoodBye return result = From C 拜拜!