我希望在后台跟踪对用户选定的外部存储文件夹所做的更改**,不使用前台服务**,并在发生更改时唤醒应用**。即使用户从最近的应用中 * 删除应用,此操作也应起作用。在此阶段唤醒应用的意思是我向用户发送了一个通知,告知已检测到更改。我不希望使用前台服务的原因是我不希望显示一个持续通知**,告知我正在监视文件系统。
我原以为这在目前的Android限制下是不可能的,但后来我遇到了FolderSync应用程序。当你设置一个本地-远程文件夹对时,它跟踪本地文件夹的更改非常准确,同时不在状态栏中显示任何通知(意味着他们**没有运行aForeground****Service来执行此操作)。请查看this video以了解其工作原理(在运行Android 13的三星手机上拍摄)
我研究了各种方法,发现唯一可能的解决方案是使用WorkManager**提供的addContentUriTrigger。
我的场景中的一个示例用法是:
val folderUri = Uri.parse("file://" + folderPath)
workRequestBuilder.setConstraints(
Constraints.Builder()
.addContentUriTrigger(folderUri, true)
.build()
).addTag(WORKER_TAG)
workManager.enqueue(syncMonitorBuilder.build())
但它不起作用。首先,在本例中,由于某种原因,WorkManager根本没有被触发。如果我将其替换为.addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true)
以侦听DCIM目录的更改(而不是自定义目录)- WorkManager工作正常,而应用程序在最近的应用程序中,但是,一旦您将该应用从最近的应用中删除**,就会停止。
1条答案
按热度按时间mwg9r5ms1#
我在Android(API级别33)模拟器中安装了FolderSync,然后设置它从本地
folder1
同步文件到本地folder2
,然后从最近的应用程序中删除它,在logcat上看到:最后一行每隔约10分钟重复一次。
正如你在名称
ScheduleAlarmReceiver
和SyncService
上看到的,它似乎使用AlarmManager和sync adapter从睡眠中唤醒,因为我知道这两个都可以用来唤醒应用程序,所以我很确定这两个都被使用了。例如,AlarmManager可以每10分钟唤醒您的应用(请参阅setRepeating()和setInexactRepeating())。
如果您使用同步适配器,则在“设置”〉“帐户”(类似于电子邮件帐户)下会为您的应用设置一个帐户。它还可以定期唤醒您的应用。
在logcat中,你还可以看到它试图创建一个前台服务,但这被阻止了,因为应用程序在后台,正如你所看到的,即使FolderSync也使用前台服务。
我等了一个小时,应用程序没有被杀死。我假设FolderSync在AOSP上被AlarmManager重新启动后再也不会被杀死。你可以在dontkillmyapp.com上读到,AOSP上没有后台应用程序被杀死的问题。
但在三星,FolderSync在被唤醒后很快就会再次被杀死。唤醒30秒后,FolderSync可能会再次被杀死。因此,唤醒应用程序并不能解决问题,因为它很快就会再次被杀死。
你遇到了一个许多Android程序员都讨厌的问题。类似于“如何防止我的应用程序被杀?”的问题在stackoverflow上被问了很多次。但正如dontkillmyapp.com所解释的那样,这些问题来自制造商,而不是Android本身。
有时候会有一些电池设置(可能取决于制造商)最终阻止你的应用程序被杀死,这在dontkillmyapp.com上有解释。
我建议使用前台服务。事实上,像WhatsApp这样的应用程序( meta/Facebook的一部分)使用前台服务来检查消息显示这是如何完成的。没有其他秘密的方法来防止你的应用程序被杀死。而且,如果标题栏中有一个小符号,它不会困扰大多数人。例如,WhatsApp会启动前台服务,当工作完成后,它会结束前台服务。所以你不会一直看到它。
你可以使用AlaramManager来定期唤醒你的应用。你也可以创建一个账户(出现在设置〉账户下)来定期唤醒你的应用。或者你可以使用谷歌云消息向你的应用发送消息。还有很多其他的广播,比如“设备启动”或“屏幕打开”,都可以唤醒你的应用。但是正如前面所说,如果没有前台服务,它很快就会再次被杀死。
我想补充的是,当你根你的设备是有可能保持你的应用程序在后台运行,而没有前台服务。