MaiinActivity.java
package com.example.as_jni_project;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.example.as_jni_project.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
// Used to load the 'as_jni_project' library on application startup.
static {
System.loadLibrary("as_jni_project");
}
private ActivityMainBinding binding;
private String name = "Derry";//等下用c++代码,修改为Beyond
public static int age = 28;//等下用native代码 修改为:29
private double number = 100000;
private final double number = 900000;//用c++暴力修改 get是没有问题,set在之前版本有问题,现在也没有问题了
/**
* A native method that is implemented by the 'as_jni_project' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public native void changeName();//改变我们的属性name
public static native void changeAge();//改变我们的属性age
private native void changeNumber();
public native void callAddMathod();//c调用java方法--->public int add(int number1, int number2){}
//"(II)I"
//被C调用的方法
public int add(int number1, int number2){
System.out.println("C居然调用了我");
return number1+number2+90;
}
//(I)V
public int add(int number1){
return number1;
}
//(Ljava/lang/String;)Ljava/lang/String;
//被C调用的方法
public String shoew String(String str, int value){
System.out.println("C居然调用了我 showString str:" + str + "vale:" + value);
return"【" + str + "】";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText(stringFromJNI());
System.out.println("name修改前是"+name);
changeName();
System.out.println("name修改后是"+name);
System.out.println("age修改前是"+age);
changeAge();
System.out.println("age修改后是"+age);
System.out.println("number修改前是"+number);
changeNumber();
System.out.println("number修改后是"+number);
callAddMathod();
}
}
native.cppp
#include <jni.h>
#include <string>
//日志输出
#include <android/log.h>
#define TAG "Derry"
//__VA_ARGS__ 代表 ...的可变参数
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__);
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_as_1jni_1project_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"//下面的代码,采用c的编译方式?为什么要这样,JNIEnv源码
JNIEXPORT//重要关键字,标记该方法可以被外界调用
void //代表java中的void
JNICALL//约束函数入栈顺序,和推栈内存清理的规则
//Java包名 com_xx_xx_1_类名_方法名
//JNIEnv *env JNI 桥梁 核心
//jobject == MainActivity this 实例调用的
//jclass == MainActivity class 类调用的
Java_com_derry_as_1jni_1project_MainActivity_changeName(JNIEnv *env, jobject mainActivitThis){
//如果当前是native-lib.c
//(*env)->xxx函数
//(*env)->DeleteLocalRef()
//C语言是JNIEnv *env 二级指针
//(*env)->DeleteLocalRef(env, NULL);//c没有对象,想持有env环境,就必须传递进去
//如果当前是native-lib.cpp
//env->xxx函数
//env->DeleteLocalRef()
//C++语言是JNIEnv *env 一级指针
//env->DeleteLocalRef(NULL);//C++有对象,本来就会持有this
//String Student Person Object 引用类型 == JNI全部命名为Object
jclass mainActivitCls = env->FindClass("Android/as_1jni_1project_1cpp/MainActivity");
//jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
jfieldID nameFid = env->GetFieldID(mainActivitCls, "name", "Ljava/lang/String;");//方式一
//void SetObjectField(jobject obj, jfieldID jfieldID, jobject value)
jstring value = env->NewStringUTF("修改为fff");
env->SetObjectField(mainActivitThis,nameFid, value);
}
exctern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_1cpp_MainActivity_changeAge(JNIEnv *env, jclass mainActivityCls){
//jclass mainActivityCls = env->GetObjectClass(mainActivityThis);//方式二
//jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig)
jfieldID ageFid = env->GetStaticFieldID(mainActivityCls, "age", "I");
//void SetIntField(jobject obj, jfieldID fieldID, jint value)
env->SetStaticIntField(mainActivityCls, ageFid, 29);
//jint 背后就是int, 可以直接用,string不行,必须用jstring
//int age = env->GetStaticIntField(mainActivityCls, ageFid);//获取之前的age
//env->SetStaticIntField(mainActivityCls, ageFid, age+10);
}
exctern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_1cpp_MainActivity_changeNumber(JNIEnv *env, jclass mainActivitThis){
jclass mainActivityCls = env->GetObjectClass(mainActivitThis);
//jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig)
jfieldID numberFid = env->GetFielID(mainActivityCls,"number","D");
//void SetDoubleField(jobject obj, jfieldID fieldID, jint value)
env->SetDoubleField(mainActivitThis, numberFid, 885.55);
//修改 final number2======================
jfieldID numberFid2 = env->GerFieldID(mainActivityCls,"number2", "D");
env->SetDoubleField(mainActivitThis, numberFid2, 999999.9);
double result = env->GetDoubleField(mainActivitThis, numberFid2);
//__android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
LOGD("final result:%lf\n", result);
}
exctern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_1cpp_MainActivity_changeNumber(JNIEnv *env, jclass mainActivityThis){
jclass mainActivitCls = env->GetObjectClass(mainActivitThis);
//jmethodID(*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID addMid = env->GetMethodID(mainActiviCls, "add", "(II)I");
//jint CallVoidMethod(jobject obj, jmethodID methodID, ...)
int result = env->CallVoidMethod(mainActivitThis, addMid, 1, 1);
LOGD("result:%d\n", result);
//C调用public String shoew String(String str, int value)+++++++++++++++++++++++++++
jmethodID showStringMid = env->GetMethodID(mainActivitCls, "showString", "(Ljava/lang/String;)Ljava/lang/String;");
//jobject(*CallobjectMethod)(jobject, jmethodID, ...);
jstring value = env->NewStringUFF("liyuanba");
jstring resultStr = (jstring) env->CallObjectMethod(mainActivitThis, showStringMid, value, 9527);
const char * resultCstr = env->GetDtringUTFChars(resultStr, NULL);
LOGD("r==:%s\n", resultCstr);
}