簡體   English   中英

如何顯示藍牙設備列表然后連接? 是否可以掃描匹配特性的設備並連接到它?

[英]How to show a list of bluetooth devices and then connect? Is it possible to scan for devices that match a characteristic and connect to it?

我正在嘗試連接到符合特定特征的隨機藍牙設備。 我只想打印來自藍牙設備的傳入消息。

在過去的幾天里,我一直在嘗試嘗試連接到具有某種特性的隨機藍牙設備,以便能夠僅打印來自藍牙設備的消息。

public class main extends AppCompatActivity {

private List Service_UUIDs;
private List Charac_UUIDS;
private List Descriptor_UUIDs;
public static final UUID descriptor = UUID.fromString("863930fc-947c-421b- 
9170-9969ea6ad610");
private BluetoothAdapter bluetoothAdapter = null;
private BluetoothLeScanner bluetoothLeScanner;
private ScanCallback scanCallback;
private TextView messageText;
private Handler handler;
private static final int SCAN_TIME = 15000;
private int connectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTED = 2;
private boolean isConnected;
private boolean isScanning;
private BluetoothLeScanner myScanner;
private BluetoothGatt bluetoothGatt;
private String connected = "";
public List<BluetoothGattService> myServices;
private ScanCallback myScanCallBack;
private BluetoothDevice myDevice;
private HashMap<String, BluetoothDevice> myScanResults;
public final static String ACTION_GATT_SERVICES_DISCOVERED =
        "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
        "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";

public static final int REQUEST_ENABLE_BT = 10;

private void unpairDevice(BluetoothDevice device) {
    try {
        Method m = device.getClass().getMethod("removeBond", (Class[]) 
null);
        m.invoke(device, (Object[]) null);
        Log.d("unpairDevice", Integer.toString(device.getBondState()));
    }
    catch (Exception e) { Log.e("unpairDevice", e.getMessage()); }
}

private void makeToast(String message) {
    //creates pop-ups in UI of the message
    Context context = getApplicationContext();
    CharSequence text = message;
    int duration = Toast.LENGTH_LONG;
    Toast toast = Toast.makeText(context, text, duration);
    toast.show();
}

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    BluetoothManager bluetoothManager = (BluetoothManager) 
getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();

        if(!bluetoothManager.getAdapter().isEnabled()){
            Intent btEnable = new 
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(btEnable, REQUEST_ENABLE_BT);
        }
    messageText = findViewById(R.id.atm_msg);

    findViewById(R.id.scan_button).setOnClickListener(new handleScan());
}

class handleScan implements View.OnClickListener{
    public void onClick(View view){
        startScan();
    }
}

private void startScan() {
    List<ScanFilter> filters = new ArrayList<>();
    ScanFilter scanFilter = new ScanFilter.Builder()
            .setServiceUuid(new ParcelUuid(descriptor))
            .build();
    filters.add(scanFilter);
    ScanSettings settings = new ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
            .build();
    myScanResults = new HashMap<>();
    myScanCallBack = new BtleScanCallback(myScanResults);
    bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
    bluetoothLeScanner.startScan(myScanCallBack);
    isScanning = true;
    new Handler().postDelayed(this::stopScan, SCAN_TIME);
}

private void stopScan(){
    if(isScanning && bluetoothAdapter != null
            && bluetoothAdapter.isEnabled()
            && bluetoothLeScanner != null){
        bluetoothLeScanner.stopScan(myScanCallBack);
        scanComplete();
    }

    myScanCallBack = null;
    isScanning = false;
    handler = null;
}

private void scanComplete(){
    if (myScanResults.isEmpty()){
        return;
    }

    for(BluetoothDevice device: myScanResults.values()){
        connectDevice(device);
    }
}

protected class BtleScanCallback extends ScanCallback {

    private HashMap<String, BluetoothDevice> myScanResults;

    BtleScanCallback(HashMap<String, BluetoothDevice> scanResults) {
        myScanResults = scanResults;
    }

    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        addScanResult(result);
    }

    @Override
    public void onBatchScanResults(List<ScanResult> results) {
        for (ScanResult result : results) {
            addScanResult(result);
        }
    }

    @Override
    public void onScanFailed(int errorCode) {
        makeToast("BLE Scan Failed with code " + errorCode);
    }

    private void addScanResult(ScanResult result) {
        myDevice = result.getDevice();
        String deviceAddress = myDevice.getAddress();
        myScanResults.put(deviceAddress, myDevice);
    }
}

private void connectDevice(BluetoothDevice device) {
    bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback);
}

