安卓蓝牙StartDiscovery()总是返回false

11

我试图发现附近的蓝牙设备,但startDiscovery()总是返回false,好像它没有起作用。因此,它无法找到设备。

我发现除了Bluetooth和Bluetooth_Admin外,我还必须包括Coarse_Location权限,但是无论如何,它都不起作用。

这是我正在尝试的代码,其中主要是跟踪以查看它如何工作:

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);
    }


}

这里是Android清单文件中的权限:


    <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" />

更新:当我点击查看startDiscovery方法的描述时,我得到了这个结果,其中RequiresPermission和startDiscovery呈现为红色,显示“无法解析方法”,而Manifest.permission.BLUETOOTH_ADMIN则带有下划线,并显示“找不到方法值”:

@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;
    }

你解决了吗? - zeller
8个回答

15

你检查过设备上的位置是否已激活吗?

即使位置权限已经被授予,当其被禁用时,蓝牙API也无法工作。

因此我建议您添加以下代码以确保权限有效:

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);
}

谢谢,这个解决了我的问题。我从来没有想过蓝牙设备需要激活GPS位置。 - Encrypted
蓝牙连接将在未启用位置时正常工作。无法正常工作的是蓝牙发现和扫描。 - Slion

2

我不得不将蓝牙权限设置为"始终允许"。我在位置设置中手动设置为"始终允许"。我还没有测试您是否可以使用应用程序自动设置它。

"仅在使用时"的蓝牙访问应用程序无法正常工作!

Xiaomi Redmi Note 10 Pro / Android 11


2
降级到28版本的方法如果你计划在Google Play商店分发应用程序,将不再起作用。 我遇到了同样的问题(Android 9可以工作,而Android 10:startDiscovery()返回false)。我所做的唯一一件事就是将权限从ACCESS_COARSE_LOCATION更改为ACCESS_FINE_LOCATION。别忘了到处都要修改!我看到,在您的清单中,但在您的活动中,您请求ACCESS_COARSE_LOCATION。还要记得修改onRequestPermissionsResult ;) 最后一件事:在设置中,位置服务应该启用。还有允许BT扫描的选项。

1

我也遇到了同样的问题。即使已经授予了位置权限,我仍然无法让它正常工作。但是后来我发现我的BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE没有设置。然后我只需添加以下代码,一切都可以正常工作(在OnCreate中)。

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

完整代码:

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);
        }
    }
}

没有太多意义... System.out.println 不会改变任何东西。 - Dark.Rider
完全同意@Dark.Rider的观点,这里提出的代码毫无意义,将内容打印到控制台对代码没有任何影响。请纠正或解释您想要做/说什么。 - Eloy Calatrava

1

对我有效的唯一方法是将targetSdkVersion降级为28。当然,位置权限仍然适用。


1

我遇到了类似的问题。后来,我发现定位权限出了问题。我把应用程序设置为禁用位置信息,导致一直返回错误结果。


1
可能是与targetSdkVersion 29权限相关的问题。 一个简单的解决方案是降低目标SDK版本。在文件build.gradle(app)中进行更改,例如:
        targetSdkVersion 29 -> targetSdkVersion 28

0
targetSdkVersion降级到28。
使用较高版本无法正常工作。
此外,您还需要ACCESS_COARSE_LOCATION权限。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接