androidbluetoothbluetooth-lowenergyandroid-bluetoothinput-devices

How to get battery level of a game controller from an Android application


I have developed an Android application that connects via Bluetooth to a gamepad controller and shows button presses, joy stick movements, etc made on the handheld controller on the Android device.

Application and source code are on Github here: https://github.com/portsample/gamecontroller

An elusive goal of this endeavor has been having battery state of the gamepad controller captured by the application and shown on the Android device. This may or may not be possible using the Google Android API for SDK 33 or more recent. Any suggestions or advice would be highly appreciated.

May 3, 2024 Update: This is close,

 private int getBatteryLevel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        int[] deviceIds = InputDevice.getDeviceIds();
        for (int deviceId : deviceIds) {
            InputDevice inputDevice = InputDevice.getDevice(deviceId);
            if (inputDevice != null && (inputDevice.getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) {
                //float batteryLevel = inputDevice.getBatteryCapacity();
                float batteryLevel = inputDevice.getBatteryState();
                //float batteryLevel = 27;
                return (int) (batteryLevel * 100); // Convert battery level to percentage
            }
        }
    }
    return -1; // Battery level not available
}

But still no cigar. Error message is,

error: incompatible types: BatteryState cannot be converted to float
                float batteryLevel = inputDevice.getBatteryState();

How to do this with BatteryState() object and GetCapacity() function?


Solution

  • This works.

    
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothGatt;
    import android.bluetooth.BluetoothGattCallback;
    import android.bluetooth.BluetoothGattCharacteristic;
    import android.bluetooth.BluetoothGattService;
    import android.content.Context;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.Toast;
    import androidx.appcompat.app.AppCompatActivity;
    import java.util.UUID;
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "GamepadBattery";
        private static final UUID BATTERY_SERVICE_UUID = UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb");
        private static final UUID BATTERY_LEVEL_UUID = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb");
        private BluetoothAdapter bluetoothAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            getBatteryLevel();
        }
    
        private void getBatteryLevel() {
            BluetoothDevice device = getXboxController();
            if (device == null) {
                Log.e(TAG, "No Xbox controller found.");
                Toast.makeText(this, "No Xbox controller found.", Toast.LENGTH_SHORT).show();
                return;
            }
    
            device.connectGatt(this, false, new BluetoothGattCallback() {
                @Override
                public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        BluetoothGattService batteryService = gatt.getService(BATTERY_SERVICE_UUID);
                        if (batteryService != null) {
                            BluetoothGattCharacteristic batteryLevelChar = batteryService.getCharacteristic(BATTERY_LEVEL_UUID);
                            if (batteryLevelChar != null) {
                                gatt.readCharacteristic(batteryLevelChar);
                            }
                        }
                    }
                }
    
                @Override
                public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS && BATTERY_LEVEL_UUID.equals(characteristic.getUuid())) {
                        int batteryLevel = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
                        Toast.makeText(MainActivity.this, "Battery level is " + batteryLevel + "%", Toast.LENGTH_LONG).show();
                        gatt.close();
                    }
                }
            });
        }
    
        private BluetoothDevice getXboxController() {
            if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                return null;
            }
    
            for (BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
                if (device.getName() != null && device.getName().toLowerCase().contains("xbox")) {
                    return device;
                }
            }
            return null;
        }
    }