NotificationListenerService and Doze mode and App Standby
Asked Answered
I

2

9

I have an app that listens for phone notifications and sends a message to an Android Wear watch via the MessageApi. Everything works good except for some devices with Android 6, especially Huawei Mate 8 (looks like all Huawei Android 6's do this).

Huawei has its own implementation of freezing apps' background processing (Protected apps). From the users reports I have confirmed that my app has an exception in the Huawei's protected apps and also in the Android 6's Doze mode. The app works OK but after exactly 15 minutes with display off my app stops sending messages to the connected Android Wear watch. My app can also record received notifications history and nothing arrives after the 15 minutes... until the phone's display is turned on and my app is opened. After that all the notifications that should have arrived while the phone's display was off arrive into my NotificationListenerService implementation and are sent to the watch, all at once. This is also confirmed with the recorded history.

Any ideas how to fix this for these phones, especially the Huawei Mate 8 with Android 6 with Doze mode?

What is the correct behaviour of the NotificationListenerService while the device is in the doze mode and/or the app is in the standby mode?

EDIT

Users have also confirmed that their phones are not in a power saving mode which also affects background apps and their services. This bug looks like Huawei exclusive because no Nexus users have reported this and my OnePlus One with M is not doing this either. Also N preview works good on Nexus devices.

EDIT 2

I have added an optional foreground service (startForeground()) so my app has a permanent notification in the notification center, thus my app should be excluded from every battery optimization. For the foreground service notification I used a priority of NotificationCompat.PRIORITY_MIN and I added the Notification.FLAG_ONGOING_EVENT flag. This helped a bit on the Huawei phones but not much, now the delayed notifications arrive into my NotificationListenerService right after the screen is turned-on instead after opening my app. I do not use the startForeground() in my NotificationListenerService but in another Service because I have no control about its lifecycle.

Irradiant answered 27/4, 2016 at 20:42 Comment(0)
F
2

For Huawei devices (not sure if applies to all Huawei devices), you need to request for Protected Apps permission in order for your app to not be freezed when it goes into the background.

To detect if a Huawei device has Protected Apps permission:

private boolean hasProtectedAppsSetting() {
    Intent intent = new Intent();
    intent.setClassName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity");

    List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,
            PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}

To bring up Huawei Protected Apps settings page:

private void showProtectedAppsSetting() {
    try {
        String cmd = "am start -n com.huawei.systemmanager/.optimize.process.ProtectActivity";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            cmd += " --user " + getUserSerial();
        }
        Runtime.getRuntime().exec(cmd);
    } catch (IOException ignored) {
    }
}

private String getUserSerial() {
    //noinspection ResourceType
    Object userManager = getSystemService("user");
    if (null == userManager) return "";

    try {
        Method myUserHandleMethod = android.os.Process.class.getMethod("myUserHandle", (Class<?>[]) null);
        Object myUserHandle = myUserHandleMethod.invoke(android.os.Process.class, (Object[]) null);
        Method getSerialNumberForUser = userManager.getClass().getMethod("getSerialNumberForUser", myUserHandle.getClass());
        long userSerial = (Long) getSerialNumberForUser.invoke(userManager, myUserHandle);
        return String.valueOf(userSerial);
    } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException ignored) {
    }
    return "";
}

Unfortunately I've not found any way to check if user have granted your app as a Protected App. Please share if anybody knows :)

Reference: http://ndroid.info/ldquo_protected_appsrdquo_setting_on_huawei_phones_and_how_to_handle_it

Fomalhaut answered 1/6, 2016 at 21:52 Comment(1)
Thank you for this information. But, as mentioned in the question, the problem is that even giving my app an exception in the Huawei's Protected Apps does not solve the "background freezing". Even together with disabling Android 6's native battery optimization plus a foreground service. For some users it is enough to add an exception to both protected apps and battery optimization, but not for all. Not even for majority.Irradiant
I
0

I didn't know about Android's Doze mode until I saw your post. Then I read this article and it seems like that is how it is supposed to work! If you want to get notifications during Doze mode try to use PRIORITY_HIGH or PRIORITY_MAX for your notification priority, but even if it works it doesn't really seem like a complete solution according to the article.

Ironware answered 27/5, 2016 at 8:53 Comment(2)
That article is about push notifications and not local notifications. I do not have a server for my app, it is completely offline, so I cannot wake-up the phone via high priority push notification. It will also be impossible to send a push notification to a phone when that phone shows a notification...Irradiant
According to the article, yes you won't be able to wake the device upIronware

© 2022 - 2024 — McMap. All rights reserved.