- add android manifest

- add more fonts
- add proper checks for bluetooth state and permission
This commit is contained in:
Dorian Zedler 2020-10-18 03:26:02 +02:00
parent 5170525e4b
commit 3062219099
Signed by: dorian
GPG key ID: D3B255CB8BC7CD37
11 changed files with 319 additions and 11 deletions

View file

@ -1,7 +1,8 @@
QT += quick bluetooth quickcontrols2 QT += quick bluetooth quickcontrols2
CONFIG += c++11 CONFIG += c++11
TARGET = OmobiDisplayApp TARGET = ItsblueLedDisplayController
VERSION = 1.0.0
TEMPLATE = app TEMPLATE = app
@ -41,18 +42,24 @@ CONFIG += QBluetoothLeUart_QML
include($$PWD/QBluetoothLeUart/QBluetoothLeUart.pri) include($$PWD/QBluetoothLeUart/QBluetoothLeUart.pri)
DISTFILES += \ DISTFILES += \
test.qmodel android/AndroidManifest.xml
STATECHARTS += android {
QT += androidextras
contains(ANDROID_TARGET_ARCH,armeabi-v7a) { ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
ANDROID_ABIS = \
armeabi-v7a
}
ANDROID_ABIS = armeabi-v7a
contains(ANDROID_TARGET_ARCH,) { contains(ANDROID_TARGET_ARCH,) {
ANDROID_ABIS = \ ANDROID_ABIS = \
armeabi-v7a armeabi-v7a
} }
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_ABIS = \
armeabi-v7a
}
}
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_ABIS = \
armeabi-v7a
}

View file

@ -0,0 +1,82 @@
<?xml version="1.0"?>
<manifest package="de.itsblue.LedDisplayController" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<!-- 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. -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 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. -->
<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="ItsblueLedDisplayController" 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="ItsblueLedDisplayController" 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="ItsblueLedDisplayController"/>
<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="1"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="1"/>
<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="jar/QtAndroid.jar:jar/QtAndroidExtras.jar:jar/QtAndroidBluetooth.jar:jar/QtAndroidBearer.jar"/>
<meta-data android:name="android.app.static_init_classes" android:value="org.qtproject.qt5.android.bluetooth.QtBluetoothBroadcastReceiver"/>
<!-- 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="default"/>
<!-- extract android style -->
</activity>
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
</application>
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29"/>
</manifest>

View file

@ -5,9 +5,19 @@
#include <QTranslator> #include <QTranslator>
#include <QFontDatabase> #include <QFontDatabase>
#ifdef Q_OS_ANDROID
#include <QtAndroidExtras>
#endif
#include "omobidisplaybackend.h" #include "omobidisplaybackend.h"
#include "omobidisplaytextmodel.h" #include "omobidisplaytextmodel.h"
/*void permissionCallback(const QtAndroid::PermissionResultMap& results) {
for(QtAndroid::PermissionResult result : results) {
qWarning() << "Permission Callback Result:" << (result == QtAndroid::PermissionResult::Granted);
}
}*/
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

View file

