Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/2522.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add the ability to specify bluetooth permission.
4 changes: 4 additions & 0 deletions docs/en/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,10 @@ Applications may also need to declare the permissions they require. Permissions

Briefcase maintains a set of cross-platform permissions:

#### `permission.bluetooth`

Permission to connect to an external device via Bluetooth.
Comment thread
depaolim marked this conversation as resolved.

#### `permission.camera`

Permission to access the camera to take photos or video.
Expand Down
1 change: 1 addition & 0 deletions src/briefcase/commands/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ def _x_permissions(self, app: AppConfig):
return {
key: app.permission.pop(key, None)
for key in [
"bluetooth",
"camera",
"microphone",
"coarse_location",
Expand Down
34 changes: 26 additions & 8 deletions src/briefcase/platforms/android/gradle.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,41 +239,59 @@ def permissions_context(self, app: AppConfig, x_permissions: dict[str, str]):
"""
# Default permissions for all Android apps
permissions = {
"android.permission.INTERNET": True,
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": {},
"android.permission.ACCESS_NETWORK_STATE": {},
}

# Default feature usage for all Android apps
features = {}

if x_permissions["bluetooth"]:
permissions["android.permission.ACCESS_COARSE_LOCATION"] = {
"android:maxSdkVersion": "30"
}
permissions["android.permission.ACCESS_FINE_LOCATION"] = {
"android:maxSdkVersion": "30"
}
permissions["android.permission.BLUETOOTH"] = {
"android:maxSdkVersion": "30"
}
permissions["android.permission.BLUETOOTH_ADMIN"] = {
"android:maxSdkVersion": "30"
}
permissions["android.permission.BLUETOOTH_CONNECT"] = {}
permissions["android.permission.BLUETOOTH_SCAN"] = {
"android:usesPermissionFlags": "neverForLocation"
}

if x_permissions["camera"]:
permissions["android.permission.CAMERA"] = True
permissions["android.permission.CAMERA"] = {}
features["android.hardware.camera"] = False
features["android.hardware.camera.any"] = False
features["android.hardware.camera.front"] = False
features["android.hardware.camera.external"] = False
features["android.hardware.camera.autofocus"] = False

if x_permissions["microphone"]:
permissions["android.permission.RECORD_AUDIO"] = True
permissions["android.permission.RECORD_AUDIO"] = {}

if x_permissions["fine_location"]:
permissions["android.permission.ACCESS_FINE_LOCATION"] = True
permissions["android.permission.ACCESS_FINE_LOCATION"] = {}
Comment thread
depaolim marked this conversation as resolved.
features["android.hardware.location.network"] = False
features["android.hardware.location.gps"] = False

if x_permissions["coarse_location"]:
permissions["android.permission.ACCESS_COARSE_LOCATION"] = True
permissions["android.permission.ACCESS_COARSE_LOCATION"] = {}
features["android.hardware.location.network"] = False
features["android.hardware.location.gps"] = False

if x_permissions["background_location"]:
permissions["android.permission.ACCESS_BACKGROUND_LOCATION"] = True
permissions["android.permission.ACCESS_BACKGROUND_LOCATION"] = {}
features["android.hardware.location.network"] = False
features["android.hardware.location.gps"] = False

if x_permissions["photo_library"]:
permissions["android.permission.READ_MEDIA_VISUAL_USER_SELECTED"] = True
permissions["android.permission.READ_MEDIA_VISUAL_USER_SELECTED"] = {}

# Override any permission and entitlement definitions
# with the platform-specific definitions
Expand Down
118 changes: 73 additions & 45 deletions tests/platforms/android/gradle/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,25 +209,25 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
},
"features": {},
},
),
# Only custom permissions
(
{
"android.permission.READ_CONTACTS": True,
"android.permission.READ_CONTACTS": {},
},
{
"android.hardware.bluetooth": True,
},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.READ_CONTACTS": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.READ_CONTACTS": {},
},
"features": {
"android.hardware.bluetooth": True,
Expand All @@ -242,9 +242,9 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.CAMERA": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.CAMERA": {},
},
"features": {
"android.hardware.camera": False,
Expand All @@ -263,9 +263,9 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.RECORD_AUDIO": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.RECORD_AUDIO": {},
},
"features": {},
},
Expand All @@ -278,9 +278,9 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_COARSE_LOCATION": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.ACCESS_COARSE_LOCATION": {},
},
"features": {
"android.hardware.location.gps": False,
Expand All @@ -296,9 +296,9 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_FINE_LOCATION": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.ACCESS_FINE_LOCATION": {},
},
"features": {
"android.hardware.location.gps": False,
Expand All @@ -314,9 +314,9 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_BACKGROUND_LOCATION": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.ACCESS_BACKGROUND_LOCATION": {},
},
"features": {
"android.hardware.location.gps": False,
Expand All @@ -333,10 +333,10 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_COARSE_LOCATION": True,
"android.permission.ACCESS_BACKGROUND_LOCATION": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.ACCESS_COARSE_LOCATION": {},
"android.permission.ACCESS_BACKGROUND_LOCATION": {},
},
"features": {
"android.hardware.location.gps": False,
Expand All @@ -353,10 +353,10 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_FINE_LOCATION": True,
"android.permission.ACCESS_BACKGROUND_LOCATION": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.ACCESS_FINE_LOCATION": {},
"android.permission.ACCESS_BACKGROUND_LOCATION": {},
},
"features": {
"android.hardware.location.gps": False,
Expand All @@ -373,10 +373,10 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_COARSE_LOCATION": True,
"android.permission.ACCESS_FINE_LOCATION": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.ACCESS_COARSE_LOCATION": {},
"android.permission.ACCESS_FINE_LOCATION": {},
},
"features": {
"android.hardware.location.gps": False,
Expand All @@ -394,11 +394,11 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_COARSE_LOCATION": True,
"android.permission.ACCESS_FINE_LOCATION": True,
"android.permission.ACCESS_BACKGROUND_LOCATION": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.ACCESS_COARSE_LOCATION": {},
"android.permission.ACCESS_FINE_LOCATION": {},
"android.permission.ACCESS_BACKGROUND_LOCATION": {},
},
"features": {
"android.hardware.location.gps": False,
Expand All @@ -414,9 +414,37 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.READ_MEDIA_VISUAL_USER_SELECTED": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.READ_MEDIA_VISUAL_USER_SELECTED": {},
},
"features": {},
},
),
# Bluetooth permissions
(
{
"bluetooth": "I need to connect to bluetooth device",
},
{},
{
"permissions": {
"android.permission.ACCESS_COARSE_LOCATION": {
"android:maxSdkVersion": "30"
},
"android.permission.ACCESS_FINE_LOCATION": {
"android:maxSdkVersion": "30"
},
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.BLUETOOTH": {"android:maxSdkVersion": "30"},
"android.permission.BLUETOOTH_ADMIN": {
"android:maxSdkVersion": "30"
},
"android.permission.BLUETOOTH_CONNECT": {},
"android.permission.BLUETOOTH_SCAN": {
"android:usesPermissionFlags": "neverForLocation"
},
"android.permission.INTERNET": {},
},
"features": {},
},
Expand All @@ -426,18 +454,18 @@ def test_extract_packages(create_command, first_app_config, test_sources, expect
{
"camera": "I need to see you",
"android.permission.CAMERA": False,
"android.permission.READ_CONTACTS": True,
"android.permission.READ_CONTACTS": {},
},
{
"android.hardware.camera.external": True,
"android.hardware.bluetooth": True,
},
{
"permissions": {
"android.permission.ACCESS_NETWORK_STATE": True,
"android.permission.INTERNET": True,
"android.permission.ACCESS_NETWORK_STATE": {},
"android.permission.INTERNET": {},
"android.permission.CAMERA": False,
"android.permission.READ_CONTACTS": True,
"android.permission.READ_CONTACTS": {},
},
"features": {
"android.hardware.camera": False,
Expand Down