From 0584401410a7807bf2b6378a19cad6a4db641289 Mon Sep 17 00:00:00 2001 From: FalsinSoft Date: Mon, 14 Jan 2019 21:52:21 +0100 Subject: [PATCH] Demo app completed --- QtAndroidToolsDemo/Main.cpp | 4 +- QtAndroidToolsDemo/Main.qml | 8 +- QtAndroidToolsDemo/QtAndroidToolsDemo.pro | 12 +- .../{QmlFiles.qrc => Sources.qrc} | 0 .../android/AndroidManifest.xml | 3 + QtAndroidToolsDemo/android/build.gradle | 2 +- QtAndroidToolsDemo/images/correct.svg | 7 + QtAndroidToolsDemo/images/error.svg | 7 + QtAndroidToolsDemo/images/unknown.svg | 19 ++ .../tools/AndroidApkExpansionFiles.qml | 169 ++++++++++++++++++ .../tools/AndroidAppPermissions.qml | 140 +++++++++++++++ 11 files changed, 358 insertions(+), 13 deletions(-) rename QtAndroidToolsDemo/{QmlFiles.qrc => Sources.qrc} (100%) create mode 100644 QtAndroidToolsDemo/images/correct.svg create mode 100644 QtAndroidToolsDemo/images/error.svg create mode 100644 QtAndroidToolsDemo/images/unknown.svg diff --git a/QtAndroidToolsDemo/Main.cpp b/QtAndroidToolsDemo/Main.cpp index 139df9d..28e7c70 100644 --- a/QtAndroidToolsDemo/Main.cpp +++ b/QtAndroidToolsDemo/Main.cpp @@ -11,9 +11,9 @@ int main(int argc, char *argv[]) QIcon::setThemeName("tools"); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; - +#ifdef Q_OS_ANDROID QtAndroidTools::InitializeQmlTools(); - +#endif engine.load(QUrl(QStringLiteral("qrc:/Main.qml"))); if(engine.rootObjects().isEmpty()) return -1; diff --git a/QtAndroidToolsDemo/Main.qml b/QtAndroidToolsDemo/Main.qml index be72e1a..255ffd4 100644 --- a/QtAndroidToolsDemo/Main.qml +++ b/QtAndroidToolsDemo/Main.qml @@ -101,12 +101,11 @@ ApplicationWindow { Image { id: logo - width: pane.availableWidth / 2 - height: pane.availableHeight / 2 + width: pane.availableWidth / 3 anchors.centerIn: parent anchors.verticalCenterOffset: -50 fillMode: Image.PreserveAspectFit - source: "images/logo_falsinsoft.jpg" + source: "qrc:/images/logo_falsinsoft.jpg" } Label { @@ -130,9 +129,10 @@ ApplicationWindow { x: (window.width - width) / 2 y: window.height / 6 width: Math.min(window.width, window.height) / 3 * 2 - contentHeight: aboutColumn.height + contentHeight: copyrightLabel.height Label { + id: copyrightLabel width: aboutDialog.availableWidth text: "Copyright (c) 2018 Fabio Falsini\n\n" + "https://falsinsoft.blogspot.com" diff --git a/QtAndroidToolsDemo/QtAndroidToolsDemo.pro b/QtAndroidToolsDemo/QtAndroidToolsDemo.pro index 7e4522e..0644c1c 100644 --- a/QtAndroidToolsDemo/QtAndroidToolsDemo.pro +++ b/QtAndroidToolsDemo/QtAndroidToolsDemo.pro @@ -1,4 +1,4 @@ -QT += quick quickcontrols2 +QT += quick quickcontrols2 svg CONFIG += c++11 TARGET = QtAndroidToolsDemo @@ -8,18 +8,18 @@ SOURCES += \ Main.cpp RESOURCES += \ - QmlFiles.qrc \ + Sources.qrc \ qtquickcontrols2.conf \ icons/tools/index.theme \ $$files(icons/*.png, true) \ - $$files(images/*.jpg) + $$files(images/*.jpg) \ + $$files(images/*.svg) -DISTFILES += \ +OTHER_FILES += \ android/AndroidManifest.xml \ android/build.gradle -android -{ +android { ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android include(../QtAndroidTools/QtAndroidTools.pri) } diff --git a/QtAndroidToolsDemo/QmlFiles.qrc b/QtAndroidToolsDemo/Sources.qrc similarity index 100% rename from QtAndroidToolsDemo/QmlFiles.qrc rename to QtAndroidToolsDemo/Sources.qrc diff --git a/QtAndroidToolsDemo/android/AndroidManifest.xml b/QtAndroidToolsDemo/android/AndroidManifest.xml index dcae779..e01adfd 100644 --- a/QtAndroidToolsDemo/android/AndroidManifest.xml +++ b/QtAndroidToolsDemo/android/AndroidManifest.xml @@ -87,4 +87,7 @@ + + + diff --git a/QtAndroidToolsDemo/android/build.gradle b/QtAndroidToolsDemo/android/build.gradle index d29c709..f08069c 100644 --- a/QtAndroidToolsDemo/android/build.gradle +++ b/QtAndroidToolsDemo/android/build.gradle @@ -18,7 +18,7 @@ apply plugin: 'com.android.application' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:support-v4:24.+' + implementation 'com.android.support:support-v4:26.+' } android { diff --git a/QtAndroidToolsDemo/images/correct.svg b/QtAndroidToolsDemo/images/correct.svg new file mode 100644 index 0000000..4aae058 --- /dev/null +++ b/QtAndroidToolsDemo/images/correct.svg @@ -0,0 +1,7 @@ + + + + diff --git a/QtAndroidToolsDemo/images/error.svg b/QtAndroidToolsDemo/images/error.svg new file mode 100644 index 0000000..c8dee8f --- /dev/null +++ b/QtAndroidToolsDemo/images/error.svg @@ -0,0 +1,7 @@ + + + + diff --git a/QtAndroidToolsDemo/images/unknown.svg b/QtAndroidToolsDemo/images/unknown.svg new file mode 100644 index 0000000..4a4f085 --- /dev/null +++ b/QtAndroidToolsDemo/images/unknown.svg @@ -0,0 +1,19 @@ + + + + + diff --git a/QtAndroidToolsDemo/tools/AndroidApkExpansionFiles.qml b/QtAndroidToolsDemo/tools/AndroidApkExpansionFiles.qml index 81f0640..b2dde06 100644 --- a/QtAndroidToolsDemo/tools/AndroidApkExpansionFiles.qml +++ b/QtAndroidToolsDemo/tools/AndroidApkExpansionFiles.qml @@ -1,9 +1,178 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 +import QtQuick.Dialogs 1.3 +import QtAndroidTools.ApkExpansionFiles 1.0 Page { id: page + function downloadInProgress(downloading) + { + buttonStartDownload.enabled = !downloading; + buttonPauseDownload.enabled = downloading; + buttonContinueDownload.enabled = downloading; + buttonAbortDownload.enabled = downloading; + } + function downloadFiles() + { + QtAndroidApkExpansionFiles.base64PublicKey = ""; + QtAndroidApkExpansionFiles.salt = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]; + QtAndroidApkExpansionFiles.main.version = 1; + QtAndroidApkExpansionFiles.main.size = 123456789; + QtAndroidApkExpansionFiles.patch.version = 1; + QtAndroidApkExpansionFiles.patch.size = 123456789; + + if(QtAndroidApkExpansionFiles.base64PublicKey === "") + { + errorMessageBox.text = "Invalid base64PublicKey"; + errorMessageBox.open(); + return; + } + + switch(QtAndroidApkExpansionFiles.startDownloadFiles()) + { + case QtAndroidApkExpansionFiles.APKEF_NO_DOWNLOAD_REQUIRED: + fileDeliveredMessageBox.open(); + break; + case QtAndroidApkExpansionFiles.APKEF_DOWNLOAD_STARTED: + case QtAndroidApkExpansionFiles.APKEF_LVL_CHECK_REQUIRED: + page.downloadInProgress(true); + break; + case QtAndroidApkExpansionFiles.APKEF_STORAGE_READ_PERMISSION_REQUIRED: + case QtAndroidApkExpansionFiles.APKEF_STORAGE_WRITE_PERMISSION_REQUIRED: + errorMessageBox.text = "Without storage access permission the app can not download expansion files"; + errorMessageBox.open(); + page.downloadInProgress(false); + break; + default: + errorMessageBox.text = "Sorry, unknown error happened"; + errorMessageBox.open(); + page.downloadInProgress(false); + break; + } + } + + Connections { + target: QtAndroidApkExpansionFiles + onDownloadStateChanged: { + switch(newState) + { + case QtAndroidApkExpansionFiles.STATE_COMPLETED: + fileDeliveredMessageBox.open(); + page.downloadInProgress(false); + break; + case QtAndroidApkExpansionFiles.STATE_FAILED_UNLICENSED: + case QtAndroidApkExpansionFiles.STATE_FAILED_FETCHING_URL: + case QtAndroidApkExpansionFiles.STATE_FAILED_SDCARD_FULL: + case QtAndroidApkExpansionFiles.STATE_FAILED_CANCELED: + case QtAndroidApkExpansionFiles.STATE_FAILED: + errorMessageBox.text = QtAndroidApkExpansionFiles.getString(newState-1); + errorMessageBox.open(); + page.downloadInProgress(false); + break; + } + downloadStateLabel.text = QtAndroidApkExpansionFiles.getString(newState-1); + } + onDownloadProgress: { + var time = new Date(timeRemaining); + downloadProgressBar.to = overallTotal; + downloadProgressBar.value = overallProgress; + downloadSizeLabel.text = (overallProgress / (1024*1024)).toFixed(2) + "MB/" + (overallTotal / (1024*1024)).toFixed(2) + "MB"; + downloadTimeLabel.text = "Time left: "; + if(timeRemaining > 1000 * 60 * 60) + downloadTimeLabel.text += ("0" + time.getHours()).substr(-2) + ":" + ("0" + time.getMinutes()).substr(-2); + else + downloadTimeLabel.text += ("0" + time.getMinutes()).substr(-2) + ":" + ("0" + time.getSeconds()).substr(-2); + } + } + + Column { + width: parent.width * 0.9 + height: parent.height * 0.9 + anchors.centerIn: parent + spacing: 20 + + Label { + width: parent.width + text: "Download apk expansion files" + horizontalAlignment: Text.AlignHCenter + wrapMode: Label.Wrap + font.pixelSize: 14 + font.bold: true + } + + ProgressBar { + id: downloadProgressBar + width: parent.width * 0.85 + anchors.horizontalCenter: parent.horizontalCenter + from: 0 + } + + Label { + id: downloadStateLabel + width: parent.width + horizontalAlignment: Text.AlignHCenter + wrapMode: Label.Wrap + font.pixelSize: 15 + } + + Button { + id: buttonStartDownload + anchors.horizontalCenter: parent.horizontalCenter + text: "Start download" + onClicked: page.downloadFiles() + } + Button { + id: buttonPauseDownload + enabled: false + anchors.horizontalCenter: parent.horizontalCenter + text: "Pause download" + onClicked: QtAndroidApkExpansionFiles.pauseDownload() + } + Button { + id: buttonContinueDownload + enabled: false + anchors.horizontalCenter: parent.horizontalCenter + text: "Continue download" + onClicked: QtAndroidApkExpansionFiles.continueDownload() + } + Button { + id: buttonAbortDownload + enabled: false + anchors.horizontalCenter: parent.horizontalCenter + text: "Abort download" + onClicked: QtAndroidApkExpansionFiles.abortDownload() + } + + Label { + id: downloadSizeLabel + width: parent.width + anchors.left: parent.left + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 14 + fontSizeMode: Text.Fit + } + Label { + id: downloadTimeLabel + width: parent.width + anchors.right: parent.right + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 14 + fontSizeMode: Text.Fit + } + } + + MessageDialog { + id: errorMessageBox + standardButtons: StandardButton.Ok + title: "Error" + } + MessageDialog { + id: fileDeliveredMessageBox + standardButtons: StandardButton.Ok + title: "Advise" + text: "Apk expension files available:\n" + QtAndroidApkExpansionFiles.mainFileName() + "\n" + QtAndroidApkExpansionFiles.patchFileName() + } } diff --git a/QtAndroidToolsDemo/tools/AndroidAppPermissions.qml b/QtAndroidToolsDemo/tools/AndroidAppPermissions.qml index 81f0640..ecf83de 100644 --- a/QtAndroidToolsDemo/tools/AndroidAppPermissions.qml +++ b/QtAndroidToolsDemo/tools/AndroidAppPermissions.qml @@ -1,9 +1,149 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 +import QtQuick.Dialogs 1.3 +import QtAndroidTools.AppPermissions 1.0 Page { id: page + readonly property var permissionsNameList: ["android.permission.WRITE_EXTERNAL_STORAGE","android.permission.READ_CALENDAR","android.permission.READ_PHONE_STATE","android.permission.READ_CONTACTS"] + function setPermissionGranted(name, granted) + { + for(var i = 0; i < appPermissionModel.count; i++) + { + if(appPermissionModel.get(i).name === name) + { + appPermissionModel.get(i).symbol = granted ? "qrc:/images/correct.svg" : "qrc:/images/error.svg"; + break; + } + } + } + + Connections { + target: QtAndroidAppPermissions + onRequestPermissionsResults: { + for(var i = 0; i < results.length; i++) + { + if(results[i].granted === true) + { + setPermissionGranted(results[i].name, true); + } + else + { + if(QtAndroidAppPermissions.shouldShowRequestPermissionInfo(results[i].name) === true) + { + if(results[i].name === permissionsNameList[0]) + requestPermissionWRITE_EXTERNAL_STORAGE.open(); + else if(results[i].name === permissionsNameList[1]) + requestPermissionREAD_CALENDAR.open(); + else if(results[i].name === permissionsNameList[2]) + requestPermissionREAD_PHONE_STATE.open(); + else if(results[i].name === permissionsNameList[3]) + requestPermissionREAD_CONTACTS.open(); + } + else + { + setPermissionGranted(results[i].name, false); + } + } + } + } + } + + ListModel { + id: appPermissionModel + ListElement { + name: "android.permission.WRITE_EXTERNAL_STORAGE" + symbol: "qrc:/images/unknown.svg" + } + ListElement { + name: "android.permission.READ_CALENDAR" + symbol: "qrc:/images/unknown.svg" + } + ListElement { + name: "android.permission.READ_PHONE_STATE" + symbol: "qrc:/images/unknown.svg" + } + ListElement { + name: "android.permission.READ_CONTACTS" + symbol: "qrc:/images/unknown.svg" + } + } + + Column { + width: parent.width * 0.9 + height: parent.height * 0.9 + anchors.centerIn: parent + spacing: 20 + + Repeater { + model: appPermissionModel + Rectangle { + width: parent.width + height: premissionStatus.height + 20 + border.width: 1 + border.color: "gray" + radius: 15 + + Item { + width: parent.width * 0.9 + height: premissionStatus.height + anchors.centerIn: parent + + Image { + id: premissionStatus + anchors.left: parent.left + fillMode: Image.PreserveAspectFit + source: symbol + sourceSize.height: permissionName.contentHeight * 1.5 + } + Text { + id: permissionName + width: parent.width - premissionStatus.width - 10 + anchors.right: parent.right + text: name + font.pixelSize: parent.width * 0.04 + verticalAlignment: Text.AlignVCenter + } + } + } + } + + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: "Request permissions" + onClicked: QtAndroidAppPermissions.requestPermissions(permissionsNameList) + } + } + + MessageDialog { + id: requestPermissionWRITE_EXTERNAL_STORAGE + standardButtons: StandardButton.Ok + title: "Advise" + text: "This app require WRITE_EXTERNAL_STORAGE permission for bla bla bla..." + onAccepted: QtAndroidAppPermissions.requestPermission(permissionsNameList[0]) + } + MessageDialog { + id: requestPermissionREAD_CALENDAR + standardButtons: StandardButton.Ok + title: "Advise" + text: "This app require READ_CALENDAR permission for bla bla bla..." + onAccepted: QtAndroidAppPermissions.requestPermission(permissionsNameList[1]) + } + MessageDialog { + id: requestPermissionREAD_PHONE_STATE + standardButtons: StandardButton.Ok + title: "Advise" + text: "This app require READ_PHONE_STATE permission for bla bla bla..." + onAccepted: QtAndroidAppPermissions.requestPermission(permissionsNameList[2]) + } + MessageDialog { + id: requestPermissionREAD_CONTACTS + standardButtons: StandardButton.Ok + title: "Advise" + text: "This app require READ_CONTACTS permission for bla bla bla..." + onAccepted: QtAndroidAppPermissions.requestPermission(permissionsNameList[3]) + } }