我想在我的Android应用程序中被动地扫描BLE广告商。
但我找不到该怎么做。
但我找不到是否可以使用无源扫描模式。
问题:在Android上可以使用“被动扫描”吗?如果可能的话,如何使用这个特性?
发布于 2014-07-29 09:07:50
active和passive扫描的不同之处在于,active扫描要求广告商提供SCAN_RESPONSE paket。这是通过在检测到广告后发送一个SCAN_REQUEST标记来完成的。两者的信息(有效载荷)都将在找到的回调设备的scanRecord参数中。
一个设备可以使用主动扫描来获得更多的信息,关于可能对填充用户界面有用的设备的。主动扫描涉及更多链接层广告消息。
因此,对于任何使用,没有必要在这两种扫描类型之间进行区别。
但是如果你想在后台收听广告,那么你需要自己创建一个Service --没有内置的功能(截至Android4.4)。
对于背景扫描,请以下面的例子为例。但是扫描会在你的应用程序被系统杀死(或者被用户停止)时结束。
通过PendingIntent启动AlarmManager (应用程序中的任何地方,必须至少运行一次才能启动服务.)
AlarmManager alarmMgr = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getActivity(), BleScanService.class);
PendingIntent scanIntent = PendingIntent.getService(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(), intervalMillis, scanIntent);BleScanService
public class BleScanService extends Service implements LeScanCallback {
private final static String TAG = BleScanService.class.getSimpleName();
private final IBinder mBinder = new LocalBinder();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
public class LocalBinder extends Binder {
public BleScanService getService() {
return BleScanService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
initialize();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
long timeToScan = preferences.scanLength().get();
startScan(timeToScan);
return super.onStartCommand(intent, flags, startId);
}
/**
* Initializes a reference to the local bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter
// through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
if (mBluetoothAdapter == null) {
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
}
Log.d(TAG, "Initialzed scanner.");
return true;
}
/**
* Checks if bluetooth is correctly set up.
*
* @return
*/
protected boolean isInitialized() {
return mBluetoothManager != null && mBluetoothAdapter != null && mBluetoothAdapter.isEnabled();
}
/**
* Checks if ble is ready and bluetooth is correctly setup.
*
* @return
*/
protected boolean isReady() {
return isInitialized() && isBleReady();
}
/**
* Checks if the device is ble ready.
*
* @return
*/
protected boolean isBleReady() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
Log.d(TAG, "Found ble device " + device.getName() + " " + device.getAddress());
broadcastOnDeviceFound(device, scanRecord);
}
/**
* Broadcasts a message with the given device.
*
* @param device
* @param scanRecord
*/
protected void broadcastOnDeviceFound(final BluetoothDevice device, byte[] scanRecord) {
assert device != null : "Device should not be null.";
Intent intent = new Intent(BleServiceConstants.ACTION_DEVICE_DISCOVERED);
intent.putExtra(BleServiceConstants.EXTRA_DEVICE_DISCOVERED_DEVICE, device);
intent.putExtra(BleServiceConstants.EXTRA_DEVICE_DISCOVERED_SCAN_RECORD, scanRecord);
sendBroadcast(intent);
}
/**
* Starts the bluetooth low energy scan It scans at least the
* delayStopTimeInMillis.
*
* @param delayStopTimeInMillis
* the duration of the scan
* @return <code>true</code> if the scan is successfully started.
*/
public boolean startScan(long delayStopTimeInMillis) {
if (!isReady())
return false;
if (preferences.shouldScan().get()) {
if (delayStopTimeInMillis <= 0) {
Log.w(TAG, "Did not start scanning with automatic stop delay time of " + delayStopTimeInMillis);
return false;
}
Log.d(TAG, "Auto-Stop scan after " + delayStopTimeInMillis + " ms");
getMainHandler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "Stopped scan.");
stopScan();
}
}, delayStopTimeInMillis);
}
return startScan();
}
/**
* @return an handler with the main (ui) looper.
*/
private Handler getMainHandler() {
return new Handler(getMainLooper());
}
/**
* Starts the bluetooth low energy scan. It scans without time limit.
*
* @return <code>true</code> if the scan is successfully started.
*/
public boolean startScan() {
if (!isReady())
return false;
if (preferences.shouldScan().get()) {
if (mBluetoothAdapter != null) {
Log.d(TAG, "Started scan.");
return mBluetoothAdapter.startLeScan(this);
} else {
Log.d(TAG, "BluetoothAdapter is null.");
return false;
}
}
return false;
}
/**
* Stops the bluetooth low energy scan.
*/
public void stopScan() {
if (!isReady())
return;
if (mBluetoothAdapter != null)
mBluetoothAdapter.stopLeScan(this);
else {
Log.d(TAG, "BluetoothAdapter is null.");
}
}
@Override
public void onDestroy() {
preferences.edit().shouldScan().put(false).apply();
super.onDestroy();
}
}常量只是用来分发意图、动作和额外名称的字符串。还有另一个首选项存储,它存储扫描阶段应该多长时间,be...You可以轻松地替换它,满足您的需要。
然后,您必须使用与上述操作名称(BleServiceConstants.ACTION_DEVICE_DISCOVERED)匹配的意图筛选器注册广播接收者。
public class DeviceWatcher extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
BluetoothDevice device = intent.getParcelableExtra(BleServiceConstants.EXTRA_DEVICE_DISCOVERED_DEVICE);
// do anything with this information
}
}发布于 2020-01-20 07:17:34
在AOSP回购中找到btif_gatt_client.c,编辑它,
替换
BTM_BleSetScanParams(p_cb->scan_interval, p_cb->scan_window, BTM_BLE_SCAN_MODE_ACTI);使用
BTM_BleSetScanParams(p_cb->scan_interval, p_cb->scan_window, BTM_BLE_SCAN_MODE_PASS);然后建立AOSP,将图像闪存到电话,然后被动扫描工作。
https://stackoverflow.com/questions/24994776
复制相似问题