只是为了记录学习成长
代码在附件
//找到对应的JNITools类luo/
// com.luo.administrator.jnidemo4;
jclass jClassName=(*env)->FindClass(env,“com/luo/administrator/jnidemo4/JNITool”);
路径写错会加载不到库,找不到库
//开始注册
jint ret = (*env)->RegisterNatives(env,jClassName,method, 2);
2是方法数,如果写错会报空指针错。报错地址是0x0 因为注册的时候报错的,所以就不用反编译看哪个地址的函数了。下面是错误log
11-14 19:31:04.905 3603 3642 I bt_btif_a2dp_sink: btif_a2dp_sink_audio_handle_start_decoding
11-14 19:31:05.338 17225 17225 D JNITag : enter jni_onload
11-14 19:31:05.339 17225 17225 F libc : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4ddddc492fc960 in tid 17225 (trator.jnidemo4), pid 17225 (trator.jnidemo4)
11-14 19:31:05.403 17274 17274 E DEBUG : failed to readlink /proc/17225/fd/66: No such file or directory
11-14 19:31:05.404 17274 17274 E DEBUG : failed to readlink /proc/17225/fd/67: No such file or directory
11-14 19:31:05.435 17274 17274 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
11-14 19:31:05.437 399 399 I /system/bin/tombstoned: received crash request for pid 17225
11-14 19:31:05.441 17274 17274 I crash_dump64: performing dump of process 17225 (target tid = 17225)
11-14 19:31:05.473 17274 17274 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-14 19:31:05.473 17274 17274 F DEBUG : Build fingerprint: ‘AURA/Air_Line_AC5/Air_Line_AC5:9/PQ3A.190505.002/ron11112126:userdebug/dev-keys’
11-14 19:31:05.473 17274 17274 F DEBUG : Revision: ‘0’
11-14 19:31:05.473 17274 17274 F DEBUG : ABI: ‘arm64’
11-14 19:31:05.473 17274 17274 F DEBUG : pid: 17225, tid: 17225, name: trator.jnidemo4 >>> com.luo.administrator.jnidemo4 <<<
11-14 19:31:05.473 17274 17274 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4ddddc492fc960
核心几个部分代码:
package com.luo.administrator.jnidemo4;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class JNITestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jnitest);
Button bt1_add = findViewById(R.id.add);
Button bt1_sub = findViewById(R.id.sub);
final EditText inputa = findViewById(R.id.inputa);
final EditText inputb = findViewById(R.id.inputb);
final TextView rest = findViewById(R.id.result);
bt1_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
double result = 0;
String strA = inputa.getText().toString();
String strB = inputb.getText().toString();
int a = Integer.parseInt(strA);
int b = Integer.parseInt(strB);
result = JNITool.add(a,b);
rest.setText(""+result);
}
});
bt1_sub.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
double result = 0;
String strA = inputa.getText().toString();
String strB = inputb.getText().toString();
int a = Integer.parseInt(strA);
int b = Integer.parseInt(strB);
result = JNITool.sub(a,b);
rest.setText(""+result);
}
});
}
}
package com.luo.administrator.jnidemo4;
/**
* Created by Administrator on 2019/11/14 0014.
*/
public class JNITool {
static {
System.loadLibrary("jnidemo4");
}
//加法
public static native int add(int a,int b);
//减法
public static native int sub(int a,int b);
}
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint subNumber(JNIEnv *env,jclass clazz,jint a,jint b);
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
//打印日志,说明已经进来了
__android_log_print(ANDROID_LOG_DEBUG,"JNITag","enter jni_onload");
JNIEnv* env = NULL;
jint result = -1;
// 判断是否正确
if((*vm)->GetEnv(vm,(void**)&env,JNI_VERSION_1_6)!= JNI_OK){
return result;
}
//注册四个方法,注意签名
const JNINativeMethod method[]={
{"add","(II)I",(void*)addNumber},
{"sub","(II)I",(void*)subNumber},
// {"mul","(II)I",(void*)mulNumber},
// {"div","(II)I",(void*)divNumber}
};
//找到对应的JNITools类luo/
// com.luo.administrator.jnidemo4;
jclass jClassName=(*env)->FindClass(env,"com/luo/administrator/jnidemo4/JNITool");
//开始注册
jint ret = (*env)->RegisterNatives(env,jClassName,method, 2);
//如果注册失败,打印日志
if (ret != JNI_OK) {
__android_log_print(ANDROID_LOG_DEBUG, "JNITag", "jni_register Error");
return -1;
}
return JNI_VERSION_1_6;
}
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a+b;
}
jint subNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a-b;
}
这个build.gradle 很关键
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.luo.administrator.jnidemo4"
minSdkVersion 27
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk{
moduleName "jnidemo3"
abiFilters 'x86','armeabi-v7a','arm64-v8a'
ldLibs "log"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
sourceSets.main {
jni.srcDirs = [ ]
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
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'
}
效果图