mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Add OS battery level to DeviceCoordinator and BluetoothStateChangeReceiver
Add OS Battery Level detection to BluetoothStateChangeReceiver, pass the event to devices only if their coordinator class declares support for it. Add supportsOSBatteryLevel() to DeviceCoordinator and AbstractDeviceCoordinator defaulting to false. Change coordinator of GenericHeadphones to return true for supportsOSBatteryLevel() and remove specific BroadcastReceiver from the support class.
This commit is contained in:
@@ -263,7 +263,11 @@ public class GBApplication extends Application {
|
||||
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (isRunningOreoOrLater()) {
|
||||
bluetoothStateChangeReceiver = new BluetoothStateChangeReceiver();
|
||||
registerReceiver(bluetoothStateChangeReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
final IntentFilter bif = new IntentFilter();
|
||||
bif.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
|
||||
if (isRunningPieOrLater())
|
||||
bif.addAction(BluetoothStateChangeReceiver.ANDROID_BLUETOOTH_DEVICE_ACTION_BATTERY_LEVEL_CHANGED);
|
||||
registerReceiver(bluetoothStateChangeReceiver, bif);
|
||||
}
|
||||
try {
|
||||
//the following will ensure the notification manager is kept alive
|
||||
|
||||
+4
@@ -854,6 +854,10 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
||||
return batteryConfigs;
|
||||
}
|
||||
|
||||
public boolean supportsOSBatteryLevel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addBatteryPollingSettings() {
|
||||
return false;
|
||||
|
||||
@@ -786,6 +786,12 @@ public interface DeviceCoordinator {
|
||||
|
||||
BatteryConfig[] getBatteryConfig(GBDevice device);
|
||||
|
||||
/**
|
||||
* Returns true if the device battery level is reported by the OS (usually for headsets)
|
||||
*/
|
||||
boolean supportsOSBatteryLevel();
|
||||
|
||||
|
||||
boolean addBatteryPollingSettings();
|
||||
|
||||
boolean supportsPowerOff(GBDevice device);
|
||||
|
||||
+5
@@ -90,4 +90,9 @@ public class GenericHeadphonesCoordinator extends AbstractDeviceCoordinator {
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_headphones);
|
||||
return deviceSpecificSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsOSBatteryLevel() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+37
@@ -18,6 +18,7 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -27,11 +28,18 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||
|
||||
public class BluetoothStateChangeReceiver extends BroadcastReceiver {
|
||||
//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
|
||||
public static final String ANDROID_BLUETOOTH_DEVICE_EXTRA_BATTERY_LEVEL = "android.bluetooth.device.extra.BATTERY_LEVEL";
|
||||
public static final String ANDROID_BLUETOOTH_DEVICE_ACTION_BATTERY_LEVEL_CHANGED = "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BluetoothStateChangeReceiver.class);
|
||||
|
||||
@Override
|
||||
@@ -65,6 +73,35 @@ public class BluetoothStateChangeReceiver extends BroadcastReceiver {
|
||||
LOG.info("Bluetooth turned off => disconnecting...");
|
||||
GBApplication.deviceService().disconnect();
|
||||
}
|
||||
} else if (ANDROID_BLUETOOTH_DEVICE_ACTION_BATTERY_LEVEL_CHANGED.equals(action)) {
|
||||
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
if (device == null) {
|
||||
LOG.error("Got no device for {}", action);
|
||||
return;
|
||||
}
|
||||
|
||||
final GBDevice gbDevice = GBApplication.app().getDeviceManager().getDeviceByAddress(device.getAddress());
|
||||
if (gbDevice == null) {
|
||||
LOG.info("Bluetooth device {} unknown", device.getAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbDevice.getState() != GBDevice.State.INITIALIZED) {
|
||||
LOG.info("gbDevice {} not initialized, ignoring incoming battery information.", gbDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gbDevice.getDeviceCoordinator().supportsOSBatteryLevel()) {
|
||||
LOG.info("gbDevice {} does not support OS battery provided levels, ignoring incoming battery information.", gbDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
eventBatteryInfo.evaluate(context, gbDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-35
@@ -3,33 +3,23 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.generic_headphones;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
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.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.HeadphoneHelper;
|
||||
|
||||
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 BluetoothDisconnectReceiver mBlueToothDisconnectReceiver = null;
|
||||
private BroadcastReceiver batteryLevelReceiver = null;
|
||||
|
||||
private final BluetoothProfile.ServiceListener profileListener = new BluetoothProfile.ServiceListener() {
|
||||
@Override
|
||||
@@ -76,10 +66,6 @@ public class GenericHeadphonesSupport extends AbstractDeviceSupport implements H
|
||||
getContext().unregisterReceiver(mBlueToothDisconnectReceiver);
|
||||
mBlueToothDisconnectReceiver = null;
|
||||
}
|
||||
if (batteryLevelReceiver != null) {
|
||||
getContext().unregisterReceiver(batteryLevelReceiver);
|
||||
batteryLevelReceiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,27 +82,6 @@ public class GenericHeadphonesSupport extends AbstractDeviceSupport implements H
|
||||
|
||||
getBluetoothAdapter().getProfileProxy(getContext(), profileListener, BluetoothProfile.HEADSET);
|
||||
|
||||
if (GBApplication.isRunningPieOrLater()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
ContextCompat.registerReceiver(getContext(), batteryLevelReceiver, new IntentFilter(ANDROID_BLUETOOTH_DEVICE_ACTION_BATTERY_LEVEL_CHANGED), ContextCompat.RECEIVER_EXPORTED);
|
||||
}
|
||||
|
||||
mBlueToothDisconnectReceiver = new BluetoothDisconnectReceiver();
|
||||
ContextCompat.registerReceiver(getContext(), mBlueToothDisconnectReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED), ContextCompat.RECEIVER_EXPORTED);
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user