3、QAndroidJniObject类简介

文章目录

  • 1、JNI
    • 使用JNI的两点基础
  • 2、Qt的androidextras模块
    • 2.1、QAndroidJniEnvironment 类功能简介
    • 2.2、QAndroidJniObject 类功能简介
    • 2.3、构造一个java对象
      • 2.3.1、构造一个 Intent 对象
      • 2.3.2、构造一个空的 String 对象
    • 2.4、构造一个包含action的lntent对象
      • 2.4.1、Intent简介
      • 2.4.2、Intent属性
      • 2.4.3、调用 Intent 的 Intent(String action)构造函数来创建一个 Intent 类
    • 2.5、调用 Java 实例方法
      • 2.5.1、计算字符串的长度
      • 2.5.2、 callObjectMethod 的例子
    • 2.5、调用 Java 类(静态)方法

1、JNI

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。

使用JNI的两点基础

  • 基础1:引用java的包
    String 类在包 java.lang 中,全路径类名为 java.lang.String 。当我们在 C++ 用以字符串方式描述一个 Java 类时,需要把 “.” 替换为 “/” ,如 java.lang.String字符串描述为 “java/lang/String” 。又如 android.content.Intent ,字符串描述为 “android/content/Intent” 。

  • 基础2:方法签名
    方法签名的表述形式:(Arguments)ReturnType 。圆括号中是参数列表,紧跟圆括号的是返回值类型。例如“(I)C”的意思就是参数为 int ,返回值为 char 。当一个 Java 方法的参数或返回值类型为对象时,需要使用全路径类名,并且加前缀“L”和后缀“;”。如“(Ljava/lang/String;)Ljava/lang/String;”,表示一个方法的参数类型为 String ,返回值也是 String。

2、Qt的androidextras模块

Qt 提供的 JNI 功能编程,离开 QAndroidJniObject 可谓寸步难行。

QAndroidJniObject 属于 androidextras 模块,要使用它,需要在 pro 文件中加入下面的代码:

QT += androidextras  

androidextras 是从 Qt 5.2 引入的,这个模块内还包括了QAndroidJniEnvironment 类

2.1、QAndroidJniEnvironment 类功能简介

QAndroidJniEnvironment 代表 JNI 环境,也就是通常我们使用 JNI 编程时的 JNIEnv 。我们使用 Qt 进行 JNI 编程时,构造一个 QAndroidJniEnvironment 对象,即可获得 JNIEnv 指针,可以进一步使用 JNIEnv 的方法来实现特定功能,比如检查 JNI 调用过程中是否发生了异常、清理异常等等

2.2、QAndroidJniObject 类功能简介

QAndroidJniObject 是对原始 JNI 类型的封装,代表了一个 Java 对象(类的实例),它提供了很多方法供开发者使用:

  • 构造一个 Java 对象
  • 调用 Java 静态(类)方法
  • 调用 Java 实例方法

2.3、构造一个java对象

QAndroidJniObject 提供了下列构造函数来创建 JNI 对象:

QAndroidJniObject()
QAndroidJniObject(const char * className)
QAndroidJniObject(const char * className, const char * signature, …)
QAndroidJniObject(jclass clazz)
QAndroidJniObject(jclass clazz, const char * signature, …)
QAndroidJniObject(jobject object)

静态方法:
QAndroidJniObject fromString(const QString & string)

构造函数又分了两类

  • 一类是根据 Java 类名和 Java 类构函数签名来创建 JNI 对象;
  • 一类是根据已有的 JNI 对象(也可结合 Java 构造函数签名)来创建 QAndroidJniObject 对象;

2.3.1、构造一个 Intent 对象

QAndroidJniObject intent("android/content/Intent");

2.3.2、构造一个空的 String 对象

QAndroidJniObject str("java/lang/String");  

2.4、构造一个包含action的lntent对象

2.4.1、Intent简介

Intent的中文意思是“意图,意向”,在Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,可以将Intent理解为不同组件之间通信的“媒介”专门提供组件互相调用的相关信息。

简单理解:Intent 类是 Android 提供的、用于组件间通信的一种机制。通过 Intent ,你可以调用其它的系统功能或第三方提供的功能,比如你可以调用拨打电话的功能,可以显示联系人,也可以调用相机。我们在使用 Intent 时可以指定一个 action ,action 代表你要做的动作,也就是你想干啥;还可以在 Intent 中携带数据给被调用的一方。

2.4.2、Intent属性

Intent有以下几个属性:
动作(Action),数据(Data),分类(Category),类型(Type),组件(Compent)以及扩展信(Extra)。其中最常用的是Action属性和Data属性。

