gpt4 book ai didi

android - 在所有最新的Android限制之后,如何设置要在确切时间安排的警报?

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

注意:我尝试了各种有关StackOverflow的解决方案(示例here)。请不要在未检查发现的解决方案是否使用我下面编写的测试有效的情况下关闭此功能。

背景

该应用程序有一个要求,即用户将提醒设置为在特定时间进行安排,因此,当应用程序在此时间触发时,它会在后台执行一些微小的操作(只是一些数据库查询操作),并显示一个简单的通知,以告知有关提醒。

过去,我使用简单的代码来设置要在相对特定的时间安排的内容:

            val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pendingIntent = PendingIntent.getBroadcast(context, requestId, Intent(context, AlarmReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
when {
VERSION.SDK_INT >= VERSION_CODES.KITKAT -> alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
else -> alarmManager.set(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
}
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("AppLog", "AlarmReceiver onReceive")
//do something in the real app
}
}

用法:
            val timeToTrigger = System.currentTimeMillis() + java.util.concurrent.TimeUnit.MINUTES.toMillis(1)
setAlarm(this, timeToTrigger, 1)

问题

我现在已经在新的Android版本和带有Android 10的Pixel 4的模拟器上测试了此代码,它似乎没有触发,或者自从我提供它以来经过了很长时间才触发。我很清楚 terrible behavior新增了 some OEMs以便从最近的任务中删除应用程序,但这是在模拟器和Pixel 4设备(库存)上都有的。

我在 the docs上阅读过有关设置警报的信息,该警报受到应用程序的限制,因此不会经常发生,但这并未说明如何在特定时间设置警报,也没有说明如何 Google's Clock app成功做到了。

不仅如此,而且据我了解,它说应该对设备特别是低功耗状态施加限制,但就我而言,我在设备和仿真器上都没有这种状态。我将警报设置为从现在开始大约一分钟后触发。

看到许多闹钟应用程序不再像以前那样工作了,我认为文档中缺少某些内容。此类应用程序的示例是流行的 Timely应用程序,该应用程序是 bought by Google,但是从未获得过任何新更新来处理新限制,现在是 want it back.用户。但是,某些受欢迎的应用程序确实可以正常工作,例如 this one

我尝试过的

为了测试警报是否确实有效,我从设备连接到PC以来第一次尝试安装该应用程序之后(从现在开始),尝试在一分钟后从现在开始触发警报,然后执行以下测试:
  • 测试应用程序在前景中的时间(用户可见)。 -花了1-2分钟。
  • 测试将应用程序发送到后台的时间(例如,使用主屏幕按钮)-花费了大约1分钟的
  • 测试何时将应用程序的任务从最近的任务中删除。 -我等待了20多分钟,却没有看到警报被触发,没有写入日志。
  • 像#3一样,但也要关闭屏幕。可能会更糟...

  • 我尝试使用接下来的东西,所有的东西都不起作用:
  • alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)
  • alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
  • AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
  • 上面任何一项的
  • 组合,与:
    if (VERSION.SDK_INT >= VERSION_CODES.KITKAT)
    alarmManager.setWindow(AlarmManager.RTC_WAKEUP, 0, 60 * 1000L, pendingIntent)
  • 尝试使用服务而不是BroadcastReceiver。还尝试了不同的过程。
  • 尝试使该应用程序从电池优化中被忽略(这无济于事),但是由于其他应用程序不需要它,因此我也不应该使用它。
  • 使用以下方法尝试:
  •             if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
    alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)
    AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
  • 尝试使用会触发onTaskRemoved的服务来在此处重新安排警报,但这也无济于事(尽管该服务运行良好)。

  • 至于Google的Clock应用程序,除了在触发之前会显示通知,我没有看到其他特别之处,并且在电池优化设置屏幕的“未优化”部分也没有看到它。

    看到这似乎是一个错误,我报告了这个 here,包括一个示例项目和显示该问题的视频。

    我检查了模拟器的多个版本,看来此行为始于API 27(Android 8.1-Oreo)。看 at the docs,我没有看到AlarmManager被提及,而是关于各种背景工作而写的。

    问题
  • 我们如何设置如今要在相对准确的时间触发的内容?
  • 以上解决方案为何不再起作用?我有什么想念的吗?允许?也许我应该改为使用 worker ?但是那不是意味着它可能根本不会按时触发吗?
  • Google“时钟”应用程序如何克服所有这些问题,并且无论如何都会在准确的时间始终触发,即使它是在一分钟前触发的也是如此?仅仅是因为它是一个系统应用程序吗?如果将它作为用户应用程序安装在没有内置设备的设备上怎么办?

  • 如果您说这是因为它是一个系统应用程序,我发现另一个可以在2分钟内两次触发警报的应用程序 here,尽管我认为它有时可能会使用前台服务。

    编辑:做了一个很小的Github存储库,尝试尝试 here

    编辑:最终 found a sample既是开源的,也没有此问题。遗憾的是,它非常复杂,我仍然试图找出是什么使它如此不同(以及我应该添加到我的POC中的最小代码是什么),以使其在从近期任务中删除该应用程序后便保持其警报状态

    最佳答案

    找到了一个奇怪的解决方法(示例here),该解决方法似乎适用于所有版本,甚至包括Android R:

  • 具有 list 中声明的​​SAW权限:
  •       <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    在Android R上,您还必须将其授予。在之前,似乎不需要授予它,只是声明它。不确定为什么在R上发生了这种变化,但是我可以说,可能需要SAW作为在后台启动事物的可能解决方案,如针对Android 10的 here所示。
  • 有一个服务,该服务将检测何时删除任务以及何时删除任务,打开一个伪造的Activity,它所做的只是关闭自身:
  • class OnTaskRemovedDetectorService : Service() {
    override fun onBind(intent: Intent?) = null

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = START_STICKY

    override fun onTaskRemoved(rootIntent: Intent?) {
    super.onTaskRemoved(rootIntent)
    Log.e("AppLog", "onTaskRemoved")
    applicationContext.startActivity(Intent(this, FakeActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
    stopSelf()
    }

    }

    FakeActivity.kt
    class FakeActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d("AppLog", "FakeActivity")
    finish()
    }
    }

    您还可以使用以下主题使该Activity对用户几乎不可见:

        <style name="AppTheme.Translucent" parent="@style/Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackgroundCacheHint">@null</item>
    <item name="android:windowIsTranslucent">true</item>
    </style>

    可悲的是,这是一个怪异的解决方法。我希望找到一个更好的解决方法。

    限制是关于启动Activity的,所以我目前的想法是,如果我瞬间启动前台服务也将有所帮助,为此,我什至不需要SAW许可。

    编辑:好的,我尝试使用前台服务(示例 here),但是它不起作用。不知道为什么 Activity 有效但服务无效。我什至试图重新安排在那里的警报,并试图使服务停留一会儿,即使在重新安排之后也是如此。还尝试了常规服务,但是由于任务被删除,它当然立即关闭,并且根本不起作用(即使我创建了在后台运行的线程)。

    我没有尝试过的另一种可能的解决方案是永远拥有前台服务,或者至少要等到任务删除后再使用,但这有点怪异,而且我看不到我提到的使用它的应用程序。

    编辑:尝试在删除应用程序的任务之前(以及稍后执行)运行前台服务,并且该警报仍然有效。还尝试使该服务成为负责任务删除事件的服务,并在发生该事件时立即将其自身关闭,并且该服务仍然有效(示例 here)。这种解决方法的优点是您完全不需要SAW权限。缺点是当用户已经可以看到该应用程序时,您将获得带有通知的服务。我想知道是否可以通过“ Activity ”在应用程序已经处于前台时隐藏通知。

    编辑:似乎是Android Studio上的错误(已报告 here,包括比较版本的视频)。
    当您从我尝试的有问题的版本启动该应用程序时,可能会导致警报被清除。

    如果您从启动器启动该应用程序,则可以正常运行。

    这是设置警报的当前代码:
            val timeToTrigger = System.currentTimeMillis() + 10 * 1000
    val pendingShowList = PendingIntent.getActivity(this, 1, Intent(this, SomeActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
    val pendingIntent = PendingIntent.getBroadcast(this, 1, Intent(this, AlarmReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
    manager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingShowList), pendingIntent)

    我什至不必使用“pendingShowList”。使用null也可以。

    关于android - 在所有最新的Android限制之后,如何设置要在确切时间安排的警报?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60079472/

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