aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAssam Boudjelthia <assam.boudjelthia@qt.io>2020-05-07 12:49:24 +0300
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2020-05-25 16:20:27 +0000
commit73684040207ce0cbb782dda5dc27cb8ac71243b3 (patch)
tree26c5d5af88b75454156d5cb761bdf31e4350dafd
parent174da8f65245ae4f9333dc169d60fbdf3003f1ea (diff)
Add example to demonstrate working with custom Java objects/ArrayList
An example that retrieves music data from Java APIs, and store that in a Java ArrayList of objects. Then, how to pass that data to Qt via C++ and QML. Task-number: QTBUG-83038 Change-Id: I5201572b997973388c688ca0d3f2f30240da12f6 Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io> (cherry picked from commit 8ebbdcc7c4a0c2c6f863060500136b9399eccf98) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--examples/androidextras/androidextras.pro6
-rw-r--r--examples/androidextras/musiclist/android/AndroidManifest.xml84
-rw-r--r--examples/androidextras/musiclist/android/src/org/qtproject/example/musiclist/MusicList.java113
-rw-r--r--examples/androidextras/musiclist/doc/src/qtandroidextras-example-musiclist.qdoc128
-rw-r--r--examples/androidextras/musiclist/main.cpp93
-rw-r--r--examples/androidextras/musiclist/main.qml122
-rw-r--r--examples/androidextras/musiclist/musiclist.cpp75
-rw-r--r--examples/androidextras/musiclist/musiclist.h88
-rw-r--r--examples/androidextras/musiclist/musiclist.pro23
-rw-r--r--examples/androidextras/musiclist/qml.qrc5
-rw-r--r--src/androidextras/doc/images/musiclist.pngbin0 -> 15406 bytes
-rw-r--r--src/androidextras/doc/qtandroidextras.qdocconf2
12 files changed, 736 insertions, 3 deletions
diff --git a/examples/androidextras/androidextras.pro b/examples/androidextras/androidextras.pro
index 4ac3b2d..169797a 100644
--- a/examples/androidextras/androidextras.pro
+++ b/examples/androidextras/androidextras.pro
@@ -6,12 +6,14 @@ android {
notification \
jnimessenger \
services \
- customactivity
+ customactivity \
+ musiclist
EXAMPLE_FILES += \
notification \
jnimessenger \
services \
- customactivity
+ customactivity \
+ musiclist
}
}
diff --git a/examples/androidextras/musiclist/android/AndroidManifest.xml b/examples/androidextras/musiclist/android/AndroidManifest.xml
new file mode 100644
index 0000000..051fbaa
--- /dev/null
+++ b/examples/androidextras/musiclist/android/AndroidManifest.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<manifest package="org.qtproject.example.musiclist" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto">
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
+
+ <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
+ Remove the comment if you do not require these default permissions. -->
+ <!-- %%INSERT_PERMISSIONS -->
+
+ <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
+ Remove the comment if you do not require these default features. -->
+ <!-- %%INSERT_FEATURES -->
+
+ <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
+
+ <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:extractNativeLibs="true">
+ <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+
+ <!-- Application arguments -->
+ <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
+ <!-- Application arguments -->
+
+ <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
+ <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
+ <meta-data android:name="android.app.repository" android:value="default"/>
+ <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
+ <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
+ <!-- Deploy Qt libs as part of package -->
+ <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
+
+ <!-- Run with local libs -->
+ <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
+ <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
+ <meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/>
+ <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
+ <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
+ <!-- Used to specify custom system library path to run with local system libs -->
+ <!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> -->
+ <!-- Messages maps -->
+ <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
+ <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
+ <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
+ <meta-data android:value="@string/unsupported_android_version" android:name="android.app.unsupported_android_version"/>
+ <!-- Messages maps -->
+
+ <!-- Splash screen -->
+ <!-- Orientation-specific (portrait/landscape) data is checked first. If not available for current orientation,
+ then android.app.splash_screen_drawable. For best results, use together with splash_screen_sticky and
+ use hideSplashScreen() with a fade-out animation from Qt Android Extras to hide the splash screen when you
+ are done populating your window with content. -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/logo_portrait" / -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/logo_landscape" / -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
+ <!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
+ <!-- Splash screen -->
+
+ <!-- Background running -->
+ <!-- Warning: changing this value to true may cause unexpected crashes if the
+ application still try to draw after
+ "applicationStateChanged(Qt::ApplicationSuspended)"
+ signal is sent! -->
+ <meta-data android:name="android.app.background_running" android:value="false"/>
+ <!-- Background running -->
+
+ <!-- auto screen scale factor -->
+ <meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
+ <!-- auto screen scale factor -->
+
+ <!-- extract android style -->
+ <!-- available android:values :
+ * default - In most cases this will be the same as "full", but it can also be something else if needed, e.g., for compatibility reasons
+ * full - useful QWidget & Quick Controls 1 apps
+ * minimal - useful for Quick Controls 2 apps, it is much faster than "full"
+ * none - useful for apps that don't use any of the above Qt modules
+ -->
+ <meta-data android:name="android.app.extract_android_style" android:value="minimal"/>
+ <!-- extract android style -->
+ </activity>
+ </application>
+
+</manifest>
diff --git a/examples/androidextras/musiclist/android/src/org/qtproject/example/musiclist/MusicList.java b/examples/androidextras/musiclist/android/src/org/qtproject/example/musiclist/MusicList.java
new file mode 100644
index 0000000..d4dc840
--- /dev/null
+++ b/examples/androidextras/musiclist/android/src/org/qtproject/example/musiclist/MusicList.java
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.example.musiclist;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.MediaStore;
+import java.util.ArrayList;
+
+public class MusicList {
+
+ static ArrayList<MusicTrack> fetchMusicList(Context context) {
+ ArrayList<MusicTrack> musicList = new ArrayList<MusicTrack>();
+ Cursor songCursor;
+
+ try {
+ ContentResolver contentResolver = context.getContentResolver();
+ Uri songUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+ songCursor = contentResolver.query(songUri, null, null, null, null);
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ return musicList;
+ }
+
+ if (songCursor != null && songCursor.moveToFirst())
+ {
+ int title = songCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE);
+ int artist = songCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST);
+ int duration = duration = songCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION);
+
+ do {
+ String currentTitle = songCursor.getString(title);
+ String currentArtist = songCursor.getString(artist);
+ long currentDuration = songCursor.getLong(duration);
+ musicList.add(new MusicTrack(currentTitle, currentArtist, currentDuration));
+ } while (songCursor.moveToNext());
+ }
+
+ if (songCursor != null)
+ songCursor.close();
+
+ return musicList;
+ }
+}
+
+class MusicTrack {
+
+ private String title;
+ private String artist;
+ private long duration;
+
+ MusicTrack (String title, String artist, long duration) {
+ this.title = title;
+ this.artist = artist;
+ this.duration = duration;
+ }
+
+ public String getTitle() { return title; }
+
+ public String getArtist() { return artist; }
+
+ public long getDuration() { return duration; }
+}
diff --git a/examples/androidextras/musiclist/doc/src/qtandroidextras-example-musiclist.qdoc b/examples/androidextras/musiclist/doc/src/qtandroidextras-example-musiclist.qdoc
new file mode 100644
index 0000000..39efb6a
--- /dev/null
+++ b/examples/androidextras/musiclist/doc/src/qtandroidextras-example-musiclist.qdoc
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\title Qt JNI Music List
+ \ingroup examples-qtandroidextras
+ \example musiclist
+ \brief Demonstrates how to exchange data from complex Java objects.
+
+ \image musiclist.png
+
+ This example demonstrates how to move around data from a Java ArrayList of
+ objects over to Qt. The example uses Android APIs to retrieve a list of music
+ tracks, and displays some information about them with QML.
+
+ When the application starts, it displays a list of music tracks, showing the
+ track name, artist, and duration.
+
+ \include examples-run.qdocinc
+
+ \section1 Create the Music Classes
+
+ Let's create a Java class, \c MusicTrack, that defines some of the basic
+ information about a track. In the Java side, create the following:
+
+ \quotefromfile musiclist/android/src/org/qtproject/example/musiclist/MusicList.java
+ \skipto class MusicTrack
+ \printuntil /^\}/
+
+ Create another class with the same variables or information on the C++ side.
+ The definition for \c MusicTrack class is the following:
+
+ \quotefromfile musiclist/musiclist.h
+ \skipto class MusicTrack
+ \printuntil };
+
+ \note The \c MusicTrack class must be a \l{QObject}-derived class to be used
+ with as a QML context property. For more information, see
+ \l{Overview - QML and C++ Integration}{QML and C++ Integration}.
+
+ \section1 Fetch the Music List
+
+ To retrieve the music list, the Android APIs are used. Add the following method
+ to find music tracks that are available on the system. This method returns
+ an ArrayList of \c MusicTrack.
+
+ \quotefromfile musiclist/android/src/org/qtproject/example/musiclist/MusicList.java
+ \skipto package
+ \printuntil /^\ {4}\}/
+ \printline }
+
+ Using the JNI helpers provided with Qt, call the previous method to
+ first get an \l{QAndroidJniObject} containing an ArrayList of objects. In the
+ C++ code, you need to go through the Java ArrayList and create a parallel list
+ on C++. Add the following lines to do that:
+
+ \quotefromfile musiclist/musiclist.cpp
+ \skipto QAndroidJniObject
+ \printuntil /^\ {4}\}/
+
+ Then, add a function to return the resulted \l{QList}:
+
+ \quotefromfile musiclist/musiclist.cpp
+ \skipto MusicList::assembledMusicList
+ \printuntil }
+
+ To display the music list, create a \l{ListView} that uses the \l{QList}
+ as a property. Register the property as follows:
+
+ \quotefromfile musiclist/main.cpp
+ \skipto MusicList
+ \printuntil assembledMusicList
+
+ In the QML code, define the model of the \l{ListView} as follows:
+
+ \quotefromfile musiclist/main.qml
+ \skipto model
+ \printline model
+
+ \sa {Qt for Android}, {Qt Android Extras}
+*/
diff --git a/examples/androidextras/musiclist/main.cpp b/examples/androidextras/musiclist/main.cpp
new file mode 100644
index 0000000..0c76cc2
--- /dev/null
+++ b/examples/androidextras/musiclist/main.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "musiclist.h"
+
+#include <QtAndroid>
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QQmlContext>
+
+bool requestStoragePermission() {
+ using namespace QtAndroid;
+
+ QString permission = QStringLiteral("android.permission.WRITE_EXTERNAL_STORAGE");
+ const QHash<QString, PermissionResult> results = requestPermissionsSync(QStringList({permission}));
+ if (!results.contains(permission) || results[permission] == PermissionResult::Denied) {
+ qWarning() << "Couldn't get permission: " << permission;
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+ QQmlApplicationEngine engine;
+ const QUrl url(QStringLiteral("qrc:/main.qml"));
+
+ if (!requestStoragePermission())
+ qDebug() << "Storage permissions denied. This example might not work as intended";
+
+ MusicList *musicList = new MusicList(&app);
+ engine.rootContext()->setContextProperty(QLatin1String("musiclist"),
+ QVariant::fromValue(musicList->assembledMusicList()));
+
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
+ &app, [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+ engine.load(url);
+
+ return app.exec();
+}
diff --git a/examples/androidextras/musiclist/main.qml b/examples/androidextras/musiclist/main.qml
new file mode 100644
index 0000000..6a04bef
--- /dev/null
+++ b/examples/androidextras/musiclist/main.qml
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.14
+import QtQuick.Window 2.14
+import QtQuick.Controls 2.14
+
+Window {
+ id: window
+ visible: true
+ width: 640
+ height: 480
+ title: qsTr("Qt Android Music List")
+
+ Text {
+ id: resultText
+ height: 40
+ text: "Music library list:"
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ font.pointSize: 20
+ verticalAlignment: Text.AlignTop
+ }
+
+ ToolSeparator {
+ id: toolSeparator
+ width: parent.width
+ anchors.bottom: listView.top
+ anchors.bottomMargin: 10
+ anchors.top: resultText.bottom
+ anchors.topMargin: 6
+ anchors.horizontalCenter: parent.horizontalCenter
+ orientation: Qt.Horizontal
+ }
+
+ ListView {
+ id: listView
+ width: parent.width
+ clip: true
+ flickableDirection: Flickable.HorizontalAndVerticalFlick
+ anchors.bottomMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.top: resultText.bottom
+ anchors.topMargin: 30
+ anchors.bottom: parent.bottom
+
+ model: musiclist
+ delegate: Rectangle {
+ height: 25
+ width: ListView.view.width
+ color: index % 2 == 0 ? "#EDEDED" : "#FFFFFF"
+
+ function toTimeFormat(sec_num) {
+ sec_num = Math.floor(sec_num / 1000);
+ var hours = Math.floor(sec_num / 3600);
+ var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
+ var seconds = sec_num - (hours * 3600) - (minutes * 60);
+
+ if (hours < 10) { hours = "0" + hours; }
+ if (minutes < 10) { minutes = "0" + minutes; }
+ if (seconds < 10) { seconds = "0" + seconds; }
+
+ return hours+':'+minutes+':'+seconds;
+ }
+
+ Text { text: model.modelData.title + " | " + model.modelData.artist + " | " + toTimeFormat(model.modelData.duration) }
+ }
+ }
+}
diff --git a/examples/androidextras/musiclist/musiclist.cpp b/examples/androidextras/musiclist/musiclist.cpp
new file mode 100644
index 0000000..97d5cdb
--- /dev/null
+++ b/examples/androidextras/musiclist/musiclist.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "musiclist.h"
+
+#include <QAndroidIntent>
+#include <QAndroidJniEnvironment>
+
+MusicList::MusicList(QObject *parent) : QObject(parent)
+{
+ QAndroidJniObject musicList = QAndroidJniObject::callStaticObjectMethod(
+ "org/qtproject/example/musiclist/MusicList",
+ "fetchMusicList",
+ "(Landroid/content/Context;)Ljava/util/ArrayList;",
+ QtAndroid::androidContext().object());
+
+ for (int i = 0; i < musicList.callMethod<jint>("size"); ++i) {
+ QAndroidJniObject track = musicList.callObjectMethod("get", "(I)Ljava/lang/Object;", i);
+ const QString title = track.callObjectMethod("getTitle", "()Ljava/lang/String;").toString();
+ const QString artist = track.callObjectMethod("getArtist", "()Ljava/lang/String;").toString();
+ const long duration = track.callMethod<jlong>("getDuration");
+ m_assembledMusicList.append(new MusicTrack(title, artist, duration, this));
+ }
+}
+
+QList<MusicTrack *> MusicList::assembledMusicList() const
+{
+ return m_assembledMusicList;
+}
diff --git a/examples/androidextras/musiclist/musiclist.h b/examples/androidextras/musiclist/musiclist.h
new file mode 100644
index 0000000..14d487f
--- /dev/null
+++ b/examples/androidextras/musiclist/musiclist.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MUSICLIST_H
+#define MUSICLIST_H
+
+#include <QtAndroid>
+
+class MusicTrack : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString title READ title CONSTANT)
+ Q_PROPERTY(QString artist READ artist CONSTANT)
+ Q_PROPERTY(long duration READ duration CONSTANT)
+
+public:
+ MusicTrack(const QString title, const QString artist, const long duration, QObject *parent = nullptr)
+ : QObject(parent), m_title(title), m_artist(artist), m_duration(duration) {}
+
+ QString title() const { return m_title; }
+ QString artist() const { return m_artist; }
+ long duration() const { return m_duration; }
+
+private:
+ QString m_title;
+ QString m_artist;
+ long m_duration;
+};
+
+class MusicList : public QObject
+{
+ Q_OBJECT
+
+public:
+ MusicList(QObject *parent = nullptr);
+ QList<MusicTrack *> assembledMusicList() const;
+
+private:
+ QList<MusicTrack *> m_assembledMusicList;
+};
+
+#endif
diff --git a/examples/androidextras/musiclist/musiclist.pro b/examples/androidextras/musiclist/musiclist.pro
new file mode 100644
index 0000000..0d20de8
--- /dev/null
+++ b/examples/androidextras/musiclist/musiclist.pro
@@ -0,0 +1,23 @@
+QT += quick androidextras
+
+CONFIG += c++11
+
+DEFINES += QT_DEPRECATED_WARNINGS
+
+HEADERS += \
+ musiclist.h
+
+SOURCES += \
+ main.cpp \
+ musiclist.cpp
+
+RESOURCES += qml.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/androidextras/musiclist
+INSTALLS += target
+
+ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
+
+DISTFILES += \
+ android/AndroidManifest.xml \
+ android/src/org/qtproject/example/musiclist/MusicList.java
diff --git a/examples/androidextras/musiclist/qml.qrc b/examples/androidextras/musiclist/qml.qrc
new file mode 100644
index 0000000..5f6483a
--- /dev/null
+++ b/examples/androidextras/musiclist/qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/androidextras/doc/images/musiclist.png b/src/androidextras/doc/images/musiclist.png
new file mode 100644
index 0000000..cc37613
--- /dev/null
+++ b/src/androidextras/doc/images/musiclist.png
Binary files differ
diff --git a/src/androidextras/doc/qtandroidextras.qdocconf b/src/androidextras/doc/qtandroidextras.qdocconf
index afeb5da..0f1ce43 100644
--- a/src/androidextras/doc/qtandroidextras.qdocconf
+++ b/src/androidextras/doc/qtandroidextras.qdocconf
@@ -37,7 +37,7 @@ qhp.QtAndroidExtras.subprojects.examples.title = Examples
qhp.QtAndroidExtras.subprojects.examples.indexTitle = Qt Android Extras Examples
qhp.QtAndroidExtras.subprojects.examples.selectors = fake:example
-depends += qtcore qtdoc qtqml
+depends += qtcore qtdoc qtqml qtquick
headerdirs += ..
sourcedirs += ..
exampledirs += ../../../examples/androidextras \