我有一个应用程序可以收听手机通知,并通过MessageApi
向Android Wear手表发送消息。一些设备运行良好,除了Android 6的一些设备,特别是华为Mate 8(看起来像所有华为Android 6都这样做)。
华为有自己的冻结应用程序后台处理(受保护的应用程序)的实现。从用户报告中我已经确认我的应用程序在华为的受保护应用程序以及Android 6的 Doze 模式中有例外。该应用程序工作正常,但在显示关闭15分钟后,我的应用程序停止向连接的Android Wear手表发送消息。我的应用程序还可以记录收到的通知历史记录,15分钟后没有任何内容...直到手机的显示屏打开并且我的应用程序打开。之后,手机显示屏关闭时应该收到的所有通知都会进入我的NotificationListenerService
实施,并立即发送到手表。历史记录也证实了这一点。
如何解决这些手机的问题,尤其是带有Doze模式的Android 6的华为Mate 8?
当设备处于休眠模式和/或应用处于待机模式时,NotificationListenerService
的正确行为是什么?
修改
用户还确认他们的手机未处于省电模式,这也会影响后台应用及其服务。这个bug看起来像华为独家,因为没有Nexus用户报告这个,我的OnePlus One和M也没有这样做。 N预览也适用于Nexus设备。
编辑2
我添加了一个可选的前台服务(startForeground()
),因此我的应用会在通知中心发出永久通知,因此我的应用应该从每次电池优化中排除。对于前台服务通知,我使用了NotificationCompat.PRIORITY_MIN
的优先级,并添加了Notification.FLAG_ONGOING_EVENT
标志。这对华为手机有点帮助但不多,现在延迟通知在屏幕打开后立即到达我的NotificationListenerService
,而不是打开我的应用程序。我不会在startForeground()
中使用NotificationListenerService
,而在另一个Service
中使用,因为我无法控制其生命周期。
答案 0 :(得分:2)
对于华为设备(不确定是否适用于所有华为设备),您需要申请受保护的应用程序权限,以便您的应用程序在进入后台时不会冻结。
检测华为设备是否具有受保护的应用程序权限:
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;
}
打开华为受保护应用设置页面:
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 "";
}
很遗憾,我还没有找到任何方法来检查用户是否已将您的应用授予受保护的应用。如果有人知道,请分享:)
参考: http://ndroid.info/ldquo_protected_appsrdquo_setting_on_huawei_phones_and_how_to_handle_it
答案 1 :(得分:0)
在看到你的帖子之前,我不知道Android的Doze模式。然后我读了this article,看起来它应该是如何工作的!如果您想在打盹模式下收到通知,请尝试使用PRIORITY_HIGH
或PRIORITY_MAX
作为通知优先级,但即使它有效,根据文章,它似乎并不是一个完整的解决方案。