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])
+ }
}