扫描蓝牙 LE 设备时出现问题(无回调)
Posted
技术标签:
【中文标题】扫描蓝牙 LE 设备时出现问题(无回调)【英文标题】:Problem in scanning Bluetooth LE devices (no callback) 【发布时间】:2020-04-28 10:23:09 【问题描述】:我正在尝试开发一个能够连接到 BLE 设备的 android 应用。但是我很难找到 ble 设备。 scanLeDevice 方法运行但我没有回调。您可以在下面找到我的代码:我使用 Log.i() 来显示 ble 设备。 使用另一个应用程序(从商店下载),我可以找到我的 ble 设备和其他蓝牙设备。所以这不是我手机的问题。
感谢您的帮助!
public class MainActivity extends AppCompatActivity
private BluetoothAdapter bluetoothAdapter;
private final int REQUEST_ENABLE_BT = 1;
private boolean mScanning;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("MainActivity", "Begin");
// Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled())
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
Log.i("MainActivity", "End for permissions");
if(Build.VERSION.SDK_INT < 21)
scanLeDevice(true);
else
scanDevice(true);
private Handler handler = new Handler();
private void scanLeDevice(final boolean enable)
if (enable)
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable()
@Override
public void run()
mScanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
, SCAN_PERIOD);
mScanning = true;
bluetoothAdapter.startLeScan(leScanCallback);
Log.i("MainActivity", "scanning");
else
mScanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
// Device scan callback.
private BluetoothAdapter.LeScanCallback leScanCallback =
new BluetoothAdapter.LeScanCallback()
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord)
runOnUiThread(new Runnable()
@Override
public void run()
//Ici///////////////////////////////////////
Log.i("MainActivity", "Nam: "+device.getName()+" Adresse: "+device.getAddress());
if(device.getName() != null && device.getName().equals("RN4871-85D7"))
scanLeDevice(false);
);
;
///////////////////Scan for API 21
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothLeScanner mLEScanner;
private void scanDevice(final boolean enable)
if (mLEScanner==null)
mLEScanner = bluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters = new ArrayList<ScanFilter>();
if (enable)
if (mScanning) return;
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable()
@Override
public void run()
if (!mScanning) return;
try
mScanning = false;
//Log.d("MainActivity","STOP SCAN AFTER DELAY");
mLEScanner.stopScan(mScanCallback);
Log.i("MainActivity", "stop scanning API 21");
catch (Exception e)Log.e("MainActivity",e.getMessage());
, SCAN_PERIOD);
mScanning = true;
//Log.d("MainActivity","START SCAN FROM EXPLICIT CALL");
mLEScanner.startScan(filters, settings, mScanCallback);
Log.i("MainActivity", "scanning API 21");
else if (mLEScanner!=null)
if (!mScanning) return;
mScanning = false;
try
//Log.d("MainActivity","STOP SCAN FROM EXPLICIT CALL");
mLEScanner.stopScan(mScanCallback);
Log.i("MainActivity", "stop scanning API 21");
catch (Exception e)Log.i("MainActivity",e.getMessage());
//call back for API 21
//@TargetApi(21)
private ScanCallback mScanCallback = new ScanCallback()
@Override
public void onScanResult(int callbackType, ScanResult result)
super.onScanResult(callbackType, result);
Log.i("MainActivity", "onScanResult API 21");
@Override
public void onBatchScanResults(List<ScanResult> results)
super.onBatchScanResults(results);
Log.i("MainActivity", "onBatchScanResults API 21");
@Override
public void onScanFailed(int errorCode)
super.onScanFailed(errorCode);
Log.i("MainActivity", "onScanFailed API 21");
;
感谢您的帮助``
【问题讨论】:
您能否分享您在运行扫描时获得的日志并且 BLE 设备就在附近? 是附近的设备。问题是授权该应用访问该位置。感谢您的反应。 【参考方案1】:我发现这个位置有什么问题。 事实上,如果您使用 API >= 23,您必须授权您的应用程序访问该位置(不仅在 Manifest 文件中,而且在您自己的代码中)。 所以如果你有同样的问题:
-
首先,手动转到手机的设置,并自动让您的应用访问位置:确保这是问题所在。
然后添加下面的代码,以便应用程序要求用户授权应用程序访问该位置
/////////////////////////Location/////
@TargetApi(Build.VERSION_CODES.M)
private void loadPermissions(String perm,int requestCode)
if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED)
if (ActivityCompat.shouldShowRequestPermissionRationale(this, perm))
ActivityCompat.requestPermissions(this, new String[]perm,requestCode);
else if (checkLocationEnabled())
initScanner();
private boolean checkLocationEnabled()
LocationManager lm = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
catch(Exception ex)
try
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
catch(Exception ex)
if(!gps_enabled && !network_enabled)
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setMessage("GPS desabled");
dialog.setPositiveButton("Open GPS settings", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
// TODO Auto-generated method stub
Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
//get gps
);
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
// TODO Auto-generated method stub
);
dialog.show();
return false;
else return true;
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
switch (requestCode)
case REQUEST_FINE_LOCATION:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
// granted
if (checkLocationEnabled())
initScanner();
else
// no granted
return;
【讨论】:
【参考方案2】:我也遇到了这个问题,因为我在权限上使用了ACCESS_COARSE_LOCATION
。
当我更改为ACCESS_FINE_LOCATION
时,它终于对我有用了!
【讨论】:
以上是关于扫描蓝牙 LE 设备时出现问题(无回调)的主要内容,如果未能解决你的问题,请参考以下文章