From 5a50ef8cbe194a72a28557c3dd645dcc677744b5 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Mon, 21 Jun 2021 16:03:42 +0200 Subject: [PATCH] Started to implement propper permission handling --- headers/bluerockbackend.h | 16 +++-- resources/qml/Components/QrCodeScanPopup.qml | 64 ++++++++++++++++- resources/translations/de.qm | Bin 5384 -> 5716 bytes resources/translations/de.ts | 34 ++++++--- resources/translations/en.qm | Bin 4923 -> 5320 bytes resources/translations/en.ts | 17 ++++- sources/bluerockbackend.cpp | 69 +++++++++++++++++++ 7 files changed, 181 insertions(+), 19 deletions(-) diff --git a/headers/bluerockbackend.h b/headers/bluerockbackend.h index fa20efe..ffbef21 100644 --- a/headers/bluerockbackend.h +++ b/headers/bluerockbackend.h @@ -35,6 +35,10 @@ #include #include "QZXing.h" +#ifdef Q_OS_ANDROID +#include +#endif + #include "shareUtils/shareutils.h" class BlueRockBackend : public QObject @@ -54,10 +58,14 @@ signals: public slots: - QVariant getWidgetData(QVariantMap params); - QVariantMap getParamsFromUrl(QString url); - void shareResultsAsUrl(QString url, QString compName); - void shareResultsAsPoster(QString url, QString compName); + Q_INVOKABLE QVariant getWidgetData(QVariantMap params); + Q_INVOKABLE QVariantMap getParamsFromUrl(QString url); + Q_INVOKABLE void shareResultsAsUrl(QString url, QString compName); + Q_INVOKABLE void shareResultsAsPoster(QString url, QString compName); + + Q_INVOKABLE bool isCameraPermissionGranted(); + Q_INVOKABLE bool requestCameraPermission(); + #if defined(Q_OS_ANDROID) void onApplicationStateChanged(Qt::ApplicationState applicationState); #endif diff --git a/resources/qml/Components/QrCodeScanPopup.qml b/resources/qml/Components/QrCodeScanPopup.qml index 12469a3..1ebc2ca 100644 --- a/resources/qml/Components/QrCodeScanPopup.qml +++ b/resources/qml/Components/QrCodeScanPopup.qml @@ -31,7 +31,10 @@ Dialog { onOpened: { setDefaultStatusText() control._freezeScanning = false - cameraLoader.sourceComponent = cameraComponent + if(serverConn.isCameraPermissionGranted()) + cameraLoader.sourceComponent = cameraComponent + else + cameraLoader.sourceComponent = noPermissionComponent } onClosed: cameraLoader.sourceComponent = null @@ -168,6 +171,65 @@ Dialog { } } + Component { + id: noPermissionComponent + Item { + anchors.fill: parent + + Label { + id: noPermissionIcon + anchors { + top: parent.top + topMargin: parent.height * 0 + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: parent.height * 0.3 + font.family: fa5solid.name + text: "\uf3ed" + } + Label { + id: noPermissionText + anchors { + top: noPermissionIcon.bottom + topMargin: noPermissionIcon.height * 0.15 + horizontalCenter: parent.horizontalCenter + } + + width: parent.width * 0.9 + + font.bold: true + font.pixelSize: noPermissionIcon.height * 0.15 + + horizontalAlignment: Text.AlignHCenter + + wrapMode: Text.Wrap + + //% "Camera permission denied!" + text: qsTrId("#cameraPermissionDenied") + } + + Label { + id: noPermissionDetailText + anchors { + top: noPermissionText.bottom + topMargin: noPermissionText.height * 0.15 + horizontalCenter: parent.horizontalCenter + } + + width: parent.width * 0.9 + + font.pixelSize: noPermissionText.font.pixelSize * 0.7 + + horizontalAlignment: Text.AlignHCenter + + wrapMode: Text.Wrap + + //% "This app requires access to your camera in order to scan QR-Codes. It will never record or store any photos or videos." + text: qsTrId("#cameraPermissionDeniedDetails") + } + + } + } QZXingFilter { id: zxingFilter diff --git a/resources/translations/de.qm b/resources/translations/de.qm index df728ad8f501ae7353e542c53fe43ed35c9308ae..0fa4d501ea2ac771a397ab35fe01665f7aa41a51 100644 GIT binary patch delta 879 zcmZ{hZAep57{~wH?%kcvZB2~`#jZ{RZAuwIeGsfkFGy0M1tP@SZhF&gw#~}*VNwf% zKBTM{jNaGV2PtEINQwwWh(ZV|iu_?`g+q;ZG+U^@Zb-n^nyDK=Q= z=xk)Pk2*R}_y`u`88Bl5;xo zhth+ldb1>Dr%XPRDUn@d@i3%)QbyLHA)5XmO;oE$pa)T?*eY_^iJxd^Cd^so&=5nM za~HpO`i6WrSqmTh2pMWWHQmN41f9wl=LpZL2r?VyPUEW7CjOR{V}U2&4{1^VCM_D$ zV=+AvZqUNI7F2}5WZ^V}W^@={D!X*^Q%R*^H<@&?O0tP41^5X#v5T{*ieAohR|)(B zs2e~L9u`pIs&o1n9sEXZGq#|b*NPa57;325K$VKUY$~pQZ=GV z5Me7S0xwJ)@iraIiM+rRRh1^X(MIHI{=7`de_p0Ri~IGi*xv`rhOAL*cCBMf`3*vc B$=3h? delta 472 zcmcbj)1fs%y1s&eY5G+L1{Mbf%>_Gw^aaK}hN%n;e6ty!_&PB#@XTh~q0GR*z@NbM z(7=>|LCAqQeBE;f2JQ#UQQ1mB`CH5}Q$8^;aP={-kx>QeyTN>j^AJ#+okc5tH&7!3 zOKGYo0|RR%OGC;`pgCeJzfypFp?X$FkhU|HIQyCZpYS=6Kn}7yAW1myW1hmJNeV!uF zAp*Ya3tt&CFbGcP&_25qsE>t1Cs_#Sj71z1bXbArI&y4SwgqUPJIBw(j~MD1cv3iT zseT1o zdjn}MKHltU&On2Y^Zs5Q3Y1^T7orAK&yviSdR7%^(Mi672bY2BpYj_?1MLx5%b%15 z)W`BA6X+YpjL8cb9hjJ}ZGOz?%*a^0S)ExKNKN);SuB{!P{feRV8fu#kjP-ipvT}c qnNdV`vJC5-$+LL4CVybvyjg*xh;6bapAVaWa%M?t?&ey)>+AqiiFsE5 diff --git a/resources/translations/de.ts b/resources/translations/de.ts index 7928105..7028d3e 100644 --- a/resources/translations/de.ts +++ b/resources/translations/de.ts @@ -5,21 +5,33 @@ + Scan QR-Code QR-Code scannen - + Place the Code in the center Positioniere den Code in der Mitte + + + Camera permission denied! + + + + + This app requires access to your camera in order to scan QR-Codes. It will never record or store any photos or videos. + This app requires access to your camera in order to scan QR-Codes. It will never record store any photos or videos. + + - + Plase wait Bitte warten - + Invalid QR-Code Ungültiger QR-Code @@ -55,9 +67,8 @@ Jetzt kaufen für - This item is currently unavailable - Diese Produkt ist nicht verfügbar + Diese Produkt ist nicht verfügbar @@ -65,17 +76,18 @@ Das ist eine premium Funktion. - + + This item is currently unavailable Diese Produkt ist nicht verfügbar - + Restore purchase Kauf wiederherstellen - + contact support Support kontaktieren @@ -100,17 +112,17 @@ Über blueROCK - + Where are the IFSC results? Wo sind die IFSC Ergebnisse? - + Unfortunately, the IFSC has restricted the access to their data and <b>is not willing to share results with blueROCK anymore</b>. Because of this, blueROCK is no longer able to access and display IFSC results.<br><br>You can find current IFSC results <a href="https://ifsc.results.info">over here</a> and on <a href="https://ifsc-climbing.org">their website</a>. Leider hat die IFSC den Zugang zu ihren Ergebnissen eingeschränkt<b>und ist nicht mehr bereit, Ergebnisse mit blueROCK zu teilen</b>. Daher ist blueROCK nicht länger in der Lage auf IFSC Ergebnisse zuzugriefen und diese anzuzeigen.<br><br>Aktuelle IFSC Ergebnisse finden sich <a href="https://ifsc.results.info">hier</a> und auf der <a href="https://ifsc-climbing.org">IFSC Webseite</a>. - + This app was built using the <a href='https://qt.io'>Qt Framework</a> licensed under the <a href='https://www.gnu.org/licenses/lgpl-3.0.en.html'>GNU lgplV3 license</a>.<br><br>This app is open source and licensed under the <a href='https://www.gnu.org/licenses/agpl-3.0.en.html'>GNU agplV3 license</a>, the source code can be found <a href='https://itsblue.dev/dorian/blueROCK/'>here</a>.<br><br>Resultservice and rankings provided by <a href='http://www.digitalROCK.de'>digital ROCK</a>. Diese App wurde unter Verwendung des <a href='https://qt.io'>Qt Frameworks</a> unter der <a href='https://www.gnu.org/licenses/lgpl-3.0.en.html'>GNU lgplV3 Lizenz</a> erstellt.<br><br>Diese App ist Open-source und lizensiert unter der <a href='https://www.gnu.org/licenses/agpl-3.0.en.html'>GNU agplV3 Lizenz</a>. Der Sourcecode findet sich <a href='https://itsblue.dev/dorian/blueROCK/'>hier</a>.Die Ergebnisse und Ranglisten werden von <a href='http://www.digitalROCK.de'>digital ROCK</a> zur Verfügung gestellt. diff --git a/resources/translations/en.qm b/resources/translations/en.qm index bbc25d29a46f63a81574d813cdfadf4c4692686b..eb94bc00ad448e5b13229611a89b96bc2510d9d3 100644 GIT binary patch delta 766 zcmZ{gT}V@59LAq*=j@z)uVr{KiKC`q=_td9N-Et=R8}$x%CNN^>NNME$62$BNf|+b z3HD8eCDu)dF)s?EXb?yu2oZfiWDx`rT@+ndH$CSNLKpFJ_J801|9PM1w|A;~x@M>( z-w*5Mmw>PdH6srJ`$o&7H7ekJXZf_V3Gn!=zRDGxKej%o1mGLAepuZA1Om3bxAuISrv69wxXlR`8i=_#}qF@$g0ceKPU9ZuX4Ua_!Z|lAJ`>s zEh(_^RBYK2q0t+0qVF~!<;2NXqpXeMw;RuBT(mbnr?K~nB;S8cfFDvSbP@0mO2^Ni zN)|a)wk~8wE*)iU0m1|=GVhqVcwIV@AAd4@)lUX(a8`Iv1I{kz`j%lpEOWN?(a1UHYM7p(@jBP3!vyrh9lSQc0G}tZoz>;= zBrY`**zNg!w~c;v-bgid!hWwhYk&v6nfVvg&-m(t%<(_*9XdMTAjts@SQ;vvwG@SX zJ(>|k5-Pe`6=cj^5*lhAodTAX2z#EF%XP-50whh z44r|t2d${%pGcbu9U=C%QKjG*BRaVh>Qwapy>G$?s&(pxCi{Z>43`ObB=S)T>dd)HM2qFmRzzU_m$Wng(6I1N;ZVe$YrNYGDOG_HqvM; zXpoeMCPi{txs|e@#KI+ct-ikh`@ZLW{-fkjqBq*p3FG7iAm<`^ev5V2u$}1wtc`}p z@*==IX55SiAneAwj2s}+C)KPy0j3A3)*Z+Bp;SNq2I#-isxyIilhVGv&vzlGG=z8v zxyuy;D3x-5%M|CQ@>dJ{$TOudItX|~iBeHe1z75pK;Hrvf0T{OMbWoO5(S;Ffu?m11Jh;+P&{ z@R-$I#;T84-4n$Gj#|H0swo-}Rf*h_>x3&zVauH8ygjE#g)PfLzOBgC)XqEkwvE>7 S5|y1O4EhZrIe4wUTK)ho>Sgf& diff --git a/resources/translations/en.ts b/resources/translations/en.ts index b7e3af6..6689a06 100644 --- a/resources/translations/en.ts +++ b/resources/translations/en.ts @@ -10,17 +10,28 @@ - + Place the Code in the center + + + Camera permission denied! + + + + + This app requires access to your camera in order to scan QR-Codes. It will never record or store any photos or videos. + This app requires access to your camera in order to scan QR-Codes. It will never record store any photos or videos. + + - + Plase wait - + Invalid QR-Code diff --git a/sources/bluerockbackend.cpp b/sources/bluerockbackend.cpp index 93a9f2b..6438387 100644 --- a/sources/bluerockbackend.cpp +++ b/sources/bluerockbackend.cpp @@ -130,8 +130,10 @@ void BlueRockBackend::shareResultsAsPoster(QString url, QString compName) { QPixmap barcode; int size = writer.width() * 0.5; + QZXingEncoderConfig encoderConfig(QZXing::EncoderFormat_QR_CODE, QSize(size, size), QZXing::EncodeErrorCorrectionLevel_M, false, false); barcode.convertFromImage(QZXing::encodeData(url, encoderConfig)); + painter.drawPixmap((writer.width() - size) / 2, size * 0.5, size, size, barcode); painter.end(); @@ -140,6 +142,73 @@ void BlueRockBackend::shareResultsAsPoster(QString url, QString compName) { this->_shareUtils->sendFile(path, compName, "application/pdf", 1); } +bool BlueRockBackend::isCameraPermissionGranted() { +#ifdef Q_OS_ANDROID + QtAndroid::PermissionResult cameraAccess = QtAndroid::checkPermission("android.permission.CAMERA"); + return cameraAccess == QtAndroid::PermissionResult::Granted; +#else + return false; +#endif +} + +bool BlueRockBackend::requestCameraPermission() { + if(this->isCameraPermissionGranted()) + return true; + +#ifdef Q_OS_ANDROID + // try to get permission + QtAndroid::PermissionResultMap resultMap = QtAndroid::requestPermissionsSync({"android.permission.CAMERA"}); + bool resultBool = true; + for(QtAndroid::PermissionResult result : resultMap) { + if(result != QtAndroid::PermissionResult::Granted) { + resultBool = false; + } + } + + if(resultBool) { + return true; + } + + // getting permission the traditional way failed -> open the settings app + QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) + { + // get the package name + QAndroidJniObject context = QtAndroid::androidContext(); + QAndroidJniObject applicationPackageName = context.callObjectMethod("getPackageName"); + + QAndroidJniObject param = QAndroidJniObject::fromString("package:" + applicationPackageName.toString()); + + // Equivalent to Jave code: 'Uri uri = Uri::parse("...");' + QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", param.object()); + if (!uri.isValid()) { + qWarning("ERROR: Unable to create Uri object"); + return false; + } + QAndroidJniObject packageName = QAndroidJniObject::fromString("android.settings.APPLICATION_DETAILS_SETTINGS"); + + QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;)V", packageName.object()); + if (!intent.isValid()) { + qWarning("ERROR: Unable to create Intent object"); + return false; + } + intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", QAndroidJniObject::fromString("android.intent.category.DEFAULT").object()); + intent.callObjectMethod("setData", "(Landroid/net/Uri;)Landroid/content/Intent;", uri.object()); + + activity.callMethod("startActivity","(Landroid/content/Intent;)V",intent.object()); + } + else { + qWarning() << "ERROR: Activity not valid!"; + return false; + } + + return true; +#else + return false; +#endif + +} + // ------------------------ // --- Helper functions --- // ------------------------