11

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;
    }
marpe
  • 185
  • 2
  • 9

7 Answers7

15

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);
}
  • Thank you, this solved it for me. Would never have thought that the gps location needs to be activated for bluetooth devices. – Encrypted Oct 07 '21 at 07:33
  • Bluetooth connection will work without location enabled. What won't work is Bluetooth discovery and scan. – Slion Jun 05 '23 at 09:01
2

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.

Dark.Rider
  • 381
  • 1
  • 4
  • 17
2

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

PBahner
  • 31
  • 3
1

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
MatejC
  • 2,167
  • 1
  • 18
  • 25
1

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;

peng
  • 21
  • 1
1

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

ThanosFisherman
  • 5,626
  • 12
  • 38
  • 63
1

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);
        }
    }
}
  • Doesn't make much sense... A System.out.println doesn't change anything. – Dark.Rider Mar 19 '23 at 20:06
  • Totally agree with @Dark.Rider, the code proposed in here makes no sense, to print to the console has no effect to the code. Please correct it or explain what you wanted to do/say. – Eloy Calatrava Aug 06 '23 at 15:54