Android BLE在onScanResult中发现自定义服务,但不在onServicesDiscovered中

时间:2019-02-08 13:28:55

标签: android bluetooth bluetooth-lowenergy android-bluetooth

我正在尝试通过蓝牙低功耗连接两个Android设备(带有Android 7的Galaxy J5和带有Android 6.0.1的Redmi Note 3),因此Galaxy充当外围设备,而Redmi充当中央设备。

我称Galaxy为“ XY”。我希望Redmi在我创建的自定义服务中编写一些内容,然后使Galaxy显示Toast。

我或多或少地遵循了本教程http://nilhcem.com/android-things/bluetooth-low-energy,并尝试了一些我在其他答案中看到的修复程序,例如在BluetoothGatt的每个操作之间增加了延迟,但到目前为止没有任何效果。

在ScanCallback中,当我调用System.out.println(result.getScanRecord().getServiceUuids())时,它会打印我的服务的UUID,但是在onServicesDiscovered中,当我调用BluetoothGattCharacteristic characteristic = gatt.getService(SERVICE_UUID).getCharacteristic(WRITE_UUID);时,它会给我一个NullPointerException,如果我打印每个服务UUID,它永远不会显示我的自定义服务UUID。

这是代码:

public class MainActivity extends AppCompatActivity {

public Context mContext;
public BluetoothAdapter bt;
public final int REQUEST_ENABLE_BT = 1;
public BluetoothLeScanner LEScanner;
public BluetoothGatt mGatt;
public boolean scanning;
public Handler mHandler = new Handler();
public static final long SCAN_PERIOD = 10000; //ms
public List<BluetoothDevice> LEDevices = new ArrayList<>();
public final UUID SERVICE_ID = UUID.fromString("36afe8c7-a825-4ac0-b06c-0279645421c6");
public final UUID SERVICE_UUID = UUID.fromString("6907ff35-cc36-4872-a5a6-c01a4b3017bc");
public final UUID WRITE_UUID = UUID.fromString("64e68646-8257-4e1e-a697-1cbc07488e05");
public Button clientButton, serverButton;
public boolean connecting = false;
//Server
public BluetoothGattServer mGattServer;
public BluetoothGattCallback gattCallback;
public BluetoothLeAdvertiser advertiser;
public AdvertiseSettings settings = new AdvertiseSettings.Builder().setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
        .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH).setConnectable(false).setTimeout(0).build();
public ParcelUuid pUuid = new ParcelUuid(SERVICE_ID);
public AdvertiseData data = new AdvertiseData.Builder().setIncludeDeviceName(true).addServiceUuid(pUuid).setIncludeTxPowerLevel(false).build();
public BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
    @Override
    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
        if (characteristic.getUuid().equals(WRITE_UUID)) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(mContext, "Hey, its redmi!", Toast.LENGTH_SHORT);
                }
            });
        }
    }
};
public AdvertiseCallback advertisingCallback = new AdvertiseCallback() {
    @Override
    public void onStartSuccess(AdvertiseSettings settingsInEffect) {
        super.onStartSuccess(settingsInEffect);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(mContext, "Comenzado con MAC " + bt.getAddress() + ";", Toast.LENGTH_SHORT).show();
            }
        });

        mGattServer = ((BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE)).openGattServer(mContext, mGattServerCallback);
        final BluetoothGattService service = createService();
        mGattServer.addService(service);
        System.out.println(mGattServer.getServices().get(0).getUuid());
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(mContext, "Service UUID: " + mGattServer.getServices().get(0).getUuid(), Toast.LENGTH_SHORT).show();
                Toast.makeText(mContext, "Characteristic UUID: " + mGattServer.getServices().get(0).getCharacteristics().get(0).getUuid(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onStartFailure(int errorCode) {
        super.onStartFailure(errorCode);
        System.out.println(errorCode);
    }
};

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

    clientButton = findViewById(R.id.clientButton);
    serverButton = findViewById(R.id.serverButton);

    if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        Toast.makeText(this, "BLE not supported, exiting...", Toast.LENGTH_SHORT).show();
        finish();
    }

    bt = ((BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
    if(bt == null || !bt.isEnabled()) {
        Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBT, REQUEST_ENABLE_BT);
    }

    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION}, 1);

    LEScanner = bt.getBluetoothLeScanner();
    advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();

    clientButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            scanLeDevice(true);
        }
    });

    serverButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    advertiser.startAdvertising(settings, data, advertisingCallback);
                }
            });
        }
    });

    gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if(newState == BluetoothProfile.STATE_CONNECTED){
                scanLeDevice(false);
                System.out.println("********** DISCOVERING **********");
                SystemClock.sleep(3000);
                gatt.discoverServices();
                System.out.println("Discovered");
            }
            else{
                scanLeDevice(false);
                gatt.close();
                scanLeDevice(true);
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if(status == BluetoothGatt.GATT_SUCCESS){
                SystemClock.sleep(3000);
                System.out.println("Success discovering: writing");
                //TODO: NOT WORKING
                BluetoothGattCharacteristic characteristic = gatt.getService(SERVICE_UUID).getCharacteristic(WRITE_UUID);
                System.out.println(characteristic.toString());
                //System.exit(0);
                /*System.out.println(gatt.getService(SERVICE_UUID).toString());
                BluetoothGattCharacteristic writeChar = gatt.getService(SERVICE_UUID).getCharacteristic(WRITE_UUID);
                byte[] data = new byte[10];
                writeChar.setValue(data);
                gatt.writeCharacteristic(writeChar);
                System.out.println("WRITTEN DATA");*/
            }
            else{
                System.out.println(status);
                scanLeDevice(false);
            }
        }
    };
}

private ScanCallback LEScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        if(!connecting) {
            if (result == null || result.getDevice() == null || result.getScanRecord().getDeviceName() == null)
                return;
            System.out.println("******* ON SCAN RESULT ********");
            System.out.println(result.getScanRecord().getDeviceName());
            System.out.println(result.getScanRecord().getServiceUuids());
            System.out.println(result.getScanRecord().getAdvertiseFlags());
            System.out.println(result.getDevice().toString());
            System.out.println(result.getDevice().getAddress());
            if (result.getScanRecord().getDeviceName().equals("XY")) {
                connecting = true;
                System.out.println("******** DEVICE FOUND *********");
                System.out.println(result.getDevice().toString());
                connectToDeviceLE(result.getDevice().getAddress());
            }
        }
    }

    @Override
    public void onBatchScanResults(List<ScanResult> results) {
        super.onBatchScanResults(results);
        System.out.println("******* ON BATCH SCAN RESULT ********");
        for (ScanResult sr : results){
            System.out.println(sr.toString());
        }
    }

    @Override
    public void onScanFailed(int errorCode) {
        System.out.println("******* ON SCAN FAILED ********");
    }
};

private void scanLeDevice(final boolean enable){
    if(enable){
        mHandler.postDelayed(new Runnable(){
            @Override
            public void run() {
                scanning = false;
                LEScanner.stopScan(LEScanCallback);
                connecting = false;
            }
        }, SCAN_PERIOD);
        scanning = true;
        LEScanner.startScan(LEScanCallback);
    }
    else{
        scanning = false;
        LEScanner.stopScan(LEScanCallback);
        connecting = false;
    }
}

public void connectToDeviceLE(String deviceAddress){
    final BluetoothDevice device = bt.getRemoteDevice(deviceAddress);
    scanLeDevice(false);
    SystemClock.sleep(3000);
    mGatt = device.connectGatt(mContext, false, gattCallback);
    //System.out.println(mGatt.toString());

}

private BluetoothGattService createService(){
    BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
    BluetoothGattCharacteristic interactor = new BluetoothGattCharacteristic(WRITE_UUID,
            BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, BluetoothGattCharacteristic.PERMISSION_WRITE);
    service.addCharacteristic(interactor);
    return service;
}

0 个答案:

没有答案