From 498c0d42e22c831e8146cf9e267b9897e0749162 Mon Sep 17 00:00:00 2001 From: TaaviE Date: Sat, 1 Aug 2020 22:20:53 +0300 Subject: [PATCH] Made sure to check if location permission has been given by the user for scanning --- .../activities/ControlCenterv2.java | 25 ++-- .../activities/DiscoveryActivity.java | 109 ++++++++++-------- app/src/main/res/values/strings.xml | 1 + 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java index 51f924605..1380fd631 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java @@ -72,24 +72,19 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class ControlCenterv2 extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, GBActivity { + public static final int MENU_REFRESH_CODE = 1; + private static PhoneStateListener fakeStateListener; + //needed for KK compatibility static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } private DeviceManager deviceManager; - private GBDeviceAdapterv2 mGBDeviceAdapter; private RecyclerView deviceListView; private FloatingActionButton fab; - private boolean isLanguageInvalid = false; - private boolean pesterWithPermissions = true; - - public static final int MENU_REFRESH_CODE = 1; - - private static PhoneStateListener fakeStateListener; - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -107,6 +102,7 @@ public class ControlCenterv2 extends AppCompatActivity } } }; + private boolean pesterWithPermissions = true; @Override protected void onCreate(Bundle savedInstanceState) { @@ -373,6 +369,10 @@ public class ControlCenterv2 extends AppCompatActivity wantedPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE); if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_DENIED) wantedPermissions.add(Manifest.permission.READ_CALENDAR); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); try { if (ContextCompat.checkSelfPermission(this, Manifest.permission.MEDIA_CONTENT_CONTROL) == PackageManager.PERMISSION_DENIED) @@ -388,6 +388,12 @@ public class ControlCenterv2 extends AppCompatActivity } } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_DENIED) { + wantedPermissions.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION); + } + } + if (!wantedPermissions.isEmpty()) { Prefs prefs = GBApplication.getPrefs(); // If this is not the first run, we can rely on @@ -411,10 +417,11 @@ public class ControlCenterv2 extends AppCompatActivity if (!wantedPermissions.isEmpty()) { GB.toast(this, getString(R.string.permission_granting_mandatory), Toast.LENGTH_LONG, GB.ERROR); ActivityCompat.requestPermissions(this, wantedPermissions.toArray(new String[0]), 0); + GB.toast(this, getString(R.string.permission_granting_mandatory), Toast.LENGTH_LONG, GB.ERROR); } } - /* In order to be able to set ringer mode to silent in PhoneCallReceiver + /* In order to be able to set ringer mode to silent in GB's PhoneCallReceiver the permission to access notifications is needed above Android M ACCESS_NOTIFICATION_POLICY is also needed in the manifest */ if (pesterWithPermissions) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java index 68af2b5d5..fa816d973 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java @@ -59,7 +59,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -88,19 +87,34 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView private static final Logger LOG = LoggerFactory.getLogger(DiscoveryActivity.class); private static final long SCAN_DURATION = 30000; // 30s private static final int REQUEST_CODE = 1; - private ScanCallback newBLEScanCallback = null; - - /** Use old BLE scanning **/ - private boolean oldBleScanning = false; - /** If already bonded devices are to be ignored when scanning */ - private boolean ignoreBonded = true; - /** If new CompanionDevice-type pairing is enabled on newer Androids **/ - private boolean enableCompanionDevicePairing = false; - private final Handler handler = new Handler(); + private final ArrayList deviceCandidates = new ArrayList<>(); + private ScanCallback newBLEScanCallback = null; + /** + * Use old BLE scanning + **/ + private boolean oldBleScanning = false; + /** + * If already bonded devices are to be ignored when scanning + */ + private boolean ignoreBonded = true; + /** + * If new CompanionDevice-type pairing is enabled on newer Androids + **/ + private boolean enableCompanionDevicePairing = false; private ProgressBar bluetoothProgress; private ProgressBar bluetoothLEProgress; - + private DeviceCandidateAdapter deviceCandidateAdapter; + private final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { + @Override + public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { + //logMessageContent(scanRecord); + handleDeviceFound(device, (short) rssi); + } + }; + private BluetoothAdapter adapter; + private Button startButton; + private Scanning isScanning = Scanning.SCANNING_OFF; private final Runnable stopRunnable = new Runnable() { @Override public void run() { @@ -113,7 +127,7 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView } } }; - private DeviceCandidateAdapter deviceCandidateAdapter; + private GBDeviceCandidate bondingDevice; private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -216,14 +230,6 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView } } - private final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { - @Override - public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { - //logMessageContent(scanRecord); - handleDeviceFound(device, (short) rssi); - } - }; - private void deviceBond(GBDeviceCandidate deviceCandidate) { if (deviceCandidate.getDevice().createBond()) { // Async, wait for bonding event to finish this activity @@ -302,9 +308,6 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView connectAndFinish(device); } - private BluetoothAdapter adapter; - private final ArrayList deviceCandidates = new ArrayList<>(); - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) private ScanCallback getScanCallback() { if (newBLEScanCallback != null) { @@ -338,10 +341,6 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView return newBLEScanCallback; } - private Button startButton; - private Scanning isScanning = Scanning.SCANNING_OFF; - private GBDeviceCandidate bondingDevice; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -394,35 +393,13 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView registerReceiver(bluetoothReceiver, bluetoothIntents); - if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - toast(DiscoveryActivity.this, getString(R.string.error_no_location_access), Toast.LENGTH_SHORT, GB.ERROR); - LOG.error("No permission to access coarse location!"); - checkAndRequestLocationPermission(); - - // We can't be sure location was granted, cancel scan start and wait for user action - return; - } - - LocationManager locationManager = (LocationManager) DiscoveryActivity.this.getSystemService(Context.LOCATION_SERVICE); - try { - if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { - // Do nothing - LOG.debug("Some location provider is enabled, assuming location is enabled"); - } else { - toast(DiscoveryActivity.this, getString(R.string.require_location_provider), Toast.LENGTH_LONG, GB.ERROR); - DiscoveryActivity.this.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - // We can't be sure location was enabled, cancel scan start and wait for new user action - return; - } - } catch (Exception ex) { - LOG.error("Exception when checking location status: ", ex); - } + checkAndRequestLocationPermission(); startDiscovery(Scanning.SCANNING_BT_NEXT_BLE); } public void onStartButtonClick(View button) { - LOG.debug("Start Button clicked"); + LOG.debug("Start button clicked"); if (isScanning()) { stopDiscovery(); } else { @@ -751,8 +728,38 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView private void checkAndRequestLocationPermission() { if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + LOG.error("No permission to access coarse location!"); + toast(DiscoveryActivity.this, getString(R.string.error_no_location_access), Toast.LENGTH_SHORT, GB.ERROR); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 0); } + if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + LOG.error("No permission to access fine location!"); + toast(DiscoveryActivity.this, getString(R.string.error_no_location_access), Toast.LENGTH_SHORT, GB.ERROR); + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { + LOG.error("No permission to access background location!"); + toast(DiscoveryActivity.this, getString(R.string.error_no_location_access), Toast.LENGTH_SHORT, GB.ERROR); + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 0); + } + } + + LocationManager locationManager = (LocationManager) DiscoveryActivity.this.getSystemService(Context.LOCATION_SERVICE); + try { + if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { + // Do nothing + LOG.debug("Some location provider is enabled, assuming location is enabled"); + } else { + toast(DiscoveryActivity.this, getString(R.string.require_location_provider), Toast.LENGTH_LONG, GB.ERROR); + DiscoveryActivity.this.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + // We can't be sure location was enabled, cancel scan start and wait for new user action + toast(DiscoveryActivity.this, getString(R.string.error_location_enabled_mandatory), Toast.LENGTH_SHORT, GB.ERROR); + return; + } + } catch (Exception ex) { + LOG.error("Exception when checking location status: ", ex); + } } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 24f5241d8..4e1e6df43 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -901,6 +901,7 @@ Error retrieving devices from database Ignore bonded devices Enabling this option will ignore devices that have been bonded/paired already when scanning + Location must be turned on to scan for devices %d hour