【Qt】Qt for Android创建AndroidManifest.xml调用java

用Qt编写跨平台的安卓程序虽然便捷,但也有很大的局限性,对手机硬件的开关读写等都需要调用原生的java接口,而Qt已经提供了c++调用java的JNI接口。
从网上搜了不少帖子,基本没有一个能用的,不知是否我操作有勿,毕竟从没接触过java。现通过阅读《Qt on Android核心编程》一书,并结合自己的实践,成功通过Qt编写安卓程序,调用java对手机的wifi进行操作。还是那句话,通道一旦打开,之后就是个人发挥了。

1.创建AndroidManifest.xml

在工程中点左侧的项目,展开Build Android APK,点击Create Templa,如下图
在这里插入图片描述
直接按默认路径点击确定,在你的工程目录下便多出了一个“其他文件夹”,其中有个android文件夹,AndroidManifest.xml便在这个android文件夹下,如下图。另外,android文件夹下,除了AndroidManifest.xml文件其余的都可以删掉,前提是不使用gradle。
在这里插入图片描述
双击AndroidManifest.xml,如下图。看到其默认package name为org.qtproject.example,记住这个package name,这个非常非常,非常重要。同时,因为我调用的是wifi接口,所以在下方的permissions中要添加相关权限,比如图中我添加的那几个。
在这里插入图片描述

2.按路径添加文件夹和java源文件

Qt的JNI调用的java源文件默认是要在src文件夹下的,而刚刚说的那个非常重要的package name,也就是org.qtproject.example正是java源文件在src文件夹中的路径。什么意思呢?就是说你要调用一个java源文件,那么这个源文件必须位于src/org/qtproject/example路径下,所以,我们在android文件夹下依次创建src、org、qtproject、example文件夹,并将java源文件放在这里,我的java源文件名字为ExtendsQtWithJava,所以我的文件夹结构如下图所示
在这里插入图片描述
java源码如下

package org.qtproject.example;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.content.Context;

public class ExtendsQtWithJava extends org.qtproject.qt5.android.bindings.QtActivity
{
    private static ExtendsQtWithJava m_instance ;


    public ExtendsQtWithJava(){
        m_instance = this;
    }


    public static int getwifienable(){
        WifiManager conMan = (WifiManager) m_instance.getSystemService(Context.WIFI_SERVICE);
        if(conMan.isWifiEnabled())
            return 1;
        else
            return 0;

    }

    public static void openWifi(){
        WifiManager conMan = (WifiManager) m_instance.getSystemService(Context.WIFI_SERVICE);
        if(!conMan.isWifiEnabled()){
            conMan.setWifiEnabled(true);
        }
    }

    public static void closeWifi(){
        WifiManager conMan = (WifiManager) m_instance.getSystemService(Context.WIFI_SERVICE);
        if(conMan.isWifiEnabled()){
            conMan.setWifiEnabled(false);
        }
    }

    public static int networkEnable(){
        ConnectivityManager conMan = (ConnectivityManager)m_instance.getSystemService(Context.CONNECTIVITY_SERVICE);
        return conMan.getActiveNetworkInfo() == null ? 0:1;
    }

}

注意这个java源码的package name要和刚刚创建AndroidManifest.xml时的package name相同,也就是org.qtproject.example。在这个源文件中,定义了ExtendsQtWithJava类,继承于org.qtproject.qt5.android.bindings.QtActivity,其中实现了几个方法,分别是获得wifi状态、打开关闭wifi、获得网络状态,这些都是典型的java调用安卓设备的代码,想要什么网上都可以搜到。

3.在XML Source下配置AndroidManifest.xml

这一步非常重要,也正是网上各帖子没有讲明白的。打开AndroidManifest.xml,然后点击XML Source进入源码模式编辑AndroidManifest.xml,如下图
在这里插入图片描述
重点来了,网上所有帖子都说把android:name改成某某某,但并没有说实在哪个android:name后修改。我也是看了《Qt on Android核心编程》后才得知要修改的时activity后的android:name。
以源码模式打开AndroidManifest.xml后,我们能清楚的看到package为org.qtproject.example,然后找到activity元素,然后将其后边的android:name =“xxxxx”中的内容改为package name + java源码名字的格式。以本工程为例,就是改成android:name=“org.qtproject.example.ExtendsQtWithJava”
,如以下代码中的第四行。

<?xml version="1.0"?>
<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
    <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --">
        <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.example.ExtendsQtWithJava" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">

到此为止,在你的Qt c++程序中就可以调用ExtendsQtWithJava类中的方法了,也就是调用java。

4.在Qt中调用java

首先在pro文件中添加一行:QT += androidextras,并在需要调用java的cpp中包含以下头文件

#include <QtAndroid>
#include <QAndroidJniObject>
#include <QAndroidJniEnvironment>

现在就可以在c++中调用java了
添加了三个按钮和一个textEdit用来调试wifi状态和开关wifi,代码如下

void MainWindow::on_pushButton_clicked()
{
    int wifistate;
    wifistate = QAndroidJniObject::callStaticMethod<jint>("org/qtproject/example/ExtendsQtWithJava",
                                                          "getwifienable",
                                                          "()I");
    if(wifistate == 1)
    {
        ui->textEdit->append(tr("wifi is enable"));
    }
    else
    {
        ui->textEdit->append(tr("wifi is disable"));
    }
}


void MainWindow::on_pushButton_2_clicked()
{
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/ExtendsQtWithJava",
                                        "openWifi");
    ui->textEdit->append(tr("wifi open"));
}


void MainWindow::on_pushButton_3_clicked()
{
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/ExtendsQtWithJava",
                                        "closeWifi");
    ui->textEdit->append(tr("wifi closed"));
}

利用QAndroidJniObject::callStaticMethod来调用java源码中的方法。

QAndroidJniObject::callStaticMethod<jint>("org/qtproject/example/ExtendsQtWithJava",
                                                          "getwifienable",
                                                          "()I");

这里的是因为在java源码中getwifienable这个函数是返回int的,后边的三个参数:1.“org/qtproject/example/ExtendsQtWithJava”,源码路径;2. “getwifienable”,java方法;3. “()I”,java签名,因为次方法为无参数、返回int型的,所以此处的java签名为()I,具体java签名规则可以自行百度。

5.编译、安装、测试

连接手机后编译,程序在手机上按预期运行。即点击wifi state按钮能够获得手机当前wifi的打开、关闭状态,open wifi和close wifi也能按预期执行,测试正常,如下图。
在这里插入图片描述
在这里插入图片描述
工程源码:https://download.csdn.net/download/spiremoon/11962116

猜你喜欢

转载自blog.csdn.net/spiremoon/article/details/102936869