'BluetoothAdapter StartDiscovery does not work in Foreground Service

My application starts a service that detects phone shaking. When the service detects a shake, it searches for a BT device within range and if a suitable device is found, it connects to it and sends data to it.

To check if the system is killing the service, I turn on the vibration when it detects shaking.

Everything works fine when Activity is on the main screen. However, when I close Activity, the service detects shaking, but the device search does not start (BroadcastReceiver onReceive does not receive any Intent).

Are there any limitations to searching for Bluetooth devices from the background service? How can this be solved?

App Permissions:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Start Discovery Code in ForegroundService.java

IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);

cnt.registerReceiver(receiver, filter);
btAdapter.startDiscovery();

Broadcast Receiver

private final BroadcastReceiver receiver = new BroadcastReceiver()
{
    public void onReceive(Context context, Intent i)
    {
        String action = i.getAction();
        //Log.d("BluetoothFinder", "receiver action: " + action);
        if (BluetoothDevice.ACTION_FOUND.equals(action))
        {
            BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            int rssi = i.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);

            String name = "<brak nazwy urządzenia>";
            if (device.getName() != null) name = device.getName();

            BTDevice d = new BTDevice(device.getAddress(), name, true,
                    (device.getBondState() != BluetoothDevice.BOND_BONDED) ? BTDevice.UNBONDED : BTDevice.BONDED, rssi);

            if (addDevIfDoesntExists(d))
            {
                newBTDevice = d;
                Log.d("BluetoothFinder", "Znaleziono nowe urządzenie: " + d.MAC + " rssi: " + rssi);
                try { methodParamOnFound.call();  } catch (Exception e) {}
            }
        }
        else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
        {
            Log.d("BluetoothFinder", "ACTION_DISCOVERY_FINISHED");
            try { methodParamOnEnd.call(); } catch (Exception e) { }
        }
        else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action))
        {
            Log.d("BluetoothFinder", "ACTION_DISCOVERY_FINISHED");
            btDevices.clear();
        }
    }
};


Solution 1:[1]

EDIT: Unfortunately, this is not exactly a good solution. Sometimes the service won't start discovering.

I found an answer. I had to add line:

android:foregroundServiceType="location"

in AndroidManifest.xml:

<service
        android:name=".ForegroundService"
        android:exported="true"
        android:enabled="true"
        android:foregroundServiceType="location"
        />

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1