startLeScan在API21中有所体现

时间:2015-07-09 13:05:27

标签: android bluetooth-lowenergy android-bluetooth

我正在开发一个使用蓝牙低功耗的Android应用程序。我使用了类BluetoothAdapter但现在在API-21中,类是BluetoothLeScanner我的旧代码实现了接口BluetoothAdapter.LeScanCallback我现在必须实现什么接口?或者我可以做另一种解决方案吗? 我们不推荐使用stopLeScanstartLeScan这两种方法,这就是为什么我要使用类BluetoothLeScanner,而是让方法启动和停止。

这是我班级的代码:

public class BleDevicesScanner implements Runnable, BluetoothAdapter.LeScanCallback {
    private static final String TAG = BleDevicesScanner.class.getSimpleName();

    private static final long DEFAULT_SCAN_PERIOD = 500L;
    public static final long PERIOD_SCAN_ONCE = -1;

    private final BluetoothAdapter bluetoothAdapter;
    private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
    private final LeScansPoster leScansPoster;

    private long scanPeriod = DEFAULT_SCAN_PERIOD;
    private Thread scanThread;
    private volatile boolean isScanning = false;

    public BleDevicesScanner(BluetoothAdapter adapter, BluetoothAdapter.LeScanCallback callback) {
        if (adapter == null)
            throw new IllegalArgumentException("Adapter should not be null");

        bluetoothAdapter = adapter;

        leScansPoster = new LeScansPoster(callback);
    }

    public synchronized void setScanPeriod(long scanPeriod) {
        this.scanPeriod = scanPeriod < 0 ? PERIOD_SCAN_ONCE : scanPeriod;
    }

    public boolean isScanning() {
        return scanThread != null && scanThread.isAlive();
    }

    public synchronized void start() {
        if (isScanning())
            return;

        if (scanThread != null) {
            scanThread.interrupt();
        }
        scanThread = new Thread(this);
        scanThread.setName(TAG);
        scanThread.start();
    }

    public synchronized void stop() {
        isScanning = false;
        if (scanThread != null) {
            scanThread.interrupt();
            scanThread = null;
        }
        bluetoothAdapter.stopLeScan(this);
    }

    @Override
    public void run() {
        try {
            isScanning = true;
            do {
                synchronized (this) {
                    bluetoothAdapter.startLeScan(this);
                }

                if (scanPeriod > 0)
                    Thread.sleep(scanPeriod);

                synchronized (this) {
                    bluetoothAdapter.stopLeScan(this);
                }
            } while (isScanning && scanPeriod > 0);
        } catch (InterruptedException ignore) {
        } finally {
            synchronized (this) {
                bluetoothAdapter.stopLeScan(this);
            }
        }
    }

    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
        synchronized (leScansPoster) {
            leScansPoster.set(device, rssi, scanRecord);
            mainThreadHandler.post(leScansPoster);
        }
    }

    private static class LeScansPoster implements Runnable {
        private final BluetoothAdapter.LeScanCallback leScanCallback;

        private BluetoothDevice device;
        private int rssi;
        private byte[] scanRecord;

        private LeScansPoster(BluetoothAdapter.LeScanCallback leScanCallback) {
            this.leScanCallback = leScanCallback;
        }

        public void set(BluetoothDevice device, int rssi, byte[] scanRecord) {
            this.device = device;
            this.rssi = rssi;
            this.scanRecord = scanRecord;
        }

        @Override
        public void run() {
            leScanCallback.onLeScan(device, rssi, scanRecord);
        }
    }
}

2 个答案:

答案 0 :(得分:3)

在5.0上有可用的apis,在较低版本上缺少。我建议使用目标sdk 22(最新版)构建应用程序。 i)使用不同的apis在不同版本中获得相同的结果。就像手机运行低于Android 5.0一样,使用startScan,否则使用startLEScan。 ii)Android 5.0和5.1也有差异,因此请相应地使用这些方法。像startScan这样的apis已被弃用,但我知道,他们仍然在工作,因为他们已经将它们与新api绑在一起了。所以在他们删除旧的api之前,他们将在所有平台上工作。这正是弃用意味着:)

因此,您可以根据SDK版本调用相应的api。您可以通过android.os.Build.VERSION.SDK_INT在运行时获得SDK版本,所以尝试这样做:

if(android.os.Build.VERSION.SDK_INT<21) 
bluetoothAdapter.startLeScan(this); 
else{ 
bluetoothLeScanner.startScan(callBack); 
}

答案 1 :(得分:2)

Android documenation描述了使用新的BluetoothAdapter startScan()方法:

public void startScan (List<ScanFilter> filters, ScanSettings settings, ScanCallback callback)

您可以为API级别21及更高版本创建BleDevicesScannerV21课程,该课程使用ScanCallback代替BluetoothAdapter.LeScanCallback