我有一个应用程序,可以监听电话通知,并通过MessageApi向安卓穿戴手表发送消息。除了安卓6的一些设备外,一切都很好,尤其是华为的Mate 8(看上去所有华为Android 6都这么做)。
华为自己也实现了冻结应用程序的后台处理(受保护的应用程序)。我从用户报告中证实,我的应用程序在华为受保护的应用程序和安卓6的Doze模式中都有例外。该应用程序工作正常,但正好15分钟后,我的应用程序停止发送消息给连接的安卓磨损手表。我的应用程序还可以记录收到的通知历史,15分钟后什么也不会到达.直到手机的显示器打开,我的应用程序被打开。在此之后,所有本应在手机显示关闭时到达的通知都会到达我的NotificationListenerService实现中,并立即发送到手表。这也证实了有记录的历史。
有什么办法解决这些手机,特别是华为Mate 8与Android 6与Doze模式?
当设备处于打瞌睡模式和/或应用程序处于待机模式时,NotificationListenerService的正确行为是什么?
编辑
用户还证实,他们的手机没有节能模式,这也影响后台应用程序和他们的服务。这个bug看起来像华为独家,因为没有Nexus的用户报告过这一点,而我的带有M的OnePlus之一也没有这样做。此外,N预览工作良好的Nexus设备。
编辑2
我增加了一个可选的前台服务(startForeground()),所以我的应用程序在通知中心有一个永久的通知,因此我的应用程序应该被排除在每个电池优化之外。对于前台服务通知,我使用了NotificationCompat.PRIORITY_MIN的优先级,并添加了Notification.FLAG_ONGOING_EVENT标志。这在华为手机上有点帮助,但没有多大帮助,现在延迟的通知会在屏幕打开后进入我的NotificationListenerService,而不是在打开我的应用程序之后。我没有在我的startForeground()中使用NotificationListenerService,而是在另一个Service中使用它,因为我无法控制它的生命周期。
发布于 2016-06-01 21:52:27
对于华为设备(不确定是否适用于所有华为设备),您需要请求受保护的应用程序权限,以便在应用程序进入后台时不被冻结。
若要检测华为设备是否保护了Apps权限,请执行以下操作:
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 "";
}不幸的是,我还没有找到任何方法来检查用户是否将您的应用程序作为受保护的应用程序。如果有人知道,请分享:)
参考资料:它
发布于 2016-05-27 08:53:08
直到我看到你的帖子,我才知道Android的Doze模式。然后我读了这篇文章,它似乎就是这样工作的!如果您希望在Doze模式下获得通知,请尝试使用PRIORITY_HIGH或PRIORITY_MAX作为通知优先级,但根据本文的说法,即使它工作正常,也并不是一个完整的解决方案。
https://stackoverflow.com/questions/36900480
复制相似问题