Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Qt on Android:使用JNI與第三方jar包

Qt on Android:使用JNI與第三方jar包

編輯:關於Android編程

很多朋友在論壇和QQ群裡問到這個,今天有時間寫了個簡單的示例。

功能很簡單,允許你輸入一個web頁面地址,使用Java的下載類庫下載後用QTextEdit顯示出來。

 

效果展示

初始效果如圖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 
#include 
#include 
#include 
#include ../simpleCustomEvent.h
#include 

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());
    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(&w);
    w.show();

    return a.exec();
}

注冊JNI方法,設置一個全局的對象接收通知。具體的,參考Qt幫助來理解。

 

調用Java方法

對Java方法的調用在Widget.cpp中。直接看代碼吧。

widget.h:

 

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 
#include 

class Widget : public QWidget
{
    Q_OBJECT

public:
    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 
#include 
#include ../simpleCustomEvent.h
#include 
#include 

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(an/qt/useJar/ExtendsQtWithJava,
                                       downloadWebPage,
                                       (Ljava/lang/String;)V,
                                       javaAction.object());
    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. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved