3

Update from Android 10 above I think you need ACCESS_BACKGROUND_LOCATION permissions. So if this code doesn't work on newest android versions is for this problem. ACCESS_BACKGROUND_LOCATION is subjected to strict policy on Google Play store so instead of adding this permission you can use a ForegroundService with this option setted on the manifest declaration:

android:foregroundServiceType="location"

Using this option you won't need ACCESS_BACKGROUND_LOCATION permission to do the scan.

*** SOLVED ***

Solution: on Android >= 8 (or 6, i don't remember the version now) you need the permission to access the location and the GPS enabled to see the BLE devices.

Ok I found the solution... I was already giving all permissions like "BLUETOOTH_ADMIN", "BLUETOOTH", "ACCESS_COARSE_LOCATION" in manifest and also I was already checking all permission in my MainActivity. But I don't know why I found that if I manually add the permission "Access to my location" the scan Callback start working. So now I'm going to implement the permission request inside my MainActivity before that I start the service. That's weird because I didn't get the same problem in the other application in which I do the BLE scan inside the MainActivity; my other app in which I scan inside the MainActivity didn't request this specific permission, it only need "BLUETOOTH" & "BLUETOOTH_ADMIN" permissions. So looks like that the "Access to my location" is needed only if the scan is going to work in background.

( I tryed it in my device "Huawei P8 Lite" with Android version "8.0.0")

***********

I already tryed the "BluetoothLeScanner" inside an activity and I didn't find any problem during the scan. But now that I have moved my Scan Operation inside a service I have find some problem.

This is my service:

public class BLEService extends Service {

    private static final int SCAN_TIME_MILLIS = 5000;
    private static final String MY_MAC = "00:15:85:10:85:3C";

    private Handler mHandler;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothLeScanner mScanner;
    private ScanCallback mScanCallback;
    private BluetoothGatt mBluetoothGatt;
    private BluetoothGattCallback mGattCallback;
    private int mTxpower;

    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        initAll();
        startScan();
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void startScan(){
        mScanner.startScan(mScanCallback);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                stopScan();
            }
        }, SCAN_TIME_MILLIS);
    }

    private void stopScan(){
        mScanner.stopScan(mScanCallback);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                startScan();
            }
        }, SCAN_TIME_MILLIS);
    }

    private void initAll(){
        initBluetoothAdapter();
        initBluetoothLeScanner();
        initBluetoothScanCallback();
        initGattCallback();
    }

    private void initBluetoothAdapter(){
        final BluetoothManager bluetoothManager = (BluetoothManager) getBaseContext().getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        mBluetoothAdapter.startDiscovery();
    }

    private void initBluetoothLeScanner(){
        mScanner = mBluetoothAdapter.getBluetoothLeScanner();
    }

    private void initBluetoothScanCallback(){
        mScanCallback = new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
                super.onScanResult(callbackType, result);
            }

            @Override
            public void onBatchScanResults(List<ScanResult> results) {
                super.onBatchScanResults(results);
            }

            @Override
            public void onScanFailed(int errorCode) {
                super.onScanFailed(errorCode);
            }
        };
    }

    private void initGattCallback(){
        mGattCallback = new BluetoothGattCallback() {
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                super.onConnectionStateChange(gatt, status, newState);
            }

            @Override
            public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
                super.onReadRemoteRssi(gatt, rssi, status);
            }
        };
    }
}

When I use the method "startScan()" if I look the logs I can see that the Scanner was registered right:

I/BluetoothAdapter: getBluetoothLeScanner

D/BluetoothAdapter: isLeEnabled(): ON

D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=7 mScannerId=0

So it looks like the Scan starts right, but if I try to debug the callback of the scan it never reach my breakpoints. Can anybody help me please?

Thank you :D

Z3R0
  • 1,011
  • 10
  • 19
  • 3
    'if I manually add the permission "Access to my location" ' - What is this? For Android version > 6.0 you have to ask user for permission in the app. I cannot understand if you are doing this or something else. – reTs Oct 30 '18 at 10:54
  • 5
    I tryed to go to "Settings > App > Permissions > MyApp > Access to my location" and I saw that when I turned on it the Scan started working, then that I found which was the problem inside my main activity I put the code to ask the permission to access to the current location. – Z3R0 Oct 30 '18 at 14:42
  • @Z3R0 you you are correct, when I manually allowed "Location" from Settings -> App -> Permission, then scan callback started to come in my activity. Thanks for your post, it saved my time. I am using android Q version – Kushal Oct 27 '20 at 09:12
  • For further reading, u can see my post.. https://stackoverflow.com/questions/68452095/android-bluetooth-le-scanner-on-foreground-service-stops-immediately-when-screen/68560159#68560159 – Alex Rivas Jul 28 '21 at 12:54
  • 2
    This self-answered question is quite underrated. I encountered the same problem on OPPO A73s (Android 8). I thought requesting ACCESS_FINE_LOCATION, BLUETOOTH, and BLUETOOTH_ADMIN permissions should suffice for BLE scanning. Not realize that turning on the Google location is also necessary even though my toy app really don't care location, lol. Great thanks, @Z3R0 – Leo May 05 '22 at 22:51
  • @Leo Thank you leo (: happy to have been helpful – Z3R0 May 09 '22 at 13:19

0 Answers0