Skip to content

Commit

Permalink
Rework Android Bluetooth permission system (for the 12th time)
Browse files Browse the repository at this point in the history
  • Loading branch information
emericg committed Dec 16, 2023
1 parent c0af923 commit 2c6b4e5
Show file tree
Hide file tree
Showing 15 changed files with 911 additions and 360 deletions.
12 changes: 8 additions & 4 deletions assets/android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
<!-- Request legacy Bluetooth permissions (up to Android 11 / SDK 30) -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:minSdkVersion="29" /> <!-- android:maxSdkVersion="31" /> -->

<!-- Request new Bluetooth permissions (Android 12+ / SDK 31) -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:minSdkVersion="31" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" android:minSdkVersion="31" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:minSdkVersion="29" /> <!-- android:maxSdkVersion="31" /> -->
<!-- Service -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:minSdkVersion="29" />

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Others -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" android:minSdkVersion="33"/>

<!-- Hardware permissions -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
Expand All @@ -30,9 +33,10 @@
android:theme="@style/AppTheme" android:icon="@mipmap/ic_launcher"
android:label="WatchFlower">

<!-- Activity -->
<activity android:name="org.qtproject.qt.android.bindings.QtActivity"
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:launchMode="singleTop" android:screenOrientation="unspecified" android:windowSoftInputMode="adjustResize" android:exported="true"
android:screenOrientation="unspecified" android:windowSoftInputMode="adjustResize" android:launchMode="singleTop" android:exported="true"
android:label="WatchFlower">

