很多朋友在论坛和QQ群里问到这个,今天有时间写了个简单的示例。

功能很简单,允许你输入一个web页面地址,使用Java的下载类库下载后用QTextEdit显示出来。

版权所有:foruok。转载请注明出处:http://blog.csdn.net/foruok。

效果展示

初始效果如图1所示:


图1 useJar示例初始效果

图2为点击"GET"按钮后下载到对应页面的效果:


图2 下载页面成功

下载部分,为了显示如何使用jar包,我用了asynchttpclient,参考我的博文:Android开源框架AsyncHttpClient (android-async-http)使用。

项目创建

参考《Qt on Android:图文详解Hello World全过程》吧,没什么特别可说的。

pro文件内添加“QT +=androidextras”。

创建一个AndroidManifest,package命名为an.qt.useJar。

版权所有:foruok。转载请注明出处:http://blog.csdn.net/foruok。

添加Java源码

你可以任意的文本编辑器中编辑java源码,然后通过Qt Creator项目视图加到项目里,在其它文件那里鼠标右键点击,选择添加现有文件即可。参考下面几张图吧。


图3 添加Java源码之右键菜单


图4 添加Java源文件之选择Java源文件


图5 添加Java源文件OK

修改AndroidManifest,把activity标签的android:name属性值修改为an.qt.useJar.ExtendsQtWithJava。这是必须的,因为我们的ExtendsQtWithJava.java实现的Activity就是这个名字。

好了,Java代码添加结束。

添加第三方jar包

这个没什么好说的,放在android/libs目录下即可。看图:


图6 放jar包

只要放好位置,Qt Creator编译项目时就会把这个jar包打包到APK里。

Java源码使用jar包

这是java编程的内容了,import包名,然后使用即可。

源码分析

咱先看Java侧的代码吧。

Java代码

ExtendsQtWithJava.java:

package an.qt.useJar;import java.lang.String;import android.content.Context;import android.content.Intent;import android.app.PendingIntent;import android.os.Handler;import android.os.Message;import android.util.Log;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.net.Uri;import android.location.Criteria;import android.provider.Settings;import android.os.Bundle;import android.os.Environment;import java.io.File;import com.loopj.android.http.AsyncHttpClient;import com.loopj.android.http.AsyncHttpResponseHandler;public class ExtendsQtWithJava extends org.qtproject.qt5.android.bindings.QtActivity{    private static ExtendsQtWithJava m_instance;    private final static String TAG = "extendsQt";    private static String m_pageUri = null;    private static Handler m_handler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {            case 1:                if(m_pageUri == null){                    m_pageUri = (String)msg.obj;                    m_instance.downloadText(m_pageUri);                }else{                    m_instance.notifyQt(0, (String)msg.obj, "Downloader is Busy now!");                }                break;            };        }    };        public ExtendsQtWithJava(){        m_instance = this;    }    public static int networkState(){        ConnectivityManager conMan = (ConnectivityManager) m_instance.getSystemService(Context.CONNECTIVITY_SERVICE);        return conMan.getActiveNetworkInfo() == null ? 0 : 1;    }    public static AsyncHttpClient m_httpc = new AsyncHttpClient();    public static ExtendsQtNative m_nativeNotify = null;    public void downloadText(String uri){        Log.d(TAG, "start downloadText");        m_httpc.get(uri, null, new AsyncHttpResponseHandler(){            @Override            public void onSuccess(String data){                notifyQt(1, m_pageUri, data);                m_pageUri = null;            }            @Override            public void onFailure(Throwable e, String data){                notifyQt(-1, m_pageUri, data);                m_pageUri = null;            }        });    }        public static void downloadWebPage(String uri){        Log.d(TAG, "downloadWebPage");        m_handler.sendMessage(m_handler.obtainMessage(1, uri));    }        private void notifyQt(int result, String uri, String data){        if(m_nativeNotify == null){            m_nativeNotify = new ExtendsQtNative();        }        m_nativeNotify.OnDownloaded(result, uri, data);    }}

ExtendsQtNative.java:

package an.qt.useJar;import java.lang.String;public class ExtendsQtNative{    public native void OnDownloaded(int result, String url, String content);}

基本思路是酱紫的:

Qt调用java的downloadWebPage,Java代码使用asynchttpclient下载一个网页,然后调用ExtendsQtNative通知Qt C++代码。

C++代码

分两部分,一部分是实现JNI方法。另一部分是调用Java类的方法。

实现JNI方法并注册

先看与ExtendsQtNative对应的JNI实现,在main.cpp中,都列出吧:

#include "widget.h"#include <QApplication>#include <QAndroidJniEnvironment>#include <QAndroidJniObject>#include <jni.h>#include "../simpleCustomEvent.h"#include <QDebug>QObject *g_listener = 0;// result: -1 failed; 1 success; 0 busy;static void onDownloaded(JNIEnv *env, jobject thiz,int result, jstring uri, jstring data){    QString qstrData;    const char *nativeString = env->GetStringUTFChars(data, 0);    qstrData = nativeString;    env->ReleaseStringUTFChars(data, nativeString);    QCoreApplication::postEvent(g_listener, new SimpleCustomEvent(result, qstrData));}bool registerNativeMethods(){    JNINativeMethod methods[] {        {"OnDownloaded", "(ILjava/lang/String;Ljava/lang/String;)V", (void*)onDownloaded}    };    const char *classname = "an/qt/useJar/ExtendsQtNative";    jclass clazz;    QAndroidJniEnvironment env;    QAndroidJniObject javaClass(classname);    clazz = env->GetObjectClass(javaClass.object<jobject>());    qDebug() << "find ExtendsQtNative - " << clazz;    bool result = false;    if(clazz)    {        jint ret = env->RegisterNatives(clazz,                                        methods,                                        sizeof(methods) / sizeof(methods[0]));        env->DeleteLocalRef(clazz);        qDebug() << "RegisterNatives return - " << ret;        result = ret >= 0;    }    if(env->ExceptionCheck()) env->ExceptionClear();    return result;}int main(int argc, char *argv[]){    QApplication a(argc, argv);    SimpleCustomEvent::eventType();    registerNativeMethods();    Widget w;    g_listener = qobject_cast<QObject*>(&w);    w.show();    return a.exec();}

