要解决“Android BluetoothLeScanner在28次后系统范围内启动扫描PendingIntent失败”的问题,您可以考虑使用以下代码示例:
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
import android.support.annotation.RequiresApi;
import android.util.Log;
import java.util.UUID;
public class BluetoothScannerHelper {
private static final String TAG = BluetoothScannerHelper.class.getSimpleName();
private static final int MAX_SCAN_RETRIES = 28;
private static final long SCAN_RETRY_DELAY_MS = 1000;
private Context mContext;
private BluetoothLeScanner mBluetoothLeScanner;
private PendingIntent mScanPendingIntent;
public BluetoothScannerHelper(Context context) {
mContext = context;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void startScan() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
// 创建一个唯一的UUID作为扫描过滤器
UUID scanFilterUuid = UUID.randomUUID();
ParcelUuid parcelUuid = new ParcelUuid(scanFilterUuid);
Intent scanIntent = new Intent(mContext, ScanBroadcastReceiver.class);
scanIntent.putExtra(ScanBroadcastReceiver.EXTRA_SCAN_FILTER, parcelUuid);
mScanPendingIntent = PendingIntent.getBroadcast(mContext, 0, scanIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// 开始扫描
mBluetoothLeScanner.startScan(null, null, mScanPendingIntent);
}
public void stopScan() {
if (mBluetoothLeScanner != null) {
mBluetoothLeScanner.stopScan(mScanPendingIntent);
}
}
// 广播接收器用于接收扫描结果
public static class ScanBroadcastReceiver extends android.content.BroadcastReceiver {
public static final String EXTRA_SCAN_FILTER = "scan_filter";
@Override
public void onReceive(Context context, Intent intent) {
UUID scanFilterUuid = ((ParcelUuid) intent.getParcelableExtra(EXTRA_SCAN_FILTER)).getUuid();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
int bluetoothState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (bluetoothState == BluetoothAdapter.STATE_OFF) {
Log.d(TAG, "Bluetooth is turned off, stopping scan");
stopScan();
}
} else if (BluetoothLeScanner.ACTION_SCAN_RESULT.equals(intent.getAction())) {
ScanResult scanResult = intent.getParcelableExtra(BluetoothLeScanner.EXTRA_SCAN_RESULT);
if (scanResult != null && scanResult.getDevice() != null) {
Log.d(TAG, "Scan result: " + scanResult.getDevice().getName() + ", UUID: " + scanFilterUuid);
}
}
}
}
// 重新启动扫描
private void restartScan() {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
startScan();
}
}, SCAN_RETRY_DELAY_MS);
}
// 扫描回调用于处理扫描失败的情况
private ScanCallback mScanCallback = new ScanCallback() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e(TAG, "Scan failed with error code: " + errorCode);
// 如果扫描失败次数小于最大重试次数,则重新启动扫描
if (errorCode != ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED && errorCode != ScanCallback.SCAN_FAILED_INTERNAL_ERROR) {
if (mRetryCount < MAX_SCAN_RETRIES) {
mRetryCount++;
restartScan();
} else {
Log.e(TAG, "Scan failed after max retries, stopping scan");
stopScan();
}
}
}
};
}
在上述代码示例中:
BluetoothScannerHelper
类是一个辅助类,用于处理蓝牙扫描操作。startScan()
方法用于启动蓝牙LE扫描。它创建一个唯一的UUID作为扫描过滤器,并将其作为额外数据添加到扫描意图中。