转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119209444 本文出自【赵彦军的博客】
Java 类型和JNI符号对比
对应基础类型字段的转换:
Java 类型 | JNI符号 |
---|
Boolean | Z | Byte | B | Char | C | Short | S | Int | I | Long | J | Float | F | Double | D |
对于引用类型的字段签名转换,是大写字母 L 开头,然后是类的签名转换,最后以 ; 结尾。
Java 类型 | JNI符号 |
---|
String | Ljava/lang/String; | Class | Ljava/lang/Class; | Throwable | Ljava/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 类
public class Util {
String usernName = "zhaoyanjun";
int age = 10;
static float key = 2f;
native void changeNameValue();
native void changeAgeValue();
native void changeStaticValue();
}
访问 String 属性、int 属性
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val util = Util()
util.changeNameValue()
util.changeAgeValue()
util.changeStaticValue()
binding.sampleText.text = "value:${util.usernName} ${util.age} ${Util.key}"
}
companion object {
init {
System.loadLibrary("native-lib")
}
}
}
native-lib.cpp
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_Util_changeNameValue(JNIEnv *env, jobject thiz) {
jclass cls = env->GetObjectClass(thiz);
jfieldID fid = env->GetFieldID(cls, "usernName", "Ljava/lang/String;");
jstring str = env->NewStringUTF("niu b");
env->SetObjectField(thiz, fid, str);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_Util_changeAgeValue(JNIEnv *env, jobject thiz) {
jclass 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) {
jclass 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) {
jclass cls = env->FindClass("com/example/myapplication/Util");
jclass cls2 = env->GetObjectClass(thiz);
}
JNI 方法Java方法
无参无返回值
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) {
jclass 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) {
jclass 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) {
jclass cls = env->FindClass("android/util/Log");
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: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Util.logd("china--", "good")
}
companion object {
init {
System.loadLibrary("native-lib")
}
}
}
|