Android Bluetooth StartDiscovery() always returns false

7.3k Views Asked by At

I am trying to discover bluetooth devices nearby, but startDiscovery() always returns false, as if it is not working. Therefore it is not able to find devices.

I saw that i have to include Coarse_Location permission apart from Bluetooth and Bluetooth_Admin, but anyway, it doesn´t work.

Here is the code I am trying right now, where there are mainly traces to see how it works:

public class BluetoothActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    ArrayList<BluetoothDevice> dispositivos;
    BTAdapter adaptador;
    BluetoothAdapter mBluetoothAdapter;
    Button buscar;

    final int REQUEST_ACCESS_COARSE_LOCATION = 16;
    @Override
    public void onCreate(Bundle savedInsanceState){
        super.onCreate(savedInsanceState);
        setContentView(R.layout.bluetooth_activity);

        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if(mBluetoothAdapter != null) {
            Toast.makeText(this, "No es nulo", Toast.LENGTH_SHORT).show();
            if (!mBluetoothAdapter.isEnabled()) {
                Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(intent, RESULT_OK);
            }

            IntentFilter filter = new IntentFilter();

            filter.addAction(BluetoothDevice.ACTION_FOUND);
            filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
            filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

            registerReceiver(mReceiver, filter);

        }

        buscar = findViewById(R.id.buscar);
        buscar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(BluetoothActivity.this, "Empezar a buscar", Toast.LENGTH_SHORT).show();

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    switch (ContextCompat.checkSelfPermission(BluetoothActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
                        case PackageManager.PERMISSION_DENIED:
                            ActivityCompat.requestPermissions(BluetoothActivity.this,
                                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                                    REQUEST_ACCESS_COARSE_LOCATION);

                            break;
                        case PackageManager.PERMISSION_GRANTED:
                            boolean a = mBluetoothAdapter.startDiscovery();
                            Toast.makeText(BluetoothActivity.this, "Start discovery es "+a, Toast.LENGTH_SHORT).show();
                            break;
                    }
                }
            }
        });
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(action)){
                Toast.makeText(BluetoothActivity.this, "Encontrado", Toast.LENGTH_SHORT).show();
            }
        }
    };

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_ACCESS_COARSE_LOCATION: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    boolean a = mBluetoothAdapter.startDiscovery();
                    Toast.makeText(BluetoothActivity.this, "Start discovery es "+a, Toast.LENGTH_SHORT).show();
                }
                else {
                    //exit application or do the needful
                }
                return;
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
    }


}

And here the permissions in android manifest:


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

    <uses-feature android:name="android.hardware.bluetooth" />

UPDATE: when I clicked to see the description of the startDiscovery method, I get this, with RequiresPermission and startDiscovery in red, saying "Cannot resolve method" and Manifest.permission.BLUETOOTH_ADMIN underlined and saying "Cannot find method value" :

@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public boolean startDiscovery() {
        if (getState() != STATE_ON) {
            return false;
        }
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.startDiscovery(getOpPackageName());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        } finally {
            mServiceLock.readLock().unlock();
        }
        return false;
    }
8

There are 8 best solutions below

2
Cédric BERTRAND On

Have you checked that the location is activated on your device?

Even if the location permission is granted, when it is disabled, the bluetooth API doesn't work.

So I suggest you to add the following code to be sure that the permission is effective:

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isGpsEnabled) {
  startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), MY_REQUEST_CODE);
}
0
MatejC On

It can be targetSdkVersion 29 permissions related problem. A simple workaround solution can be to downgrade target SDK. In file build.gradle (app) change for example:

        targetSdkVersion 29 -> targetSdkVersion 28
0
peng On

I encountered a similar problem. Later, I found that there was a problem with the location permission. I set the APP to disable the location, which led to false return all the time;

0
ThanosFisherman On

The only thing that worked for me was to downgrade targetSdkVersion to 28. Of course Location permission still applies.

0
Dark.Rider On

The downgrade to 28 doesn't work any more if you plan to distribute your application on Google Play Store. I had the same issue (Android 9 works, Android 10: startDiscovery() returns false). The only thing I had to do is to change the Permission from ACCESS_COARSE_LOCATION to ACCESS_FINE_LOCATION. Don't forget to change it EVERYWHERE! I see, it is in your Manifest but in your activity you request ACCESS_COARSE_LOCATION. Also don't forget to alter onRequestPermissionsResult too ;)

The last thing: in the settings the location service should be enabled. There is also the option to allow BT scan.

0
PBahner On

I had to turn bluetooth-permission to "allow-always". I set it manually in the location settings to "allow-always". I haven't tested if you can set it automatically with your app.

Bluetooth acces "only-while-using" app doesn't worked!

Xiaomi Redmi Note 10 Pro / Android 11

2
Harshvardhan Yadav On

I had run into the same problem. Even after giving location permissions I had not got it to work. But then I found out that my BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE was not set. Then I just added following code and everything worked(Inside OnCreate).

if(bluetoothAdapter.getScanMode()!=BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){ System.out.println(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); }

Entire Code:

package com.example.bluetoothapi22;

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView textView;
    Button button;
    ListView listView;
    BluetoothAdapter bluetoothAdapter;

    public void search(View view){
        textView.setText("Searching...");
        button.setEnabled(false);
        System.out.println(bluetoothAdapter.startDiscovery());
    }

    private final BroadcastReceiver broadcastReceiver=new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action=intent.getAction();
            System.out.println(action);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=findViewById(R.id.loadingTextView);
        button=findViewById(R.id.searchButton);
        listView=findViewById(R.id.listView);
        bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        registerReceiver(broadcastReceiver,intentFilter);
        if(!bluetoothAdapter.isEnabled()){
            System.out.println(bluetoothAdapter.enable());
        }
        if(bluetoothAdapter.isDiscovering()){
            System.out.println(bluetoothAdapter.cancelDiscovery());
        }
        if(bluetoothAdapter.getScanMode()!=BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
            System.out.println(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
        }
    }
}
0
pasquale On

Downgrade targetSdkVersion to 28.

With upper version, doesn't work

Also you need ACCESS_COARSE_LOCATION permission