Android M listening to android.os.action.DEVICE_IDLE_MODE_CHANGED
Asked Answered
P

2

8

Can a third party application get an action once the device goes in to Doze mode?

Trying to register Broadcast receiver for below action,

<receiver android:name="com.doze.sample.DozemodeReceiver" android:enabled="true">
    <intent-filter>
        <action android:name=" android.os.action.DEVICE_IDLE_MODE_CHANGED" />
    </intent-filter>
</receiver>

It's not working (the receiver is not being called).

Pilewort answered 22/7, 2015 at 9:52 Comment(5)
Space in action are you good?Enphytotic
Its proper.. in codePilewort
"android.os.action" maybe M bug..Try developer.android.com/reference/android/os/… if this works in API 21 !Enphytotic
Register dynamically started working..Pilewort
Cool! Sometimes its that way in android! #6249523 .. mark as answere..Enphytotic
A
18

Building on a perfect answer provided by @zmarties, here is the full solution:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @RequiresApi(api = Build.VERSION_CODES.M) @Override public void onReceive(Context context, Intent intent) {
                PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

                if (pm.isDeviceIdleMode()) {
                    // the device is now in doze mode
                } else {
                   // the device just woke up from doze mode
                }
            }
        };

        context.registerReceiver(receiver, new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED));
    }

In case you are able to check when the context is destroyed (e.g. in the activity or service), call this to avoid leaking resources:

context.unregisterReceiver(receiver);

To test this piece of code, use the following commands:

adb shell dumpsys deviceidle force-idle

to bring the device into doze mode,

adb shell dumpsys deviceidle step

To wake up the device from Doze.

Ahders answered 6/2, 2017 at 10:33 Comment(8)
I am using exactly the same method for catching that broadcast but it seems to be working only when I invoke deviceidle force-idle and unforce. If I leave my phone standing for over an hour without touching it, nothing gets received in my broadcast receiver. Anyone experienced this?Alena
same problem hereGoatee
@SavaMikalački: The phone is unplugged, right? That is one of the conditions for entering Doze mode.Violative
@BobSnyder yes, my phone is disconnected. After some more tests I found out that I do get the broadcast when my phone is idle for several hours and I even get it over night when my phone is connected to my charger after several hours. Also, I understood that since there are steps when you call deviceidle step command, that I would also get these steps in the broadcast, but I only get broadcast if it went to idle and when it wakes up.Alena
@SavaMikalački: Thanks for the feedback. The broadcasts are similarly inconsistent for me. It's disappointing. I was expecting they would be a more reliable indication of idle state changes.Violative
Is it possible to register to it in manifest instead? Also, when entering this state, does it mean mobile data cannot be used?Hesperidium
@BobSnyder There are several stages of idle mode. Light Doze, Deep Doze, and each has several states. It takes a while to enter Deep Doze. (click here for article) You may also have active wakelocks preventing the phone from entering idle mode.Charger
Based on the android documentation for testing your app with Doze, you should use adb shell dumpsys deviceidle unforce to wake the device from Doze, not dupsys deviceidle stepBoohoo
M
14

To confirm what was mentioned in the comments, defining the android.os.action.DEVICE_IDLE_MODE_CHANGED broadcast receiver via the AndroidManifest.xml has no effect.

The only way to register the receiver is to do it dynamically:

IntentFilter filter = new IntentFilter();
filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
context.registerReceiver(new BroadcastReceiver()
{
  @Override
  public void onReceive(Context context, Intent intent)
  {
    onDeviceIdleChanged();
  }
}, filter);
Marlborough answered 9/9, 2015 at 15:16 Comment(1)
remember that if you use activity context, you need to unregister the receiver, so it can't be created as an anonymous class.Ahders

© 2022 - 2024 — McMap. All rights reserved.