<intent-filter>
Expand Down
45 changes: 31 additions & 14 deletions qml/DeviceList.qml
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,29 @@ Item {

function checkBluetoothStatus() {
if (deviceManager.hasDevices) {
if (!deviceManager.bluetoothAdapter || !deviceManager.bluetoothEnabled) {
rectangleBluetoothStatus.setBluetoothWarning()
} else if (!deviceManager.bluetoothPermissions) {
rectangleBluetoothStatus.setPermissionWarning()
// The device list is shown
loaderItemStatus.source = ""

if (!deviceManager.bluetoothPermissions) {
actionbarBluetoothStatus.setPermissionWarning()
} else if (!deviceManager.bluetoothAdapter) {
actionbarBluetoothStatus.setAdapterWarning()
} else if (!deviceManager.bluetoothEnabled) {
actionbarBluetoothStatus.setBluetoothWarning()
} else {
rectangleBluetoothStatus.hide()
actionbarBluetoothStatus.hide()
}
} else {
// The sensor list is not populated
rectangleBluetoothStatus.hide()
actionbarBluetoothStatus.hide()

if (!deviceManager.bluetoothPermissions) {
loaderItemStatus.source = "ItemNoPermissions.qml"
} else if (!deviceManager.bluetoothAdapter || !deviceManager.bluetoothEnabled) {
loaderItemStatus.source = "ItemNoBluetooth.qml"
} else {
loaderItemStatus.source = "ItemNoDevice.qml"
}
}
}

Expand Down Expand Up @@ -120,35 +133,39 @@ Item {
////////////////

ActionbarBluetooth {
id: rectangleBluetoothStatus
id: actionbarBluetoothStatus
anchors.left: parent.left
anchors.right: parent.right
}

////////////////

ActionbarSelection {
id: rectangleSelections
id: actionbarSelection
anchors.left: parent.left
anchors.right: parent.right
}
}

////////////////////////////////////////////////////////////////////////////

ItemNoDevice {
Loader {
id: loaderDeviceList
anchors.fill: parent
visible: !deviceManager.hasDevices
anchors.topMargin: rowbar.height

visible: deviceManager.hasDevices
asynchronous: false
}

////////////////////////////////////////////////////////////////////////////
////////

Loader {
id: loaderDeviceList
id: loaderItemStatus
anchors.fill: parent
anchors.topMargin: rowbar.height

asynchronous: false
visible: !deviceManager.hasDevices
asynchronous: true
}

////////////////////////////////////////////////////////////////////////////
Expand Down
106 changes: 84 additions & 22 deletions qml/MobilePermissions.qml
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,78 @@ Item {

////////

Item {
id: element_bluetooth
height: 24
Item { // Bluetooth
anchors.left: parent.left
anchors.right: parent.right
height: 24

RoundButtonIcon {
anchors.left: parent.left
anchors.leftMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
width: 32
height: 32

property bool validperm: deviceManager.permissionOS

source: (validperm) ? "qrc:/assets/icons_material/baseline-check-24px.svg" : "qrc:/assets/icons_material/baseline-close-24px.svg"
iconColor: (validperm) ? "white" : "white"
backgroundColor: (validperm) ? Theme.colorSuccess : Theme.colorSubText
backgroundVisible: true

onClicked: {
utilsApp.vibrate(25)
utilsApp.getMobileBluetoothPermission()
refreshPermissions.start()
}
}

Text {
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
anchors.right: parent.right
anchors.rightMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
height: 16

text: qsTr("Bluetooth")
textFormat: Text.PlainText
wrapMode: Text.WordWrap
font.pixelSize: 17
color: Theme.colorText
verticalAlignment: Text.AlignVCenter
}
}
Text { // Bluetooth legend
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
anchors.right: parent.right
anchors.rightMargin: Theme.componentMargin

text: qsTr("The Android operating system requires permission to scan for nearby Bluetooth Low Energy sensors.")
textFormat: Text.StyledText
wrapMode: Text.WordWrap
color: Theme.colorSubText
font.pixelSize: Theme.fontSizeContentSmall
}

////////

ListSeparatorPadded { height: 16+1 }

////////

Item { // Bluetooth control
anchors.left: parent.left
anchors.right: parent.right
height: 24

RoundButtonIcon {
anchors.left: parent.left
anchors.leftMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
width: 32
height: 32

property bool validperm: true

Expand All @@ -78,12 +138,12 @@ Item {
}

Text {
height: 16
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
anchors.right: parent.right
anchors.rightMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
height: 16

text: qsTr("Bluetooth control")
textFormat: Text.PlainText
Expand Down Expand Up @@ -113,16 +173,16 @@ Item {
////////

Item { // Location
height: 24
anchors.left: parent.left
anchors.right: parent.right
height: 24

RoundButtonIcon {
width: 32
height: 32
anchors.left: parent.left
anchors.leftMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
width: 32
height: 32

property bool validperm: deviceManager.permissionLocationBLE

Expand All @@ -139,12 +199,12 @@ Item {
}

Text {
height: 16
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
anchors.right: parent.right
anchors.rightMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
height: 16

text: qsTr("Location")
textFormat: Text.PlainText
Expand All @@ -168,9 +228,9 @@ Item {
font.pixelSize: Theme.fontSizeContentSmall
}
ButtonWireframeIcon {
height: 36
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
height: 36

primaryColor: Theme.colorPrimary
secondaryColor: Theme.colorBackground
Expand Down Expand Up @@ -199,11 +259,11 @@ Item {
anchors.right: parent.right

RoundButtonIcon {
width: 32
height: 32
anchors.left: parent.left
anchors.leftMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
width: 32
height: 32

property bool validperm: deviceManager.permissionLocationBackground

Expand All @@ -220,12 +280,12 @@ Item {
}

Text {
height: 16
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
anchors.right: parent.right
anchors.rightMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
height: 16

text: qsTr("Background location")
textFormat: Text.PlainText
Expand Down Expand Up @@ -254,17 +314,17 @@ Item {

////////

Item { // GPS
height: 24
Item { // GPS
anchors.left: parent.left
anchors.right: parent.right
height: 24

RoundButtonIcon {
width: 32
height: 32
anchors.left: parent.left
anchors.leftMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
width: 32
height: 32

property bool validperm: deviceManager.permissionLocationGPS

Expand All @@ -280,12 +340,12 @@ Item {
}

Text {
height: 16
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
anchors.right: parent.right
anchors.rightMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
height: 16

text: qsTr("GPS")
textFormat: Text.PlainText
Expand All @@ -309,9 +369,9 @@ Item {
}

ButtonWireframeIcon {
height: 36
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
height: 36

primaryColor: Theme.colorPrimary
secondaryColor: Theme.colorBackground
Expand All @@ -331,16 +391,16 @@ Item {

Item {
id: element_infos
height: 24
anchors.left: parent.left
anchors.right: parent.right
height: 32

IconSvg {
width: 32
height: 32
anchors.left: parent.left
anchors.leftMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter
width: 32
height: 32

opacity: 0.66
color: Theme.colorSubText
Expand All @@ -352,9 +412,11 @@ Item {
anchors.leftMargin: appHeader.headerPosition
anchors.right: parent.right
anchors.rightMargin: Theme.componentMargin
anchors.verticalCenter: parent.verticalCenter

text: qsTr("Click on the checkmarks to request missing permissions.")
textFormat: Text.StyledText
lineHeight : 0.8
wrapMode: Text.WordWrap
color: Theme.colorText
font.pixelSize: Theme.fontSizeContent
Expand All @@ -376,9 +438,9 @@ Item {
}

ButtonWireframeIcon {
height: 36
anchors.left: parent.left
anchors.leftMargin: appHeader.headerPosition
height: 36

primaryColor: Theme.colorPrimary
secondaryColor: Theme.colorBackground
Expand Down
Loading

0 comments on commit 2c6b4e5

Please sign in to comment.