2.4.3、调用 Intent 的 Intent(String action)构造函数来创建一个 Intent 类

  • 功能介绍:
    打开 Android 系统设置
  • 代码
 QAndroidJniObject action = QAndroidJniObject::fromString("android.settings.SETTINGS");  
 QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;)V", 
  , action.object<jstring>());  
  • 代码步骤:

使用 QAndroidJniObject::fromString 构造了一个 Java 的 String 对象作为我们的 action ,这个 action 会打开 Android 系统设置。

然后我们调用 Intent 的 Intent(String action)构造函数来创建一个 Intent 类。 构造函数没有返回值,参数为 String, 所以函数签名是“(Ljava/lang/String;)V”。QAndroidJniObject 的 object 方法返回它所持有的 java 对象, action.object() 返回的就是 jstring 喽。

2.5、调用 Java 实例方法

有了 Java 对象,我们就可以调用这个对象的实例方法。
所谓实例方法,就是一个类的非静态方法,需要先有对象才能调用。而类方法,指的就是类的静态方法。

QAndroidJniObject 提供了下列方法以方便我们调用 Java 实例方法:

  • T callMethod(const char * methodName) const
  • T callMethod(const char * methodName, const char * signature, …) const
  • QAndroidJniObject callObjectMethod(const char * methodName) const
  • QAndroidJniObject callObjectMethod(const char * methodName, const char * signature, …) const

两个 callMethod 方法,调用 Java 对象的那些返回值为基础类型(如int、double等)的实例方法。两个 callObjectMethod 方法则调用 Java 对象的那些返回值为对象(类实例)的实例方法

2.5.1、计算字符串的长度

QAndroidJniObject action = QAndroidJniObject::fromString("android.settings.-
family: Arial, Helvetica, sans-serif;">SETTINGS-family: Arial,
Helvetica, sans-serif;">");</span>  
int = action.callMethod<jint>("length");  

上面的代码调用 fromString 创建一个 Java String 对象,然后使用 callMethod 调用 String 的 “int length()” 方法来获取字符串的长度。

2.5.2、 callObjectMethod 的例子

 QAndroidJniObject action = QAndroidJniObject::fromString("android.settings.SETTINGS");  
jint start = 4;  
QAndroidJniObject substring = action.callObjectMethod("substring", "(I)Ljava/lang/String", 
start); 

上面的代码,调用 Java String 类的 “String substring(int start)”方法来获取子串。

2.5、调用 Java 类(静态)方法

 调用 Java 类方法,无需构造 Java 对象,因为类方法是静态方法,是属于类的,不需要对象就可以调用。

QAndroidJniObject 提供了下列静态方法来调用 Java 类方法:

  • T callStaticMethod(const char * className, const char * methodName)
  • T callStaticMethod(const char * className, const char * methodName, const char * signature, …)
  • T callStaticMethod(jclass clazz, const char * methodName)
  • T callStaticMethod(jclass clazz, const char * methodName, const char * signature, …)
  • QAndroidJniObject callStaticObjectMethod(const char * className, const char * methodName)
  • QAndroidJniObject callStaticObjectMethod(const char * className, const char * methodName, const char * signature, …)
  • QAndroidJniObject callStaticObjectMethod(jclass clazz, const char * methodName)
  • QAndroidJniObject callStaticObjectMethod(jclass clazz, const char * methodName, const char * signature, …)

callStaticMethod 有四个,直接调用 Java 类的静态方法,需要一个模版参数,对应于 Java 类方法的返回值。
callStaticObjectMethod 也有四个,可以调用 Java 类的那些返回对象的静态方法。

 jint a = 2;  
 jint b = 4;  
 jint max = QAndroidJniObject::callStaticMethod<jint>(  
                       "java/lang/Math", "max", "(II)I", a, b);  
                       
QAndroidJniObject thread =   
              QAndroidJniObject::callStaticObjectMethod(  
               "java/lang/Thread", "currentThread",  
                "()Ljava/lang/Thread;");  
                
QAndroidJniObject string =   
         QAndroidJniObject::callStaticObjectMethod(  
            "java/lang/String", "valueOf", "(I)Ljava/lang/String;", 10);  

上面的代码片段实际上是三个小示例。

第一个小示例,调用 java.lang.Math 来求两个数中较大的那个。“ int max(int, int) ”用来完成“求两数中较大那个”这一功能。

第二个小示例,调用 java.lang.Thread 的 currentThread方法获取当前的线程对象,currentThread 方法没有参数,返回值是 Thread 对象。

第三个小示例,调用 java.lang.String 的 valueOf 方法把一个数字转换为字符串。valueOf 原型为 “ String valueOf(int)”。

你可能感兴趣的:(Qt工作积累,java,开发语言)