2

I'm trying to run some code every time the charger gets connected to the device and the app is closed. The only thing I've found is to schedule a job that only can run when the charger is connected, but the problem with that is that the code will only run once (unless I reschedule it ofc) and it will only run at the set times. I want the code to run immediately and every time I connect the charger, like a broadcastlistener, but in the background.

Is this possible or do you have some other suggestions?

Thanks in advance! :)

EDIT: It seems like you can't listen to these kinds of broadcasts anymore if you're running API level 26+ ref

Slimez
  • 557
  • 1
  • 7
  • 21

3 Answers3

3

The BatteryManager broadcasts an action whenever the device is connected or disconnected from power. It's important to receive these events even while your app isn't running—particularly as these events should impact how often you start your app in order to initiate a background update—so you should register a BroadcastReceiver in your manifest to listen for both events by defining the ACTION_POWER_CONNECTED and ACTION_POWER_DISCONNECTED within an intent filter.

<receiver android:name=".PowerConnectionReceiver">
  <intent-filter>
    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
  </intent-filter>
</receiver>

Within the associated BroadcastReceiver implementation, you can extract the current charging state and method as described in the previous step.

public class PowerConnectionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                            status == BatteryManager.BATTERY_STATUS_FULL;

        int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
        boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
        boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
    }
}

Ref: https://developer.android.com/training/monitoring-device-state/battery-monitoring

Sultan Mahmud
  • 1,245
  • 8
  • 18
  • It seems to only return the default value (-1) and doesn't run in the background :( – Slimez Apr 16 '19 at 11:26
  • Fixed the default value problem but it still doesn't run in the background :( – Slimez Apr 16 '19 at 14:35
  • You cannot register receivers in the manifest for most implicit broadcasts on Android 8 and newer [due to background execution limitations](https://developer.android.com/about/versions/oreo/background#broadcasts). – mike47 Apr 27 '19 at 19:57
2

You could use a JobScheduler, and use the setRequiresCharging(boolean requiresCharging) method on the JobInfo.Builder you create.

PPartisan
  • 8,173
  • 4
  • 29
  • 48
  • Yeah, but then I have to schedule it every 15 minutes, right? :/ – Slimez Apr 17 '19 at 08:10
  • As I understand it, your job will be triggered as soon as the device goes on charge *unless* your allotted time window has passed (which I believe is around every 15minutes). So, you wouldn't need to poll, but it would mean that if the phone hadn't been on charge for half an hour, and then went on charge, it's very likely your Job would be executed...however, if you then went off charge and on charge again in under a minute, it probably wouldn't. I'd recommend you test it out yourself though! – PPartisan Apr 17 '19 at 09:17
  • Ah, cool! So it's basically a cooldown period. I'm definately going to test it out and i'll let you know if it works :) – Slimez Apr 17 '19 at 09:43
0

Keep running a thread in the background and use this method

public static boolean isConnected(Context context) {
    Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
}

if isConnected() returns true then update the time.

Code reference

Maifee Ul Asad
  • 3,992
  • 6
  • 38
  • 86