AndroidStudio 的 JNI 工程创建与调用

1.新建一个 Android 工程

写一个 JNI 工具类:JNITools.java

package com.example.jnitest;
public class JNITools {
public static native String getStringFromJNI();
}

2.Activity的xml文件里给布局 添加一个 id

<?xml version="1.0" encoding="utf-8"?> 
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MainActivity"> 
    <TextView 
        android:id="@+id/tv_show" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Hello World!" 
        app:layout_constraintBottom_toBottomOf="parent" 
        app:layout_constraintLeft_toLeftOf="parent" 
        app:layout_constraintRight_toRightOf="parent" 
        app:layout_constraintTop_toTopOf="parent" /> 
</androidx.constraintlayout.widget.ConstraintLayout>

3.在MainActivity调⽤写好的 JNI⽅法

package com.example.jnitest; 
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; 
import android.widget.TextView; 
public class MainActivity extends AppCompatActivity { 
    @Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        TextView tvShow = findViewById(R.id.tv_show); 
        tvShow.setText(JNITools.getStringFromJNI()); 
    } 
} 
此时因为没有 native实现,运行会报错: java.lang.UnsatisfiedLinkError: No implementation found for
2020-09-08 20:18:57.785 18756-18756/com.example.jnitest E/ AndroidRuntime: FATAL EXCEPTION: main 
    Process: com.example.jnitest, PID: 18756 
    java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.example.jnitest.JNITools.getStringFromJNI() (tried 
Java_com_example_jnitest_JNITools_getStringFromJNI and 
Java_com_example_jnitest_JNITools_getStringFromJNI__) 
        at com.example.jnitest.JNITools.getStringFromJNI(Native Method) 
        at com.example.jnitest.MainActivity.onCreate(MainActivity.java:16) 
        at android.app.Activity.performCreate(Activity.java:8085) 
        at android.app.Activity.performCreate(Activity.java:8073) 
        at 
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320)         at 
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3868)         at 
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4074) 

4.Native实现——编译 JNI⽂件

MakeProject或者 RebuildProject之后,到 app下的 build⽂件夹找到 class所在⽬ 录;
进⼊到包名的上级⽬录,运⾏:javah -jni com.example.jnitest.JNITools
⽣成⼀个 com_example_jnitest_JNITools.h⽂件,com.example.jnitest.JNITools是 你 JNI⼯具类所在引⽤,可根据实际情况修改。

com_example_jnitest_JNITools.h ⽂件源代码:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> 
/* Header for class com_example_jnitest_JNITools */ #ifndef _Included_com_example_jnitest_JNITools 
#define _Included_com_example_jnitest_JNITools 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
 * Class:     com_example_jnitest_JNITools 
 * Method:    getStringFromJNI 
 * Signature: ()Ljava/lang/String; 
 */ 
JNIEXPORT jstring JNICALL 
Java_com_example_jnitest_JNITools_getStringFromJNI   (JNIEnv *, jclass); 
#ifdef __cplusplus 
} 
#endif 
#endif 
jni_tool.c源代码:
#include "com_example_jnitest_JNITools.h" 
JNIEXPORT jstring JNICALL 
Java_com_example_jnitest_JNITools_getStringFromJNI 
  (JNIEnv *env, jobject obj){ 
return (*env)->NewStringUTF(env,"Hellow World,这是我的 NDK的第⼀⾏ 代码"); 
  } 
注意:include进来是 com_example_jnitest_JNITools.h⽂件,⽅法名与 com_example_jnitest_JNITools.h⾥⽅法名保持⼀致

5.cd到 jni⽬录,运⾏ ndk-build

此时会报以下错误信息:

Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.    
Android NDK: WARNING: APP_PLATFORM android-16 is higher than 
android:minSdkVersion 1 in /Users/maolijun298/AndroidStudioProjects/JniTest/ app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ ndk/+/master/docs/user/common_problems.md for more information.    Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: /Users/ maolijun298/AndroidStudioProjects/JniTest/app/src/main/jni/Android.mk    /Users/maolijun298/Library/Android/sdk/ndk/21.3.6528147/build/core/add- application.mk:88: *** Android NDK: Aborting...    .  Stop. 
原因是因为没有 Android.mk文件 。

6.添加Android.mk文件

新建Android.mk文件到jni目录

Android.mk文件内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := jni_tool

LOCAL_SRC_FILES := jni_tool.c

include $(BUILD_SHARED_LIBRARY)

7.引用so

添加完成后,再次 cd到 jni⽬录,运⾏ ndk-build,会⽣成 libs⽂件夹和对应的 so库。
生成了libs对应的so库之后,需要在app的build.gradle文件里引用so路径。

build.gradle

android { 
sourceSets{ 
main{ 
jniLibs.srcDirs+=['src/main/java/libs'] } 
} 
}

7.加载so

最后,在JNITools里面加载so文件

package com.example.jnitest; 
public class JNITools { 
static { 
        System.loadLibrary("jni_tool"); 
    } 
public static native String getStringFromJNI(); } 

8.运行

最后,sync一下代码,然后运行,界面就会显示出c代码里输出的文案:

Hellow World,这是我的 NDK的第⼀⾏ 代码

以上流程亲测可用,欢迎指正!

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=36dabq4yjfswo