注册JNI方法,设置一个全局的对象接收通知。具体的,参考Qt帮助来理解。

调用Java方法

对Java方法的调用在Widget.cpp中。直接看代码吧。

widget.h:

#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QLineEdit>#include <QTextEdit>#include <QLabel>class Widget : public QWidget{    Q_OBJECTpublic:    Widget(QWidget *parent = 0);    ~Widget();    bool event(QEvent *e);public slots:    void onGet();private:    QLineEdit * m_urlEdit;    QTextEdit * m_resultView;    QLabel * m_stateLabel;};#endif // WIDGET_H

都是界面相关的,没什么好说的。看widget.cpp:

#include "widget.h"#include <QVBoxLayout>#include <QPushButton>#include "../simpleCustomEvent.h"#include <QAndroidJniObject>#include <QAndroidJniEnvironment>Widget::Widget(QWidget *parent)    : QWidget(parent){    QVBoxLayout *layout = new QVBoxLayout(this);    QHBoxLayout *getLayout = new QHBoxLayout();    layout->addLayout(getLayout);    m_urlEdit = new QLineEdit("http://blog.csdn.net/foruok");    getLayout->addWidget(m_urlEdit, 1);    QPushButton *getButton = new QPushButton("GET");    getLayout->addWidget(getButton);    connect(getButton, SIGNAL(clicked()), this, SLOT(onGet()));    m_resultView = new QTextEdit();    m_resultView->setReadOnly(true);    layout->addWidget(m_resultView, 1);    m_stateLabel = new QLabel();    layout->addWidget(m_stateLabel);}Widget::~Widget(){}bool Widget::event(QEvent *e){    if(e->type() == SimpleCustomEvent::eventType())    {        e->accept();        SimpleCustomEvent *sce = (SimpleCustomEvent*)e;        switch(sce->m_arg1)        {        case 1:            m_resultView->setText(sce->m_arg2);            m_stateLabel->setText("Success!");            break;        case 0:            m_resultView->setText(sce->m_arg2);            m_stateLabel->setText("Failed!");            break;        case -1:            m_stateLabel->setText(sce->m_arg2);            break;        }        return true;    }    return QWidget::event(e);}void Widget::onGet(){#ifdef WIN32    m_resultView->setText("Sorry, Just for Android!");#elif defined(ANDROID)    QString url = m_urlEdit->text();    QAndroidJniObject javaAction = QAndroidJniObject::fromString(url);    QAndroidJniObject::callStaticMethod<void>("an/qt/useJar/ExtendsQtWithJava",                                       "downloadWebPage",                                       "(Ljava/lang/String;)V",                                       javaAction.object<jstring>());    m_stateLabel->setText("Downloading...");#endif}

调用Java的代码在onGet()槽中,很简单,不解释了。有疑问看Qt帮助手册有关QAndroidJniObject类的说明。


OK,到此结束。源码下载点我点我

版权所有:foruok。转载请注明出处:http://blog.csdn.net/foruok。

我的Qt on Android系列文章:

  • Qt on Android:图文详解Hello World全过程
  • Windows下Qt 5.2 for Android开发入门
  • Qt for Android 部署流程分析
  • Qt on Android:将Qt调试信息输出到logcat中
  • Qt on Android: Qt 5.3.0 发布,针对 Android 改进说明
  • Qt on Android Episode 1(翻译)
  • Qt on Android Episode 2(翻译)
  • Qt on Android Episode 3(翻译)
  • Qt on Android Episode 4(翻译)
  • Qt for Android 编译纯C工程
  • Windows下Qt for Android 编译安卓C语言可执行程序
  • Qt on Android: Android SDK安装
  • Qt on Android: http下载与Json解析
  • Qt on Android 之设置应用名为中文
  • Qt on Android:让 Qt Widgets 和 Qt Quick 应用全屏显示
  • Qt on Android:怎样适应不同的屏幕尺寸

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 超简单实用详细的android Widget实例教程
  3. 玩一下android的反编译和代码混淆
  4. JS和Android交互调用
  5. Android(安卓)下拉回弹BounceScrollView
  6. Android之串口通信基础
  7. (4.1.19)【Android(安卓)UI设计与开发】第06期:底部菜单栏(一)使用Tab
  8. Android(安卓)手机获取手机号实现方法
  9. Android(安卓)学习之《第一行代码》第二版 笔记(十八)调用摄像头拍

随机推荐

  1. 短信接口怎么对接?看完这篇文章你就知道了
  2. web前端开发必备技能
  3. 前端工程师想要做一个Vue-ts后台管理系统
  4. kubernetes生产实践之mysql
  5. 使用supervisor 管理logstash
  6. ProBuilder快速原型开发技术 ---模型精细
  7. 数字孪生与物联网(IoT)底层伴生技术的强联
  8. RHEL7 root 开启FTP服务
  9. 如何解决Plao Alto防火墙的V*P*N客户端Gl
  10. Nginx编译报错解决方法