gpt4 book ai didi

android - Android应用程序的生命周期:也许是无限的?

转载 作者:行者123 更新时间:2023-12-01 01:22:01 25 4
gpt4 key购买 nike

我正在开发一款旨在将android手机转换为无需用户操作即可运行的远程设备的应用程序。当时该应用是由Activity制作的,该Activity设置AlarmManager每隔X分钟执行一次服务(项目内的类)。
所有这些工作正常,但是偶尔在5-6天后连续运行该应用程序会崩溃(当前我不知道为什么,因为我现在无法拿到电话)。这不是连接问题(我知道),并且电话仍在运行(插入交流电)。我唯一能想到的是该应用程序已关闭。
我不认为这是由于错误引起的,因为预先调试不会给我任何错误。
因此,我必须假设android已经终止了该活动(系统需要更多的内存?),并且如镜像所说明的那样,没有办法对其进行备份。

但是我有一个疑问:在我的应用程序中,活动无关紧要,因为所有工作都是由服务完成的。该服务本身由警报管理器调用,并且在两次调用之间的时间内,该服务由Stop​​Self()终止。
就我而言,系统可能会终止我的警报管理器服务计划?
如何使警报管理器永久启动该服务?
(注意:当前尚有唤醒锁,但是这仅考虑了服务的执行!我希望您已经了解警报管理器每隔x分钟调用一次该服务,而不是终止该服务...我想针对以下情况执行此操作无限期)
[由于发布时间太长,我没有发布源代码]

最佳答案

rk

我自己也曾尝试过类似的问题,但我可能会为您提供一些建议。我假设您将Android设备用作一种远程“嵌入式控制器”,该控制器以最少的用户交互来执行其功能。我相信您在那里95%的人只需要进行一些小的体系结构更改。由于您没有提供代码,因此我将仅以抽象术语进行说明,而不是提供示例代码。

CommonsWare是正确的,您需要使用AlarmManager,但是我怀疑您已经知道这一点。
首先,请先做一些背景说明,以确保所有内容都是可以理解的。
由AlarmManager创建的警报存在于系统级别,也就是说,它们可以存在于创建它们的活动和应用程序的生命周期之外。如果您设置了警报但不希望它在您的应用程序更改状态时关闭(例如,在销毁状态之后),则可以使用alarmManager.cancel(pendingIntent)取消警报–只需使用以下命令创建意图和警报管理器相同的参数,Android将匹配警报)。
同样,BroadcastReceivers在系统级别注册(至少如果它们在manifest.xml中声明),并且可以在创建它们的活动和应用程序的生命周期之外存在。同样,如果您要确保在应用程序更改状态后(例如,在销毁应用程序后)发生的事件不会触发BroadcastReceiver,则需要在其代码中明确注销。如果是通过程序注册的,则使用context.unregisterReceiver(broadcastReceiver);如果它是在清单中静态注册的,那么就不那么容易-您将不得不使用PackageManager和ComponentName来检索接收器(请参阅:Android - how to unregister a receiver created in the manifest?),并且请记住,如果再次需要接收器,则需要重新启用它。

您说您已经设置了闹钟。确保为警报类型指定ELAPSED_REALTIME_WAKEUP或RTC_WAKUP,以确保即使手机处于“睡眠”模式也可以运行。
您还说您已经创建了关联的BroadcastReceiver来处理警报事件。 BroadcastReceiver应该做最少的工作,因此您应该在单独的线程中或通过启动服务来处理所有处理。您选择启动服务,并在服务完成时使用stopSelf()终止该服务,以免消耗系统资源。到目前为止,一切都很好。

这在应用程序运行时很好,但是由于您需要无限期可靠运行的内容,因此需要确保在暂停的情况下,设备在“睡眠”,应用程序崩溃的情况下管理“异常”情况/终止,或者设备已重启(以及您可能想到的任何其他异常情况)。以下是我确定您需要解决的问题:

首先:仅在BroadcastReceiver的onReceive()方法期间保证WakeLock。终止后,即使您的服务尚未启动或完成,设备也可能会回到“睡眠”状态,因此您需要创建WakeLock,将其传递给服务并释放它,然后再停止服务。 (注意:对于您的应用程序,您需要PARTIAL_WAKE_LOCK)。使用WakeLock时请务必小心-确保仅在最短的时间内握住WakeLock并确保将其释放,因为使用WakeLock会导致电池消耗过多)。有关使用WakeLocks的示例,请参见http://www.netmite.com/android/mydroid/development/pdk/docs/power_management.html

第二:如果您在代码中重置了警报(而不是定义一个自动重复的警报),请在BroadcastReceiver的OnReceive()方法中执行此操作,或者作为您启动的服务中的第一件事进行此操作–这将确保警报重复发生,不论应用程序或设备的状态如何。

第三:确保您使用的所有上下文都是非空值。您可以使用getApplicationContext()动态获取服务中的上下文。否则,可以通过将上下文从您的应用程序明确传递给警报,并确保将其始终通过BroadcastReceiver以及相关的线程和服务传递,来实现。如果您在应用程序中静态存储了Context,因此可以在任何地方检索它,那么如果应用程序终止,它将返回null值。如果使用Context(例如,检索资源,访问数据库等),并且它为null,则将导致null指针异常,并且Service或BroadcastReceiver将崩溃。我相信这是您的应用终止后,广播接收器无法正常工作的最可能原因。

第四:您可能希望引用完全合格(.R.drawable.icon)或从传递的上下文生成的Service或BroadcastReceiver中的ResourceID(例如R.drawable.icon)。我还没有发现这是必要的,但我怀疑这是谨慎的做法。

第五:实现一个单独的BroadcastReceiver来处理设备重启情况(ON_BOOT_COMPLETE事件)。您可以在适当的情况下让该接收器重新启动该应用程序,或者可以启动服务以检查您的应用程序是否处于活动状态,设置所有必需的参数并设置相关警报,然后使用stopSelf()终止它,或者只是再次设置闹钟,让接收者处理所有这一切。请记住要确保服务在其有效期内具有WakeLock,并在完成后释放WakeLock。如果您不只是重新启动应用程序或服务(声明为应用程序的一部分),那么还应在需要时将正确的Context作为类属性静态存储在BroadcastReceiver中,以便可以访问它。资源。

您可能还需要考虑其他几件事:
由于您的设置是远程的,因此我将认真考虑将所有持久性数据存储在SQLite数据库表中。这将确保在应用程序终止和设备重启之间恢复数据,而无需重新生成数据。
如果您的应用程序与服务器服务进行通信,请考虑使用推送通知进行服务器启动的通信,而不是让应用程序定期进行轮询。推送通知还可以用于“唤醒并启动服务和应用程序”,因此可以用作远程机制的一部分,以查询设备和应用程序的状态。这种方法也更省电,更及时。
在代码的关键点将信息发布到LogCat进行调试。如果应用程序终止,则adb停止跟踪为接收方和服务运行的源代码,但LogCat继续起作用,因此可用于检查代码和变量值的路径。

其他人可能有更好的方法来解决这些问题或其他一些提示(我当然会很高兴看到其他意见),但我希望这些想法对您有所帮助,并祝您好运!

关于android - Android应用程序的生命周期:也许是无限的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8608451/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com