日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android NDK学习笔记3:JNI访问Java属性、方法

發布時間:2024/9/30 Android 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android NDK学习笔记3:JNI访问Java属性、方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/119209444
本文出自【趙彥軍的博客】

文章目錄

  • Java 類型和JNI符號對比
  • JNI 訪問屬性
  • native方法,非晶態和靜態區別
  • 多種方式獲得 jclass
  • JNI 方法Java方法
    • 無參無返回值
    • 有參數有返回值
    • 靜態方法
      • 方式1:非靜態 native 方法
      • 方式2:靜態 native 方法
  • 實戰演練: 調用Android Log
  • 實戰演練: 彈 Toast
  • 實戰演練:數組傳值

Java 類型和JNI符號對比

對應基礎類型字段的轉換:

Java 類型JNI符號
BooleanZ
ByteB
CharC
ShortS
IntI
LongJ
FloatF
DoubleD

對于引用類型的字段簽名轉換,是大寫字母 L 開頭,然后是類的簽名轉換,最后以 ; 結尾。

Java 類型JNI符號
StringLjava/lang/String;
ClassLjava/lang/Class;
ThrowableLjava/lang/Throwable;
int[][I
Object[][Ljava/lang/Object;

對于方法簽名描述的轉換,首先是將方法內所有參數轉換成對應的字段描述,并全部寫在小括號內,然后在小括號外再緊跟方法的返回值類型描述。

Java 類型JNI 對應的描述轉換
String f();()Ljava/lang/String;
long f(int i, Class c);(ILjava/lang/Class;)J
String(byte[] bytes);([B)V

這里要注意的是在 JNI 對應的描述轉換中不要出現空格。

JNI 訪問屬性

創建 Util.java 類

/*** @author : zhaoyanjun* @time : 2021/7/29* @desc :*/ public class Util {String usernName = "zhaoyanjun";int age = 10;static float key = 2f;//修改類string屬性native void changeNameValue();//修改類int屬性native void changeAgeValue();//改變靜態變量值native void changeStaticValue(); }

訪問 String 屬性、int 屬性

class MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)val util = Util()util.changeNameValue() //修改stringutil.changeAgeValue() //修改intutil.changeStaticValue() //修改靜態變量binding.sampleText.text = "value:${util.usernName} ${util.age} ${Util.key}"}companion object {// Used to load the 'native-lib' library on application startup.init {System.loadLibrary("native-lib")}} }

native-lib.cpp

//修改字符串屬性 extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_changeNameValue(JNIEnv *env, jobject thiz) {//獲取classjclass cls = env->GetObjectClass(thiz);//獲取字段jfieldID fid = env->GetFieldID(cls, "usernName", "Ljava/lang/String;");//創建新值jstring str = env->NewStringUTF("niu b");//給字段賦值env->SetObjectField(thiz, fid, str); }//修改int屬性 extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_changeAgeValue(JNIEnv *env, jobject thiz) {//獲取classjclass cls = env->GetObjectClass(thiz);//獲取字段jfieldID fid = env->GetFieldID(cls, "age", "I");//給字段賦值env->SetIntField(thiz, fid, 100); }//修改靜態屬性 extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_changeStaticValue(JNIEnv *env, jobject thiz) {//獲取classjclass cls = env->GetObjectClass(thiz);//獲取字段jfieldID fid = env->GetStaticFieldID(cls, "key", "F");//獲取靜態字段值jfloat value = env->GetStaticFloatField(cls, fid);//給字段賦值env->SetStaticFloatField(cls, fid, value + 100); }

運行起來,看看效果

值已經改變。

native方法,非晶態和靜態區別

Util.java

public class Util {native void fun1();native static void fun2(); }

native-lib.cpp

//非靜態方法 extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_fun1(JNIEnv *env, jobject thiz) {}//靜態方法 extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_fun2(JNIEnv *env, jclass clazz) {}

可以看到,非靜態方法,參數是 jobject; 靜態方法,參數是jclass。

多種方式獲得 jclass

extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_fun1(JNIEnv *env, jobject thiz) {//方式一:FindClass,參數傳入類全路徑jclass cls = env->FindClass("com/example/myapplication/Util");//方式二:GetObjectClassjclass cls2 = env->GetObjectClass(thiz); }

JNI 方法Java方法

無參無返回值

/*** @author : zhaoyanjun* @time : 2021/7/29* @desc :*/ public class Util {void run() {Log.d("util-", "runing");}String speak(String message) {Log.d("util-", "speak " + message);return message + " java";}//無參無返回值native void callRun(); }

native-lib.cpp

extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_callRun(JNIEnv *env, jobject thiz) {//獲取jclassjclass cls = env->GetObjectClass(thiz);//獲取方法jmethodID method = env->GetMethodID(cls, "run", "()V");//調用方法env->CallVoidMethod(thiz, method); }

無參符號:() , 無返回值符號:V , 結合起來就是 ()V

有參數有返回值

native String callSpeak();

native-lib.cpp

//調用帶有 extern "C" JNIEXPORT jstring JNICALL Java_com_example_myapplication_Util_callSpeak(JNIEnv *env, jobject thiz) {//獲取jclassjclass cls = env->GetObjectClass(thiz);//獲取方法jmethodID method = env->GetMethodID(cls, "speak", "(Ljava/lang/String;)Ljava/lang/String;");jstring str = env->NewStringUTF("jni hello");//方法調用,并接收返回值jobject result = env->CallObjectMethod(thiz, method, str);//返回結果return static_cast<jstring>(result); }

靜態方法

方式1:非靜態 native 方法

public class Util {static void run() {Log.d("util-", "runing");}native void callRun(); }

native-lib.cpp

extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_callRun(JNIEnv *env, jobject thiz) {jclass cls = env->GetObjectClass(thiz);jmethodID method = env->GetStaticMethodID(cls, "run", "()V");env->CallStaticVoidMethod(cls, method); }

調用:

val util = Util() util.callRun()

需要注意的是

  • 獲取靜態方法用 GetStaticMethodID
  • 調用靜態方法用 CallStaticVoidMethod

方式2:靜態 native 方法

public class Util {static void run() {Log.d("util-", "runing");}//靜態的native static void callRun(); }

native-lib.cpp

extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_callRun(JNIEnv *env, jclass clazz) {jmethodID method = env->GetStaticMethodID(clazz, "run", "()V");env->CallStaticVoidMethod(clazz, method); }

調用:

Util.callRun()

需要注意的是:靜態的 native 方法,必須用 類名調用。非靜態的 nativie方法,需要用對象調用。

實戰演練: 調用Android Log

我們首先來看系統Log類

要確認兩點信息
第一:類的包名是:android.util
第二:d() 方法,兩個參數,都是 String 類型。返回值是 int

下面我們就可以寫代碼了。

首先創建 native 方法,有兩個參數,一個是 tag , 一個是 message

public class Util {//靜態的native static void logd(String tag, String message);}

native-lib.cpp

extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_logd(JNIEnv *env, jclass clazz, jstring tag, jstring message) {//獲取Log classjclass cls = env->FindClass("android/util/Log");//獲取 d() 方法jmethodID method = env->GetStaticMethodID(cls, "d","(Ljava/lang/String;Ljava/lang/String;)I");//調用方法env->CallStaticIntMethod(cls, method, tag, message); }

具體使用:

class MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)//調用c++輸出日志Util.logd("china--", "good")}companion object {// Used to load the 'native-lib' library on application startup.init {System.loadLibrary("native-lib")}} }

實戰演練: 彈 Toast

c 代碼

/*** 顯示一個 Toast* Toast.makeText(this,"message",Toast.LENGTH_SHORT).show();*/ extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_showToast(JNIEnv *env, jclass clazz, jobject context,jstring message) {//獲取Toastjclass cls = env->FindClass("android/widget/Toast");//獲取 makeText 方法jmethodID makeText = env->GetStaticMethodID(cls, "makeText","(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;");//調用makeText方法, Toast.LENGTH_SHORT=0jobject toast = env->CallStaticObjectMethod(cls, makeText, context, message, 0);//獲取 show 方法jmethodID show = env->GetMethodID(cls, "show", "()V");//調用 show 方法env->CallVoidMethod(toast, show); }

java 方法聲明

public class Util {native static void showToast(Context context, String message); }

方法調用:

//顯示一個toast Util.showToast(this, "今天是周一")

實戰演練:數組傳值

Util.java 類

public class Util {native void run();//這個方法時c調用public void show(String[] array) {for (int i = 0; i < array.length; i++) {Log.d("show-", "" + i + " " + array[i]);}} }

可以看到 Util 有兩個方法,一個是 run , 一個是 show 方法,參數是一個 String 數組。

我們現在來做,java 調用 run , 然后 c 實現的 run 再調用 show方法,并且傳值 。

c 代碼如下:

extern "C" JNIEXPORT void JNICALL Java_com_example_myapplication_Util_run(JNIEnv *env, jobject thiz) {jclass cls = env->GetObjectClass(thiz);//獲取show反復jmethodID show = env->GetMethodID(cls, "show", "([Ljava/lang/String;)V");//定義string數組int size = 3;jclass strClass = env->FindClass("java/lang/String");jobjectArray resultArray = env->NewObjectArray(size, strClass, nullptr);//string數組賦值jstring strItem;for (int i = 0; i < size; ++i) {strItem = env->NewStringUTF("string in native");env->SetObjectArrayElement(resultArray, i, strItem);}//調用 show 方法env->CallVoidMethod(thiz, show, resultArray); }

java 調用 run , 代碼如下:

Util().run()

輸出結果如下:

D/show-: 0 string in native D/show-: 1 string in native D/show-: 2 string in native

總結

以上是生活随笔為你收集整理的Android NDK学习笔记3:JNI访问Java属性、方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。