我试图发现附近的蓝牙设备,但 startDiscovery() 总是返回 false,就好像它不起作用一样。因此它无法找到设备。
我发现除了蓝牙和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;
}
您是否检查过您的设备上的位置已激活?
即使授予位置权限,当禁用该权限时,蓝牙 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);
}
如果您计划在 Google Play 商店上分发应用程序,则降级至 28 不再起作用。 我遇到了同样的问题(Android 9 有效,Android 10:startDiscovery() 返回 false)。我唯一要做的就是将权限从 ACCESS_COARSE_LOCATION 更改为 ACCESS_FINE_LOCATION。不要忘记到处更改它!我明白了,它在您的清单中,但在您的活动中您请求 ACCESS_COARSE_LOCATION。另外也不要忘记更改 onRequestPermissionsResult ;)
最后一件事:在设置中应启用定位服务。还有允许 BT 扫描的选项。
我必须将蓝牙权限设置为“始终允许”。我在位置设置中手动将其设置为“始终允许”。我还没有测试过你是否可以使用你的应用程序自动设置它。
蓝牙访问“仅在使用时”应用程序不起作用!
小米红米 Note 10 Pro / Android 11
可能是 targetSdkVersion 29 权限相关问题。 一个简单的解决方案是降级目标 SDK。在文件 build.gradle (app) 中更改例如:
targetSdkVersion 29 -> targetSdkVersion 28
我遇到了类似的问题。后来发现位置权限有问题。我把APP设置为禁用定位,导致一直错误返回;
唯一对我有用的就是将 targetSdkVersion 降级到 28。当然位置权限仍然适用。
我也遇到了同样的问题。即使在授予位置权限后我也没有让它工作。但后来我发现我的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);
}
}
}
将 targetSdkVersion 降级至 28。
使用高版本,不起作用