GenericAudioBT: Add battery level

Add a listener to get the current battery level of the audio device.

Also prevent the spurious notification about missing firmware and hardware version.
This commit is contained in:
Daniele Gobbetti
2025-04-07 14:57:32 +02:00
parent f000171535
commit cf18f01f25
@@ -3,22 +3,49 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.generic_headphones;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothDisconnectReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothDisconnectReceiver;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.HeadphoneHelper; import nodomain.freeyourgadget.gadgetbridge.service.HeadphoneHelper;
public class GenericHeadphonesSupport extends AbstractDeviceSupport implements HeadphoneHelper.Callback { public class GenericHeadphonesSupport extends AbstractDeviceSupport implements HeadphoneHelper.Callback {
//the following constants are annotated as systemApi, hence cannot be referenced directly
//they are reported as working in https://community.home-assistant.io/t/bluetooth-battery-levels-android/661525
private static final String ANDROID_BLUETOOTH_DEVICE_EXTRA_BATTERY_LEVEL = "android.bluetooth.device.extra.BATTERY_LEVEL";
private static final String ANDROID_BLUETOOTH_DEVICE_ACTION_BATTERY_LEVEL_CHANGED = "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
private HeadphoneHelper headphoneHelper; private HeadphoneHelper headphoneHelper;
private BluetoothDisconnectReceiver mBlueToothDisconnectReceiver = null; private BluetoothDisconnectReceiver mBlueToothDisconnectReceiver = null;
private final BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (GBApplication.isRunningPieOrLater()) {
final String action = intent.getAction();
if (ANDROID_BLUETOOTH_DEVICE_ACTION_BATTERY_LEVEL_CHANGED.equals(action)) {
final int batteryLevel = intent.getIntExtra(ANDROID_BLUETOOTH_DEVICE_EXTRA_BATTERY_LEVEL, -1);
final GBDeviceEventBatteryInfo eventBatteryInfo = new GBDeviceEventBatteryInfo();
eventBatteryInfo.state = batteryLevel == -1 ? BatteryState.UNKNOWN : BatteryState.BATTERY_NORMAL;
eventBatteryInfo.level = batteryLevel;
evaluateGBDeviceEvent(eventBatteryInfo);
}
}
}
};
private final BluetoothProfile.ServiceListener profileListener = new BluetoothProfile.ServiceListener() { private final BluetoothProfile.ServiceListener profileListener = new BluetoothProfile.ServiceListener() {
@Override @Override
public void onServiceConnected(int profile, BluetoothProfile proxy) { public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -64,7 +91,7 @@ public class GenericHeadphonesSupport extends AbstractDeviceSupport implements H
getContext().unregisterReceiver(mBlueToothDisconnectReceiver); getContext().unregisterReceiver(mBlueToothDisconnectReceiver);
mBlueToothDisconnectReceiver = null; mBlueToothDisconnectReceiver = null;
} }
getContext().unregisterReceiver(batteryLevelReceiver);
} }
@Override @Override
@@ -75,8 +102,16 @@ public class GenericHeadphonesSupport extends AbstractDeviceSupport implements H
gbDevice.setState(GBDevice.State.CONNECTING); gbDevice.setState(GBDevice.State.CONNECTING);
gbDevice.sendDeviceUpdateIntent(getContext(), GBDevice.DeviceUpdateSubject.CONNECTION_STATE); gbDevice.sendDeviceUpdateIntent(getContext(), GBDevice.DeviceUpdateSubject.CONNECTION_STATE);
final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
versionCmd.fwVersion2 = "N/A";
handleGBDeviceEvent(versionCmd);
getBluetoothAdapter().getProfileProxy(getContext(), profileListener, BluetoothProfile.HEADSET); getBluetoothAdapter().getProfileProxy(getContext(), profileListener, BluetoothProfile.HEADSET);
if (GBApplication.isRunningPieOrLater()) {
ContextCompat.registerReceiver(getContext(), batteryLevelReceiver, new IntentFilter(ANDROID_BLUETOOTH_DEVICE_ACTION_BATTERY_LEVEL_CHANGED), ContextCompat.RECEIVER_EXPORTED);
}
mBlueToothDisconnectReceiver = new BluetoothDisconnectReceiver(); mBlueToothDisconnectReceiver = new BluetoothDisconnectReceiver();
ContextCompat.registerReceiver(getContext(), mBlueToothDisconnectReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED), ContextCompat.RECEIVER_EXPORTED); ContextCompat.registerReceiver(getContext(), mBlueToothDisconnectReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED), ContextCompat.RECEIVER_EXPORTED);
return true; return true;