英文:
Is there any alternative for PeriodicWorkManager, if I would like to run a background work more frequently than 15 minutes?
问题
PeriodicTimeRequest
的最小周期时间为15分钟。但我发现,例如Google Maps位置共享可以更新得更频繁,Facebook Messenger也几乎可以立即接收消息。
当用户收到新消息时,我想向用户发送通知。我的应用程序必须在本地网络上运行,因此Firebase不是一个选项。我必须向服务器发送一个JSON请求,如果有新消息,我会向用户显示通知。
英文:
The PeriodicTimeRequest
has a minimum periodic time of 15 minutes. But I see, that for example Google Maps location sharing can update more frequently than that, and facebook messenger can also receive messages almost instantly.
I would like to send a notification to the user, when it got a new message. My application has to work on local network, so Firebase is not an option. I have to send a json request to the server, and if there is a new message, I show a notification to the user.
答案1
得分: 3
关于FCM:
FCM在所有安装有Google Play的设备上都可用,它负责订阅和接收推送事件,在Android引入各种资源限制的情况下,它承担了沉重的责任。
它与操作系统紧密耦合,并且是统一的(一个实体,一个持久连接用于设备中的所有应用程序),这就是它能够工作的原因
关于您的工作频率:
考虑到您需要更频繁地向服务器发送请求,您需要一个始终运行的服务,即前台服务。
尽管这会消耗资源,但祝您好运,能够以充分的理由说服用户为什么它应该始终保持运行。
我认为您已经成功实现了客户端与服务器之间的交互,因为在本地网络中识别服务器本身就是一项巨大的任务。
英文:
Regarding FCM:
FCM, which is available in all devices with Google Play takes the weight of subscribing to and receiving push events, under all the resource constraints Android has been ever introducing.
It's tightly coupled with the OS and is unified (one entity, one persistent connection for all apps in your device), which is why it works
<hr>
Regarding Frequency of your Work:
Given your requirement of more frequent pings to the server, you'd need to have a service which runs all the time, i.e. A Foreground Service.
It is resource consuming though, so good luck convincing the user with a good reason why it should stay alive all the time.
<hr>
I think you've managed to make the client-server interaction possible, since identifying a server in a local network is a huge task in itself.
答案2
得分: 2
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
CountDownTimer timer = new CountDownTimer(15 * 60 * 1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
// 在这里执行您的任务,每秒执行一次
// 如果您想要将倒计时间隔从1000毫秒增加到您需要的值
}
@Override
public void onFinish() {
this.start();
// 它会重新开始。
}
};
timer.start();
return START_STICKY;
}
英文:
use this in your service.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
CountDownTimer timer = new CountDownTimer(15 * 60 * 1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
// execute your task here, every sec
//if you want increase the count down interval from 1000 to what you want
}
@Override
public void onFinish() {
this.start();
// it will start again.
}
};
timer.start();
return START_STICKY;
}
答案3
得分: 1
很抱歉,您要求的是只返回翻译好的部分,那么以下是您提供的内容的翻译:
我恐怕没有使用一组解决方法是不可能的。这意味着您可能无法获得一致的行为。
@Arvind 已经非常好地解释了使用 Firebase 服务的好处,而且这是实现此任务的推荐方法。
首先,我想指出,对 WorkManager 的这些限制存在是因为 Android 一直遭受(除其他外)开发人员试图滥用某些机制来使他们的软件工作,最终导致用户的电池遭受了这些滥用,自 Android 6 以来,Google 开始努力解决这些问题。您可以在这里阅读有关 Doze 模式以及如何与其一起工作的内容。
我之所以指出这些内容,是因为我一直在尝试构建一个不依赖于 Firebase 的聊天服务,我真的不希望您像我一样花费太多时间在试图解决难题上。有些事情您根本无法抗衡。这意味着如果设备有时进入“深度睡眠”模式,您只能接受它。
我的方法
请注意
关注用户的兴趣以及他们电池的寿命,尽量使与设备的交互尽可能顺畅。这只是对强加给我们的限制的一种变通方法。我不鼓励采用这种方法,因为这需要大量的工作来实现,并且可能被滥用。
我的解决方案
基本上,在 Android 应用程序中要收到通知(即使让您的代码运行),您将想要接收系统事件或广播。这是您设置BroadcastReceiver
并将Intent
传递给它,然后您可以相应地采取行动的地方。但是您必须要快,因为在操作系统再次终止进程之前,您只有10秒的运行时间。理想情况下,您应该拥有一个非常快速的服务器,以便可以在尽可能频繁地保持在10秒的限制内。
因此,您将使用多种服务的组合来监视您希望监视的内容,以便在这些内容的状态发生更改时获得通知(即广播)。以下是一些想法:
- WiFi 状态(这也将有助于查看是否可以连接到本地服务器)
- 低功耗蓝牙数据包(或附近的数据包,根据附近的功能的能力,这可能完全解决了您的问题)
- 如您所指出的,使用 WorkManager。
- AlarmManager,以便定期发送意图的广播。
- 地理围栏(尽管涉及读取用户的位置;您可以在办公楼周围设置非常小的地理围栏,并在用户穿过该地理围栏时通过广播收到通知)
因此,每当您从这些来源接收到广播时,您将从同一个BroadcastReceiver处理此类通知。
在此广播接收器的实现体中,您将轮询本地网络服务器,以_检查_用户是否有新消息,然后提醒通知。并且重要的是要将应用程序必须执行的工作和IO时间保持在最低限度,因为它们会累积起来,而您只有10秒的时间。
如果启动了前台服务,则可以绕过10秒的限制。然后,这段时间将延长到10分钟,并且您需要为用户提供一个可见的通知,指示您正在检查是否有任何新消息。
请记住
- 不要过分耗尽用户的电池。否则,Android 将惩罚您的应用,您将较少甚至完全不会收到通知。
- 对用户要友好。如果用户在某个时候不得不强制关闭您的应用程序,它将停止接收任何类型的广播或运行任何类型的工作任务。
- 此解决方案在不同设备上的行为可能不同。由于通知您的应用程序的决定是由操作系统进行的,不同的操作系统(红米,三星,魅族等)可能导致不一致的行为。
- 您无法控制事物,操作系统有控制权。
- 在合理范围内,尽量将广播的时间安排在3分钟左右的时间间隔内,以便始终在15分钟以下接收广播。
英文:
I am afraid it is not going to be possible without using a set of workarounds. Which means you might not get a consistent behavior.
@Arvind has done a very good job explaining the benefits of a Firebase Service and it is the recommended approach for achieving such task.
First I'd like to point out that such restrictions on the WorkManager exist because Android has been suffering (between other things) of developers trying to abuse some mechanisms to get their software working and at the end of the day, the battery of the users had been suffering from such abuses and since Android 6 Google has started trying to address these issues. There's a good read for you over here about Doze mode and how to work with it
I am pointing this stuff out because I've been trying to build a chat service that wouldn't rely on Firebase and I really don't want you to waste as much time as me banging your head against a wall. There are things that you simply can't fight. That means that if the device enters in a "deep-sleep" mode sometimes you can only accept it.
My approach
Please
keep in mind the user interests and the life of their batteries and try to be as smooth as you can with their devices and this is just a workaround over the restrictions that have been imposed upon us. And that I discourage this approach due to the amount of work that it takes to pull off and for how misused it can be.
My solution
Essentially, to get notified (ie getting your code running) in an Android App you're going to be wanting to receive system events or Broadcasts. This is where you set up a BroadcastReceiver
and you get Intent
s delivered to it and you can act upon them accordingly. BUT YOU HAVE TO BE QUICK BECAUSE YOU HAVE ONLY 10 SECONDS OF RUNTIME BEFORE THE OS KILLS THE PROCESS AGAIN. Ideally you would have a really quick server so you can have very little IO times to ensure you can be within 10 second restriction as frequently as possible.
So essentially you would be using a combination various of services that you would like to be monitoring in order to get notifications (aka Broadcasts) whenever the state of those changes. Here are a few ideas:
- WiFi state (which will also be useful to see if you can reach your local server)
- Bluetooth Low Energy packets (or Nearby which may solve the entirety of your problem depending on Nearby's capabilities)
- WorkManager as you already pointed out.
- AlarmManager to schedule a broadcast of intents every so often.
- Geofencing (although it involves reading the user's location; you can set really small geofences around the office building and get notified by a Broadacast when users go through that geofence)
So whenever you receive a Broadcast of these sources you would handle such notifications from within the same BroadcastReceiver
From the implementation body of this Broadcast receiver you would poll the local network's server to check whether if your user has new messages or not and lift up a notification. And it's important to keep the amount of work and IO times the app has to do at a minimum since those add up and you've got only 10 seconds.
You can get around the 10 second mark if you launch a ForegroundService. Then, that period of time is going to be extended until a 10 minute mark and you will need a visible notification for the user stating something that you're checking if it's got any new messages.
Keep in mind
- Don't stress the user's battery too much. Or Android will penalise your app and you'll end up notified less often or even completely not notified.
- Be gentle with the user. If the user has to force-kill your app at some point it will stop receiving any sort of Broadcasts or running any sort of WorkTasks.
- This solution can behave differently accross devices. Since the decisions of notifying your app are made by the OS, different OS (redmi, samsung, meizu...) you are likely to not end up with a consistent behavior across all devices
- You don't have control over things, the OS does
- Within measure, try to time your Broadcasts to your BroadcastReceiver within spans of 3 minutes or so; so you are always receiving a Broadcast below the 15 minute mark.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论