4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

QtAdvent Calendar 2020

Day 20

Android Studioで作成したJarファイルをQt/Androidアプリで使用する

Last updated at Posted at 2020-12-19

はじめに

Android Studioで作成したJavaクラスをJarファイル化し、JarファイルをQtプロジェクトに取り込んで、Qt/AndroidアプリからJarファイルのクラスを使用する方法を紹介します。

開発環境

  • Android Studio:3.5.3
  • Android端末:SO-02J(Android8.0.0)
  • Qt Creator:4.13.3
  • コンパイラ:Android Qt 5.15.2 Clang Multi-Abi

Android StudioでJarファイルを作成する

Android StudioにはJarファイル単体を作成するプロジェクトはない為、まず使い捨ての空プロジェクトを作成します。
Android1.png

File -> New -> New Moduleを選択します。
Android2.png
Java Libraryを選択してNextを押下します。

Android3.png
Library nameをmyLibraryに変更し、Finishを押下します。

Android4.png
すると、ツリーにmyLibraryが追加され、MyClass.javaが作成されます。
MyClassに次のようにgetWord()メソッドを追加します。

MyClass.java
package com.argama147.mylibrary;

public class MyClass {
    public String getWord() {
        return "test";
    }
}

View -> Tool Windows -> Gradleを選択します。

Android5.png
Gradleウィンドウで、myLibrary -> Tasks -> buildにあるjarをダブルクリックします。
するとプロジェクトディレクトリ/myLibrary/build/libs/にmyLibrary.jarが作成されます。

作成されたライブラリの中身を確認

Jarファイルはいくつかのコマンドを使用することで逆アセンブルできますが、http://java-decompiler.github.io/ のJD-GUIというツールを使用すれば簡単に中身を確認することができます。

jd_gui.png

Qt/Androidアプリ作成

Qt CreatorでQt Quickアプリを作成します。サンプルはGitHubに格納してあります。

Qt1.png
プロジェクトテンプレートでQt Quickアプリを作成します。

Android用の設定

プロジェクトファイル

UsrJar.pro
QT += quick androidextras

プロジェクトファイルにandroidextrasを追加します。

Android固有ファイルを追加

Qt2.png

プロジェクト -> Build Android APK -> Application にあるCreate Templatesボタンを押下します。
すると、プロジェクトディレクトリ直下にandroidディレクトリが作成され、AndroidManifest.xml等のファイルが作成されます。

Jarファイルのコピー

Jarファイルは$ANDROID_PACKAGE_SOURCE_DIR/libs下に格納すると認識されます。先程のCreate Templatesの操作で、プロジェクトファイルに

UsrJar.pro
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android

のように追加されていますので、プロジェクトディレクトリ/android/下にlibsディレクトリを作成し、Android Studioで作成したmyLibrary.jarをコピーします。

QMLコードを改造

Javaクラスで取得した文字列を画面に表示したい為、main.qmlを次のように改造します。

main.qml
import QtQuick 2.15;
import QtQuick.Controls 2.15;
import QtQuick.Layouts 1.15;

ApplicationWindow {
    id: window
    visible: true

    header: ToolBar {
        RowLayout {
            id: rowlayout
            anchors.fill: parent
            Label {
                text: "JarSample"
                font.pixelSize: 20
                color: "white"

                anchors.right: menu.right
                anchors.left: parent.left
                Layout.alignment: Qt.AlignTop | Qt.AlignBottom
                horizontalAlignment: Qt.AlignHCenter
                verticalAlignment: Qt.AlignVCenter
                Layout.fillWidth: true
                Layout.fillHeight: true
                background: Rectangle {
                    gradient: Gradient {
                        orientation: Gradient.Horizontal
                        GradientStop { position: 0.0; color: "lightsteelblue" }
                        GradientStop { position: 1.0; color: "blue" }
                    }
                }
            }
        }
    }

    StackView {
        id: stackView
        anchors.fill: parent
        initialItem: Pane {
            id: pane
            RowLayout {
                anchors.fill: parent
                Label {
                    objectName: "resultText"
                    horizontalAlignment: Text.AlignLeft
                    verticalAlignment: Text.AlignTop
                    wrapMode: Label.Wrap
                    Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
                }
            }
        }
    }
}

「anchors.fill: parent」の部分で、
QML_M16error.png
のようにM16エラーが出ていますが、動作には問題ありません。MinGWやMSVCコンパイラではエラーが出ない為、Androidコンパイラ固有の問題のようです。
この問題についてはQTBUG-89519で扱っています(QTCREATORBUG-24232で報告したらQTBUG-89519のreopenの形になった)。

C++からJavaクラスを使用する

C++からJNI経由でJavaクラスを使用するコードを追加します。

main.cpp
    // Create MyClass Class Instance
    QAndroidJniObject *instance = new QAndroidJniObject("com/argama147/mylibrary/MyClass");
    // Call Method
    QAndroidJniObject ret = instance->callObjectMethod("getWord","()Ljava/lang/String;");
    QString str = ret.toString();
    qDebug() << "ret" << str;
    delete instance;

    // Update Property
    QObject* root = engine.rootObjects().first();
    QQuickItem *resultText = root->findChild<QQuickItem *>("resultText");
    resultText->setProperty("text", str);

QAndroidJniObjectでJavaのcom.argama147.mylibrary.MyClassクラスを生成し、callObjectMethod()でgetWord()メソッドを呼び出しています。取得した文字列を「resultText」に渡しています。

実行結果

execute.png
getWord()から取得した「test」が画面に表示されました。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?