I'm a begginner on Bluetooth LE, I can scan all Bluetooth Device but I can't connect to the device. I got an error and I don't know where I'm wrong. I'm not sure if I use the good method to connect to another device, the Android doc is not very clear. I try to create an application to scan all device, when i get the device i wanted, the application automatically connect to the device without click on a button or other stuff.
MainActivity (I scan all device and take only the device i needed)
public class MainActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
{
Toast.makeText(this, "BLE not supported", Toast.LENGTH_SHORT).show();
finish();
}
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
if(bluetoothAdapter == null)
{
Toast.makeText(this, "Bluetooth not supported", Toast.LENGTH_SHORT).show();
finish();
return;
}
scanLeDevice();
}
private BluetoothLeScanner bluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
private boolean mScanning;
private Handler handler = new Handler();
private static final long SCAN_PERIOD = 1000;
private void scanLeDevice()
{
if(!mScanning)
{
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
mScanning = false;
bluetoothLeScanner.stopScan(leScanCallBack);
}
}, SCAN_PERIOD);
mScanning = true;
bluetoothLeScanner.startScan(leScanCallBack);
}
else
{
mScanning = false;
bluetoothLeScanner.stopScan(leScanCallBack);
}
}
private String Device_name = "";
private String Device_address;
private ScanCallback leScanCallBack = new ScanCallback()
{
@Override
public void onScanResult(int callbackType, ScanResult result)
{
super.onScanResult(callbackType, result);
if(result.getDevice().getName() != null && result.getDevice().getName().contains("ETNA") && result.getDevice().getName() != Device_name)
{
Device_name = String.valueOf(result.getDevice().getName());
Device_address = String.valueOf(result.getDevice().getAddress());
BluetoothLeService blService = new BluetoothLeService();
blService.connect(Device_address);
Log.e("Device Name : ", Device_name);
Log.e("Device address", Device_address);
Button button = findViewById(R.id.button);
button.setText(Device_name);
}
}
};}
BluetoothLeService use to get the connection state and connect to a device :
public class BluetoothLeService extends Service
{
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private String bluetoothDeviceAddress;
private BluetoothGatt bluetoothGatt;
private int connectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
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 final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA";
public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback()
{
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
{
String intentAction;
if(newState == BluetoothProfile.STATE_CONNECTED)
{
intentAction = ACTION_GATT_CONNECTED;
connectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attemping to start service discovery:" + bluetoothGatt.discoverServices());
}
else if(newState == BluetoothProfile.STATE_DISCONNECTED)
{
intentAction = ACTION_GATT_DISCONNECTED;
connectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status)
{
if(status == BluetoothGatt.GATT_SUCCESS)
{
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
}
else
{
Log.i(TAG, "onServiceDiscovered received: " + status);
}
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
{
if(status == BluetoothGatt.GATT_SUCCESS)
{
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
};
private void broadcastUpdate(final String action)
{
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic)
{
final Intent intent = new Intent(action);
if(UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid()))
{
int flag = characteristic.getProperties();
int format = -1;
if((flag & 0x01) != 0)
{
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "HEART RATE FORMAT UINT16.");
}
else
{
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "HEART RATE FORMAT UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
}
else
{
final byte[] data = characteristic.getValue();
if(data != null && data.length > 0)
{
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
{
stringBuilder.append(String.format("%02X ", byteChar));
}
String data_string = new String(data) + "
" + stringBuilder.toString();
Log.d(TAG, data_string);
intent.putExtra(EXTRA_DATA, data_string);
}
}
sendBroadcast(intent);
}
@Nullable
@Override
public IBinder onBind(Intent intent)
{
return null;
}
public boolean connect(final String address)
{
final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if(device == null)
{
Log.e(TAG, "Device not found");
return false;
}
bluetoothGatt = device.connectGatt(this, false, gattCallback);
Log.e(TAG, "Trying to create a new connection");
connectionState = STATE_CONNECTING;
return true;
}}
Error :
FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 14400
java.lang.NullPointerException: Attempt to invoke virtual method 'android.bluetooth.BluetoothDevice android.bluetooth.BluetoothAdapter.getRemoteDevice(java.lang.String)' on a null object reference
at com.example.myapplication.BluetoothLeService.connect(BluetoothLeService.java:139)
at com.example.myapplication.MainActivity$2.onScanResult(MainActivity.java:96)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:650)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)