@ -47,12 +47,29 @@ void OmobiDisplayBackend::authenticate(QString code) {
this->sendBluetoothCommand(AuthenticateCommand, QVariantMap{{"secret", this->lastDisplaySecret}}); this->sendBluetoothCommand(AuthenticateCommand, QVariantMap{{"secret", this->lastDisplaySecret}});
} }
void OmobiDisplayBackend::handleBluetoothScanningError(QBluetoothLeUartClient::BluetoothScanError error) {
if(error == QBluetoothLeUartClient::LocationPermissionDeniedError) {
#ifdef Q_OS_ANDROID
// try to get permission
//QtAndroid::requestPermissions({"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}, NULL);
#endif
}
}
void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUartClient::BluetoothLeUartClientState state){ void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUartClient::BluetoothLeUartClientState state){
switch(state){ switch(state){
case QBluetoothLeUartClient::Idle: { case QBluetoothLeUartClient::Idle: {
this->setState(Idle); this->setState(Idle);
break; break;
} }
case QBluetoothLeUartClient::AdapterTurnedOff: {
this->setState(BluetoothOff);
break;
}
case QBluetoothLeUartClient::LocationPermissionDenied: {
this->setState(LocationPermissionDenied);
break;
}
case QBluetoothLeUartClient::Scanning: { case QBluetoothLeUartClient::Scanning: {
this->setState(Scanning); this->setState(Scanning);
break; break;

View file

@ -23,6 +23,8 @@ public:
enum OmobiDisplayAppState { enum OmobiDisplayAppState {
Idle, Idle,
BluetoothOff,
LocationPermissionDenied,
Scanning, Scanning,
ReadyToConnect, ReadyToConnect,
Connecting, Connecting,
@ -78,6 +80,7 @@ private slots:
void handleBluetoothStateChange(QBluetoothLeUartClient::BluetoothLeUartClientState state); void handleBluetoothStateChange(QBluetoothLeUartClient::BluetoothLeUartClientState state);
void handleFoundNewDevice(QBluetoothLeUartDevice* device); void handleFoundNewDevice(QBluetoothLeUartDevice* device);
void handleBluetoothDeviceConected(); void handleBluetoothDeviceConected();
void handleBluetoothScanningError(QBluetoothLeUartClient::BluetoothScanError error);
void handleDisplayTextModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()); void handleDisplayTextModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
void handleDisplayTextModelRowsInserted(const QModelIndex &parent, int first, int last); void handleDisplayTextModelRowsInserted(const QModelIndex &parent, int first, int last);

View file

@ -173,6 +173,123 @@ Page {
text: parseInt(root.state) === OmobiDisplayBackend.Scanning ? qsTr("Still scanning"):qsTr("No displays found") text: parseInt(root.state) === OmobiDisplayBackend.Scanning ? qsTr("Still scanning"):qsTr("No displays found")
} }
} }
Item {
id: bluetoothOffItem
anchors.centerIn: parent
width: Math.min(parent.height, parent.width)
height: Math.min(parent.height, parent.width)
opacity: 0
Behavior on opacity {
NumberAnimation {}
}
Text {
id: bluetoothOffIcon
anchors {
top: parent.top
topMargin: parent.height * 0.1
horizontalCenter: parent.horizontalCenter
}
anchors.verticalCenterOffset: text === "..." ? -height * 0.25:0
color: "lightgrey"
font.pixelSize: parent.height * 0.4
font.family: fontAwesomeBrands.name
text: "\uf294"
}
Text {
id: bluetoothOffText
anchors {
top: bluetoothOffIcon.bottom
topMargin: bluetoothOffIcon.height * 0.15
horizontalCenter: parent.horizontalCenter
}
font.bold: true
font.pixelSize: bluetoothOffIcon.height * 0.15
color: Qt.darker("lightgrey", 1.1)
text: qsTr("Bluetooth is turned off")
}
}
Item {
id: noPermissionItem
anchors.centerIn: parent
width: Math.min(parent.height, parent.width)
height: Math.min(parent.height, parent.width)
opacity: 0
Behavior on opacity {
NumberAnimation {}
}
Text {
id: noPermissionIcon
anchors {
top: parent.top
topMargin: parent.height * 0
horizontalCenter: parent.horizontalCenter
}
anchors.verticalCenterOffset: text === "..." ? -height * 0.25:0
color: "lightgrey"
font.pixelSize: parent.height * 0.4
font.family: fontAwesome.name
text: "\uf3ed"
}
Text {
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
color: Qt.darker("lightgrey", 1.1)
text: qsTr("Error:\nLocation permission denied!")
}
Text {
id: noPermissionDetailText
anchors {
top: noPermissionText.bottom
topMargin: noPermissionText.height * 0.15
horizontalCenter: parent.horizontalCenter
}
width: parent.width * 0.9
font.bold: true
font.pixelSize: noPermissionText.font.pixelSize * 0.7
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
color: Qt.darker("lightgrey", 1.1)
text: qsTr("This app requires location permission in order for Bluetooth to work, it will not actually access your location.")
}
}
} }
} }
@ -224,6 +341,44 @@ Page {
statusText: qsTr("Tap here to scan") statusText: qsTr("Tap here to scan")
working: false working: false
} }
PropertyChanges {
target: noPermissionItem
opacity: 0
}
},
State {
name: OmobiDisplayBackend.BluetoothOff
PropertyChanges {
target: bluetoothOffItem
opacity: 1
}
PropertyChanges {
target: root
statusText: qsTr("Bluetooth is turned off")
working: false
}
PropertyChanges {
target: noDisplaysItem
opacity: 0
}
},
State {
name: OmobiDisplayBackend.LocationPermissionDenied
PropertyChanges {
target: noPermissionItem
opacity: 1
}
PropertyChanges {
target: root
statusText: qsTr("Tap here to continue")
working: false
}
PropertyChanges {
target: noDisplaysItem
opacity: 0
}
}, },
State { State {
name: OmobiDisplayBackend.Scanning name: OmobiDisplayBackend.Scanning
@ -233,6 +388,14 @@ Page {
statusText: qsTr("Scanning...") statusText: qsTr("Scanning...")
working: true working: true
} }
PropertyChanges {
target: bluetoothOffItem
opacity: 0
}
PropertyChanges {
target: noPermissionItem
opacity: 0
}
}, },
State { State {
name: OmobiDisplayBackend.ReadyToConnect name: OmobiDisplayBackend.ReadyToConnect

View file

@ -75,7 +75,7 @@ Page {
ToolTip { ToolTip {
parent: brightnessSlider.handle parent: brightnessSlider.handle
visible: brightnessSlider.pressed visible: brightnessSlider.pressed
text: brightnessSlider.value.toFixed(1) text: brightnessSlider.value
} }
} }

View file

@ -110,6 +110,15 @@ ApplicationWindow {
} }
} }
FontLoader {
id: fontAwesomeBrands
source: "qrc:/fa5brands.woff"
Component.onCompleted: {
console.log("Font name: " + fontAwesome.name)
}
}
StackView { StackView {
id: mainStack id: mainStack
@ -169,6 +178,22 @@ ApplicationWindow {
} }
}, },
State {
name: OmobiDisplayBackend.BluetoothOff
PropertyChanges {
target: mainStack
currentComponent: connectPageComp
}
},
State {
name: OmobiDisplayBackend.LocationPermissionDenied
PropertyChanges {
target: mainStack
currentComponent: connectPageComp
}
},
State { State {
name: OmobiDisplayBackend.Scanning name: OmobiDisplayBackend.Scanning
PropertyChanges { PropertyChanges {

Binary file not shown.

View file

@ -3,5 +3,6 @@
<file>omobi.png</file> <file>omobi.png</file>
<file>itsblue.png</file> <file>itsblue.png</file>
<file>fa5solid.woff</file> <file>fa5solid.woff</file>
<file>fa5brands.woff</file>
</qresource> </qresource>
</RCC> </RCC>