【问题标题】:How to use Android AlarmManager in Fragment in Kotlin?如何在 Kotlin 的 Fragment 中使用 Android AlarmManager?
【发布时间】:2020-10-08 18:13:24
【问题描述】:

我似乎无法让 AlarmManager 在片段中工作。我的接收者的 onReceive() 方法永远不会被执行。我假设我可能会以错误的方式使用上下文,但我也无法让它在 Activity 中工作。我还在清单中注册了接收器。

MyFragment.kt

class MyFragment : Fragment() {

...

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        super.onViewCreated(view, savedInstanceState)

        var alarmMgr: AlarmManager? = null
        lateinit var alarmIntent: PendingIntent

        alarmMgr = context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmIntent = Intent(context, Receiver::class.java).let { intent ->

                PendingIntent.getService(context, 0, intent, 0)

        }

        val calendar: Calendar = Calendar.getInstance().apply {

        timeInMillis = System.currentTimeMillis()

        // The EditText includes a time in 24-hour format (e.g. 12:34)
        set(Calendar.HOUR_OF_DAY, editText.text.toString().substringBefore(":").toInt())
        set(Calendar.MINUTE, editText.text.toString().substringAfter(":").toInt())

        }

        Log.d("ALARM", "CREATED")

        alarmMgr?.set(
              AlarmManager.RTC,
              calendar.timeInMillis,
              alarmIntent
        )

    }

}

Receiver.kt

class Receiver : BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {

        Log.d("ALARM", "RECEIVED")

    }

}

AndroidManifest.xml

<application
...
    <receiver android:name="com.example.name.Receiver" />
</application>

【问题讨论】:

    标签: android kotlin broadcastreceiver alarmmanager receiver


    【解决方案1】:

    第一件事:

    AndroidManifest.xml

    <receiver
      android:name="com.example.name.Receiver"
      android:enabled="true"
      android:exported="true">
       <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
       </intent-filter>
    </receiver>
    

    然后,在这种情况下,在您的 Fragment 中,我建议在其他地方执行此操作:

    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val intent = Intent(context, Receiver::class.java)
    
    // Used for filtering inside Broadcast receiver
    intent.action = "MyBroadcastReceiverAction"
    val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
    
    // In this particular example we are going to set it to trigger after 30 seconds.
    // You can work with time later when you know this works for sure.
    val msUntilTriggerHour: Long = 30000
    val alarmTimeAtUTC: Long = System.currentTimeMillis() + msUntilTriggerHour
    
    // Depending on the version of Android use different function for setting an 
    // Alarm.
    // setAlarmClock() - used for everything lower than Android M
    // setExactAndAllowWhileIdle() - used for everything on Android M and higher
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
      alarmManager.setAlarmClock(
      AlarmManager.AlarmClockInfo(alarmTimeAtUTC, pendingIntent),
      pendingIntent
      )
    } else {
      alarmManager.setExactAndAllowWhileIdle(
      AlarmManager.RTC_WAKEUP,
      alarmTimeAtUTC,
      pendingIntent
      )
    }
    

    然后在您的广播接收器中,我们执行以下操作:

    class Receiver : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            // We use this to make sure that we execute code, only when this exact 
            // Alarm triggered our Broadcast receiver
            if (intent?.action == "MyBroadcastReceiverAction") {
               Log.d("ALARM", "RECEIVED")
            }
        }
    }
    

    【讨论】:

    • 当设备使用 oreo 及更高版本重新启动时,这是否在后台工作?
    • 我们是否应该将警报管理器代码放在单独的类中,然后简单地将其放入我们的片段或活动中?
    • 为什么你使用 setExactAndAllowWhileIdle 而不是 setExact only?
    猜你喜欢
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    相关资源
    最近更新 更多