第一步:配置JDK和NDK环境,这边我不需要演示了,大家直接配置好,配置好后,可以使用ndk-build测试。
第二步:用android studio创建好一个项目(我这边是jniDemo)。
1、搭建好一个简单的布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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/txt_content"
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" />
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="调用Jni"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
2、MainActivity
package com.example.jni;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView txtContent;
private Button btnStart;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtContent = findViewById(R.id.txt_content);
btnStart = findViewById(R.id.btn_start);
btnStart.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
txtContent.setText(JNIMethod.getNativeString());
}
});
}
}
3、创建一个工具类(JNIMethod)
package com.example.jni;
public class JNIMethod {
static {
System.loadLibrary("JNIMethod");
}
public static native String getNativeString();
}
第三步:开始使用命令javac生成JNIMethod.java生成对应的class文件
..\app\src\main\java\com\example\jni>javac JNIMethod.java
第四步:使用javah命令生成.h头文件
JDK10之前调用:..\app\src\main\java>javah com.example.jni.JNIMethod
JDK10之后调用:..\app\src\main\java>javac -h com.example.jni.JNIMethod
执行以上命令后生成一个.h文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jni_JNIMethod */
#ifndef _Included_com_example_jni_JNIMethod
#define _Included_com_example_jni_JNIMethod
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jni_JNIMethod
* Method: getNativeString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_jni_JNIMethod_getNativeString
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
第五步:在main文件夹下面创建一个jni文件夹用来存放jni相关的东西,将上一步生成的.h文件移动到此文件夹下,并创建一个新的.c文件
//
// Created by Administrator on 2019/4/23.
//
#include <string.h>
#include <jni.h>
jstring Java_com_example_jni_JNIMethod_getNativeString(JNIEnv *env, jobject thiz)
{
return (*env)->NewStringUTF(env, "Hello from JNI 左左");
}
第六步:准备好头文件和源文件,开始准备编译用到的mk文件,在jni目录下分别新建Android.mk和Application.mk两个文件
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JNIMethod
LOCAL_SRC_FILES := JNIMethod.c
include $(BUILD_SHARED_LIBRARY)
以上文件,看好地址和方法名,这里并不是写死的,而是根据自己命名的类名和.c文件名
Application.mk
APP_ABI := all
上面这个是表示,编译出所有平台的so文件
第七步:编译的文件都准备好了以后,切换到jni目录执行ndk-build命令
..\app\src\main\java\jni>ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
[arm64-v8a] Compile : JNIMethod <= JNIMethod.c
[arm64-v8a] SharedLibrary : libJNIMethod.so
[arm64-v8a] Install : libJNIMethod.so => libs/arm64-v8a/libJNIMethod.so
[x86_64] Compile : JNIMethod <= JNIMethod.c
[x86_64] SharedLibrary : libJNIMethod.so
[x86_64] Install : libJNIMethod.so => libs/x86_64/libJNIMethod.so
[armeabi-v7a] Compile thumb : JNIMethod <= JNIMethod.c
[armeabi-v7a] SharedLibrary : libJNIMethod.so
[armeabi-v7a] Install : libJNIMethod.so => libs/armeabi-v7a/libJNIMethod.so
[x86] Compile : JNIMethod <= JNIMethod.c
[x86] SharedLibrary : libJNIMethod.so
[x86] Install : libJNIMethod.so => libs/x86/libJNIMethod.so
执行成功后,会形成jni同一级生成libs和obj两个目录,libs下面就是生成的各个平台的so库文件
build文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.jni"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
ndkBuild {
path "src/main/jni/Android.mk"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
以下是目录: