Skip to content

fix: BLE won't work on Android 11 and below #968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30"/>

<application
android:name=".BadgeMagicApp"
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@ class BadgeMagicPermission private constructor() {

val allPermissions = arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
)

val storagePermissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)

val locationPermissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)

val bluetoothPermissions = arrayOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_SCAN,
)

val ALL_PERMISSION = 100
val STORAGE_PERMISSION = 101
val LOCATION_PERMISSION = 102
val BLUETOOTH_PERMISSION = 103

val listPermissionsNeeded = arrayListOf<String>()
Expand All @@ -49,6 +53,13 @@ class BadgeMagicPermission private constructor() {
}
}
}
if (mode == LOCATION_PERMISSION) {
for (permission in locationPermissions) {
if (ContextCompat.checkSelfPermission(activity, permission) != android.content.pm.PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(permission)
}
}
}
if (mode == BLUETOOTH_PERMISSION) {
for (permission in bluetoothPermissions) {
if (ContextCompat.checkSelfPermission(activity, permission) != android.content.pm.PackageManager.PERMISSION_GRANTED) {
Expand All @@ -58,7 +69,20 @@ class BadgeMagicPermission private constructor() {
}
if (listPermissionsNeeded.size > 0) {
for (permission in listPermissionsNeeded) {
if (permission == Manifest.permission.WRITE_EXTERNAL_STORAGE) {
if (permission == Manifest.permission.ACCESS_FINE_LOCATION && android.os.Build.VERSION.SDK_INT <= 30) {
AlertDialog.Builder(activity)
.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_caution))
.setTitle(activity.getString(R.string.location_required_title))
.setMessage(activity.getString(R.string.location_required_message))
.setPositiveButton("OK") { _, _ ->
activity.requestPermissions(locationPermissions, REQUEST_PERMISSION_CODE)
}
.setNegativeButton("Cancel") { _, _ ->
Toast.makeText(activity, activity.getString(R.string.location_canceled_warning), Toast.LENGTH_SHORT).show()
}
.create()
.show()
} else if (permission == Manifest.permission.WRITE_EXTERNAL_STORAGE) {
AlertDialog.Builder(activity)
.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_caution))
.setTitle(activity.getString(R.string.storage_required_title))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.fossasia.badgemagic.ui

import android.Manifest
import android.app.Activity
import android.app.AlertDialog
import android.content.DialogInterface
Expand Down Expand Up @@ -224,7 +225,7 @@ class DrawerActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedLi
private fun prepareForScan() {
if (isBleSupported()) {
val permission = BadgeMagicPermission.instance
permission.checkPermissions(this, permission.BLUETOOTH_PERMISSION)
permission.checkPermissions(this, permission.LOCATION_PERMISSION)
} else {
Toast.makeText(this, "BLE is not supported", Toast.LENGTH_LONG).show()
finish()
Expand Down Expand Up @@ -293,6 +294,15 @@ class DrawerActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedLi
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Timber.d { "Required Permission Accepted" }
}
for (p in permissions) {
if (
p == Manifest.permission.ACCESS_FINE_LOCATION &&
grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
val permission = BadgeMagicPermission.instance
permission.checkPermissions(this, permission.BLUETOOTH_PERMISSION)
}
}
}
else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package org.fossasia.badgemagic.util
import android.app.AlertDialog
import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.Intent
import android.location.LocationManager
import android.provider.Settings
import android.widget.Toast
import androidx.core.content.ContextCompat
import org.fossasia.badgemagic.R
Expand All @@ -12,7 +15,7 @@ class BluetoothAdapter(appContext: Context) {
private val btAdapter = btManager.adapter!!

fun isTurnedOn(context: Context): Boolean = when {
btAdapter.isEnabled -> true
btAdapter.isEnabled -> scanLocationPermissions(context)
else -> {
showAlertDialog(context)
false
Expand All @@ -25,6 +28,22 @@ class BluetoothAdapter(appContext: Context) {
}
}

private fun scanLocationPermissions(context: Context): Boolean {
val lm = context.getSystemService(Context.LOCATION_SERVICE)
if (lm is LocationManager) {
if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && android.os.Build.VERSION.SDK_INT <= 30) {
AlertDialog.Builder(context)
.setMessage(R.string.no_gps_enabled)
.setPositiveButton("OK") { _, _ -> context.startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)) }
.setNegativeButton("Cancel", null)
.show()
return false
}
return true
}
return false
}

private fun showAlertDialog(context: Context) {
val dialogMessage = context.getString(R.string.enable_bluetooth)
val builder = AlertDialog.Builder(context)
Expand Down
8 changes: 8 additions & 0 deletions android/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@
<string name="clipart_saved_success">ClipArt已成功保存</string>
<string name="clipart_saved_error">保存剪贴画时出错</string>
<string name="drawer_saved_cliparts">保存的教具</string>
<string name="no_gps_enabled">找不到GPS,请从设置中启用GPS</string>

<string name="location_required_title">需要位置许可</string>
<string name="location_required_message">
Badge Magic 会收集位置数据以启用蓝牙低功耗并连接到 LED 徽章并将数据传输到徽章,即使应用程序关闭或未使用也是如此。\n不会将任何位置数据传输到外部设备或我们的服务器。
</string>
<string name="location_canceled_warning">请允许位置权限。 蓝牙 LE 需要这个才能工作。</string>


<string name="storage_required_title">需要存储权限</string>
<string name="storage_required_message">Badge Magic 需要访问存储空间才能保存和访问已保存的徽章/剪贴画</string>
Expand Down
12 changes: 12 additions & 0 deletions android/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@
<string name="clipart_saved_success">ClipArt Saved Successfully</string>
<string name="clipart_saved_error">Error in saving Clipart</string>
<string name="drawer_saved_cliparts">Saved Cliparts</string>
<string name="no_gps_enabled">No GPS Found, Please Enable GPS from Settings</string>

<string name="location_required_title">Location Permission Required</string>
<string name="location_required_message">
Badge Magic uses location data to enable Bluetooth LE and to transfer
data to the badges. No location data is transferred to external devices
or our servers.
</string>
<string name="location_canceled_warning">
Please allow Location permissions.
Bluetooth LE requires this to work.
</string>

<string name="storage_required_title">Storage Permission Required</string>
<string name="storage_required_message">Badge Magic requires access to storage to save and access saved Badges/Cliparts.</string>
Expand Down
Loading