private final BluetoothGattCallback bluetoothGattCallback = new 
BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int 
newState) {
        super.onConnectionStateChange(gatt, status, newState);
        if (status == gatt.GATT_FAILURE){
            Log.d("BLE_Assistance", "-----> status: " + gatt.GATT_FAILURE);
            disconnectGattServer();
            return;
        }

        if (status == 133){
            bluetoothAdapter.disable();
            bluetoothAdapter.enable();
            Log.d("OCSC: ", "133 GATT_ERROR OCCURRED");
        }
        if (newState == gatt.STATE_CONNECTED){
            Log.d("BLE_Assistance", "-----> state: " + 
gatt.STATE_CONNECTED);
            connectionState = gatt.STATE_CONNECTED;
            isConnected = true;
            return;
        }
        else if (status != gatt.GATT_SUCCESS){
            Log.d("BLE_Assistance", "-----> status: could not connect");
            disconnectGattServer();
            return;
        }
        else if (newState == gatt.STATE_DISCONNECTED){
            Log.d("BLE_Assistance", "status: " + gatt.STATE_DISCONNECTED);
            disconnectGattServer();
        }
    }

    public void disconnectGattServer(){
        isConnected = false;
        connected = "";
        if (bluetoothLeScanner != null && scanCallback != null){
            bluetoothLeScanner.flushPendingScanResults(scanCallback);
        }
        if (!myScanResults.isEmpty()){
            myScanResults.clear();
        }

        try {
            if (myServices.isEmpty()){
                Log.d("Services", "Empty");
            }
            else{
                myServices.clear();
            }
        } catch (NullPointerException nullPointerException){
            Log.d("Services", "" + nullPointerException);
        }

        bluetoothAdapter.cancelDiscovery();

        if(bluetoothGatt != null){
            bluetoothGatt.abortReliableWrite();
            bluetoothGatt.disconnect();
            bluetoothGatt.close();
            bluetoothGatt = null;
            Log.d("disconnect server", ": Disconnected GATT Server");
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        byte[] msg_bytes = characteristic.getValue();

        try {
            String message = new String(msg_bytes, 0, msg_bytes.length, 
 "utf-8");
            Log.d("onCharacteristicRead", message);

            new Handler(Looper.getMainLooper()).postDelayed(() -> {
                makeToast("onCharacteristicRead: " + message);
                messageText.append("\nonCharacteristicRead: " + message);
            }, 1000);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status){
        super.onServicesDiscovered(gatt,status);
        Service_UUIDs = new ArrayList();
        Charac_UUIDS = new ArrayList();
        Descriptor_UUIDs = new ArrayList();
        if(status != gatt.GATT_SUCCESS){
            return;
        }else{
            myServices = gatt.getServices();
            for (BluetoothGattService service : myServices) {
                for (BluetoothGattCharacteristic charac : service.getCharacteristics()) {
                    if (charac.getUuid().toString().contains("863930fc")) {
                        Service_UUIDs.add(charac.getService().getUuid().toString());
                        Charac_UUIDS.add(charac.getUuid().toString());
                        Descriptor_UUIDs.add(descriptor);
                        BluetoothGattDescriptor desc = charac.getDescriptor(descriptor);
                        gatt.setCharacteristicNotification(charac, true);
                        desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                        gatt.writeDescriptor(desc);
                    }
                }
            }
            Log.d("BLE_Assistance", "------ UUID Lists: " + Service_UUIDs + Charac_UUIDS + Descriptor_UUIDs);
        }

    }
};

}

我不太確定,我現在也正在為這種項目而苦苦掙扎,而且我對Android編程還是很陌生。 但是我在您的startScan和stopScan代碼中發現了一個小錯誤

bluetoothLeScanner.startScan(myScanCallBack);

應該

bluetoothLeScanner.startScan(List<ScanFilter> filters, ScanSettings settings, ScanCallback callback) 

與您的掃描過濾器和設置。

當您僅將“ myScanCallback”發送到“ bluetoothLeScanner.startScan”時,您僅發送不帶過濾器的默認參數。

https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#startScan(java.util.List%3Candroid.bluetooth.le.ScanFilter%3E,%20android.bluetooth.le.ScanSettings,% 20android.bluetooth.le.ScanCallback)

這意味着您正在搜索的是每台設備,而不是您想要的設備。

為了在不影響powerdraw的情況下進行測試,您還可以將ScanSettings設置為LOW_LATENCY(LOW_POWER與BLE一起使用更直觀,但不是必需的。如果您希望在掃描時增加電池壽命,可以稍后進行切換)。

希望對您有幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM