不能写给BLE GattCharacteristic

时间:2018-01-18 13:01:25

标签: java android bluetooth-lowenergy

我正在尝试连接到BLE设备然后保持连接(因为我必须每秒写入一个特性大约1次。 虽然我可以成功连接到设备,因为能够看到此日志System.out.println("dev connected..");,但每当我调用发送消息时,我都会收到异常。异常告诉我finalGatt是一个空对象引用。 (参见下面的代码和错误)。

public class BluetoothLeService2 extends Service {
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothLeScanner mLEScanner;
    private ScanSettings settings;
    private List<ScanFilter> filters;
    private BluetoothGatt mGatt;
    private BluetoothGatt finalGatt;
    private Application app;

    final BluetoothManager bluetoothManager;

    BluetoothLeService2(Application app) throws NullPointerException {
        this.app = app;
        bluetoothManager =
                (BluetoothManager) app.getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();


        mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
        settings = new ScanSettings.Builder()
                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                .build();
        filters = new ArrayList<>();
        scanLeDevice(true);
    }



    private void scanLeDevice(final boolean enable) {
        if (enable) {
                mLEScanner.startScan(filters, settings, mScanCallback);
        } else {
                mLEScanner.stopScan(mScanCallback);
        }
    }


    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            BluetoothDevice btDevice = result.getDevice();
            try {
                if(btDevice.getAddress().equals("mac")){
                    connectToDevice(btDevice);
                    scanLeDevice(false);
                }
            } catch (NullPointerException e) {
                //NULL
            }
        }

    };



    private void connectToDevice(final BluetoothDevice device) {
        new Thread(new Runnable() {
            public void run() {
                while(true) {              //keep device connected
                    if (mGatt == null) {
                        mGatt = device.connectGatt(app, true, gattCallback);
                        scanLeDevice(false);
                    }

                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }


    public void sendMessage() {
            try {
                List<BluetoothGattService> bgsList = finalGatt.getServices();
                BluetoothGattService mSVC = bgsList.get(3);
                List<BluetoothGattCharacteristic> bgcList = mSVC.getCharacteristics();
                BluetoothGattCharacteristic mCH = bgcList.get(0);
                mCH.setValue(Base64.decode("sth".getBytes(), Base64.URL_SAFE));
                if (bluetoothManager.getConnectionState(finalGatt.getDevice(), BluetoothGatt.GATT) == 0) {
                    connectToDevice(finalGatt.getDevice());
                    return;
                }
            } catch (Exception e) {
                Log.wtf("connection", "dev not connected");
            }
        }
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            switch (newState) {
                case BluetoothProfile.STATE_CONNECTED:                        
                    if(gatt.getDevice().getAddress().equals("mac")) {
                        gatt.discoverServices();
                    }
            }

        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            List<BluetoothGattService> services = gatt.getServices();
            if (status == BluetoothGatt.GATT_SUCCESS) {
               if(gatt.getDevice().getAddress().equals("mac")){
                    finalGatt = gatt;
                    connectToDevice(finalGatt.getDevice());
                    System.out.println("dev connected..");
                    scanLeDevice(false);
                }
            }
        }

    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

例外:

Attempt to invoke virtual method 'java.util.List android.bluetooth.BluetoothGatt.getServices()' on a null object reference
  java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List android.bluetooth.BluetoothGatt.getServices()' on a null object reference
      at com.faebl.BluetoothLeService2.sendMessage(BluetoothLeService2.java:135)
      at com.faebl.Activator.execute(Activator.java:56)
      at com.faebl.Activator.doInBackground(Activator.java:42)
      at android.os.AsyncTask$2.call(AsyncTask.java:295)
      at java.util.concurrent.FutureTask.run(FutureTask.java:237)
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
      at java.lang.Thread.run(Thread.java:818)

我从另一个类执行它:

bles = new BluetoothLeService2(app);
bles.sendMessage();

我哪里错了?也许我必须以另一种方式做到这一点?

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

您没有显示何时以及如何调用引发异常的sendMessage。最有可能是在调用onServicesDiscovered之前执行此操作,因为只设置了finalGatt值。