Reputation: 809
I am trying to connect to a BLE device and then stay connected to it (as I have to write to a characteristic approx 1 time per second.
Although I can successfully connect to the device as evidenced by being able to see this log System.out.println("dev connected..");
, I get an exception whenever I call send message. The exception tells me that finalGatt
is a null object reference. (See code and error below).
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;
}
}
The exception:
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)
I execute it like this from another class:
bles = new BluetoothLeService2(app);
bles.sendMessage();
Where am I going wrong? Maybe I have to do it another way?
Thank you for your help.
Upvotes: 2
Views: 415
Reputation: 1088
You didn't show when and how do you call sendMessage
in which the exception is thrown. Most probably you do it before onServicesDiscovered
is called because only there finalGatt
value is set.
Upvotes: 3