我有一个关于 Android 小部件,尤其是 Android 服务的问题。这是我想要做的:在手机上,用户应该能够将我的小部件添加到他的主屏幕。小部件从网络获取数据。 在阅读了一些关于此的教程后,我发现最好的方法是创建一个从网络(TCP 套接字)获取数据的服务,然后不断更新小部件。这是通过 ScheduledExecutorService 完成的,它在一定的时间间隔内执行 Runnable。 Runnable 将连接到服务器,获取数据并更新小部件)。
我现在的问题是,当屏幕关闭时小部件不需要更新,因此由于电池耗尽,服务不应运行。我的问题是:如何以最佳方式做到这一点?
我发现了 2 种方法或多或少可以满足我的要求:
当小部件的第一个实例被添加到主屏幕时,它将注册一个广播接收器,该接收器接收来自 Android 操作系统的 ACTION_SCREEN_ON 和 ACTION_SCREEN_OFF intent 操作。 如果触发 ACTION_SCREEN_ON,它将启动更新程序服务,否则将停止它。但由于广播接收器的生命周期,我真的不确定这是否是一个好方法。
在由 ScheduledExecutorService 定期执行并实际执行网络操作的更新程序服务的 Runnable 中,我通过 PowerManager.isScreenOn() 检查屏幕是否打开。如果是,我执行网络代码,否则不执行。但是设备处于待机状态时是什么?那么这段代码执行了吗?这里的电池耗尽怎么样?
是否有针对我想做的事情的“最佳实践”方法?我已经阅读了很多有关 AlarmManager 的文章,并且它是一个非常强大的工具。您能否用这种方式安排任务,使其仅在显示屏打开时执行?
感谢您的帮助。
最好的问候 镍钛合金
最佳答案
您的第一个解决方案(小部件处理屏幕打开和关闭广播)是解决问题的方法。启动一个新的 IntentService 以与您的应用程序服务器进行后台通信。完成后,发送带有结果的自定义“已完成”广播,然后在您的小部件中进行处理。
作为一个额外的好处,它允许您的小部件的多个实例从一个“来源”工作,并且在用户没有添加任何小部件的情况下不会消耗任何资源。
UPDATE 由于不可能使用带有小部件的屏幕开/关广播,我可能会使用 this(带有 ELAPSED_REALTIME
的 AlarmManager(不是 ELAPSED_REALTIME_WAKEUP
) alarm) 来安排( Intent )服务运行。这样您的服务就不会在屏幕关闭时被安排,但会在屏幕打开时定期运行。如果屏幕打开和关闭之间的延迟超过该时间,它将立即在屏幕重新打开时运行。
至于您关于广播接收器生命周期的问题,如前所述,请将 IntentService 用于长时间运行的任务,然后从中广播您的结果。当您启动一项服务时,调用不会阻塞,因此广播接收器将及时完成。
更新 2 根据 this 屏幕关闭并不意味着设备正在休眠。您已经通过使用 PowerManager.isScreenOn() 解决了这个问题。
关于Android - 使用来自网络的数据通过服务更新小部件。最好的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14401788/