Created
July 22, 2023 16:46
-
-
Save Hackin7/2c1adbb14f5d541d54de8541446e3c51 to your computer and use it in GitHub Desktop.
2023_07_22 Notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure to set up your imports properly before this | |
public class BLEClient { | |
private final static String TAG = BLEClient.class.getSimpleName(); | |
public Context context; | |
private String mDeviceName; | |
private String mDeviceAddress; | |
private BluetoothLeService bluetoothService; | |
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = | |
new ArrayList<ArrayList<BluetoothGattCharacteristic>>(); | |
private boolean mConnected = false; | |
private BluetoothGattCharacteristic mNotifyCharacteristic; | |
private ServiceConnection serviceConnection = new ServiceConnection() { | |
@Override | |
public void onServiceConnected(ComponentName name, IBinder service) { | |
bluetoothService = ((BluetoothLeService.LocalBinder) service).getService(); | |
if (bluetoothService != null) { | |
// call functions on service to check connection and connect to devices | |
Log.v(TAG, "Service Retrieved"); | |
if (!bluetoothService.initialize()) { | |
Log.e(TAG, "Unable to initialize Bluetooth"); | |
//context.finish(); | |
} | |
// perform device connection | |
if (!bluetoothService.connect(mDeviceAddress)){ | |
Log.e(TAG, "Cannot Connect"); | |
Toast.makeText(context, "Cannot Connect to Bluetooth Device", Toast.LENGTH_SHORT).show(); | |
}else{ | |
Log.v(TAG, "Connected to BLE"); | |
Toast.makeText(context, "Connected to BLE", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
} | |
@Override | |
public void onServiceDisconnected(ComponentName name) { | |
bluetoothService = null; | |
} | |
}; | |
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { | |
@Override | |
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { | |
if (newState == BluetoothProfile.STATE_CONNECTED) { | |
// successfully connected to the GATT Server | |
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { | |
// disconnected from the GATT Server | |
} | |
} | |
}; | |
public BLEClient(Context context, String mDeviceAddress){ | |
this.context = context; | |
this.mDeviceAddress = mDeviceAddress.toUpperCase(Locale.ROOT); | |
init(); | |
} | |
void init(){ | |
Intent gattServiceIntent = new Intent(context, BluetoothLeService.class); | |
context.bindService(gattServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE); | |
} | |
public List<BluetoothGattService> getServices(){ | |
return bluetoothService.getSupportedGattServices(); | |
} | |
public BluetoothGattCharacteristic getCharacteristic(String serviceUUIDString, int characteristicIndex){ | |
return bluetoothService.getService(UUID.fromString(serviceUUIDString)).getCharacteristics().get(characteristicIndex); | |
} | |
public void read(BluetoothGattCharacteristic characteristic, Function<byte[], Void> readCharacteristicCallback){ | |
bluetoothService.readCharacteristic(characteristic, readCharacteristicCallback); | |
} | |
public void writeInt(BluetoothGattCharacteristic characteristic, int i){ | |
byte[] bytes = ByteBuffer.allocate(4).putInt(i).array(); | |
bluetoothService.writeCharacteristic(characteristic, bytes); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure to set up your imports properly before this | |
public class BluetoothLeService extends Service { | |
private final static String TAG = BluetoothLeService.class.getSimpleName(); | |
private Binder binder = new LocalBinder(); | |
@Nullable | |
@Override | |
public IBinder onBind(Intent intent) { | |
return binder; | |
} | |
class LocalBinder extends Binder { | |
public BluetoothLeService getService() { | |
return BluetoothLeService.this; | |
} | |
} | |
private BluetoothAdapter bluetoothAdapter; | |
public boolean initialize() { | |
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); | |
if (bluetoothAdapter == null) { | |
Log.e(TAG, "Unable to obtain a BluetoothAdapter."); | |
return false; | |
} | |
return true; | |
} | |
private BluetoothGatt bluetoothGatt; | |
private Function<byte[], Void> readCharacteristicCallback; | |
private Function<Void, Void> disconnectedCallback; | |
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { | |
@SuppressLint("MissingPermission") | |
@Override | |
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { | |
if (newState == BluetoothProfile.STATE_CONNECTED) { | |
// successfully connected to the GATT Server | |
// Attempts to discover services after successful connection. | |
gatt.discoverServices(); | |
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { | |
// disconnected from the GATT Server | |
Log.v(TAG, "Disconnected"); | |
//disconnectedCallback.apply(null); | |
} | |
} | |
@Override | |
public void onCharacteristicRead( | |
BluetoothGatt gatt, | |
BluetoothGattCharacteristic characteristic, | |
byte[] data, | |
int status | |
) { | |
if (status == BluetoothGatt.GATT_SUCCESS) { | |
readCharacteristicCallback.apply(data); | |
} | |
} | |
@Override | |
public void onCharacteristicWrite( | |
BluetoothGatt gatt, | |
BluetoothGattCharacteristic characteristic, | |
int status | |
) { | |
if (status == BluetoothGatt.GATT_SUCCESS) { | |
Log.v(TAG, "Written "+ characteristic.toString()); | |
} | |
Log.v(TAG, "Test Write "+ characteristic.toString()+" "+Integer.toString(status)); | |
} | |
}; | |
public boolean connect(final String address) { | |
if (bluetoothAdapter == null || address == null) { | |
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); | |
return false; | |
} | |
try { | |
final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); | |
// connect to the GATT server on the device | |
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { | |
// TODO: Consider calling | |
// ActivityCompat#requestPermissions | |
// here to request the missing permissions, and then overriding | |
// public void onRequestPermissionsResult(int requestCode, String[] permissions, | |
// int[] grantResults) | |
// to handle the case where the user grants the permission. See the documentation | |
// for ActivityCompat#requestPermissions for more details. | |
Log.w(TAG, "No Permissions"); | |
} | |
bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback); | |
return true; | |
} catch (IllegalArgumentException exception) { | |
Log.w(TAG, "Device not found with provided address. Unable to connect."); | |
return false; | |
} | |
} | |
public void setDisconnectedCallback(Function<Void, Void> disconnectedCallback){ | |
this.disconnectedCallback = disconnectedCallback; | |
} | |
public List<BluetoothGattService> getSupportedGattServices() { | |
if (bluetoothGatt == null) return null; | |
return bluetoothGatt.getServices(); | |
} | |
public BluetoothGattService getService(UUID uuid){ | |
return bluetoothGatt.getService(uuid); | |
} | |
@SuppressLint("MissingPermission") | |
public void readCharacteristic(BluetoothGattCharacteristic characteristic, Function<byte[], Void> readCharacteristicCallback) { | |
if (bluetoothGatt == null) { | |
Log.w(TAG, "BluetoothGatt not initialized"); | |
return; | |
} | |
this.readCharacteristicCallback = readCharacteristicCallback; | |
bluetoothGatt.readCharacteristic(characteristic); | |
} | |
// Broken | |
@SuppressLint("MissingPermission") | |
public void writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] value) { | |
Log.w(TAG, "Writing to characteristic"); | |
characteristic.setValue(value); | |
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); | |
bluetoothGatt.writeCharacteristic(characteristic); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure to set up your imports & classes properly before this | |
bleClient = new BLEClient("<ble_device_address>"); | |
// Give it some time before getting services | |
List<BluetoothGattService> services = bleClient.getServices(); | |
for (BluetoothGattService service : services){ | |
Log.v("BLEClient", service.toString()+" "+service.getUuid().toString()); | |
for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()){ | |
Log.v("BLEClient", " - " + characteristic.toString() + " " + characteristic.getUuid()); | |
} | |
} | |
// Read | |
bleClient.read( | |
bleClient.getCharacteristic("<ble_device_address>", <index_of_characteristic>), | |
data -> { | |
Log.v("BLEClient", new BigInteger(1, data).toString(16)); | |
return null; | |
} | |
); | |
// Write - Not fully tested | |
bleClient.writeInt( | |
bleClient.getCharacteristic( | |
"<ble_device_address>", | |
index_of_characteristic> | |
integer_data | |
) | |
); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment