我当前正在构建一个通过向后端发送请求来启动会话的应用。之后,该应用程序必须每4.5分钟发送一次心跳请求。如果自上次成功请求后4.5分钟后,该应用程序未向后端发送请求,则该会话将被终止。心跳请求可以提前发送,这也意味着下一次心跳必须在该请求之后4.5分钟发送。 用户开始会话后,他应该能够将应用程序置于后台,以便将该设备用于其他用途。
我正在努力提出一种可以解决背景限制(打ze模式等)的解决方案。
我当前正在使用前台服务运行该应用程序。但是如果我不积极使用设备,则请求会在几分钟后停止。我尝试了WorkManager和AlarmManager。但是请求一直在延迟。
我玩过REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
,这似乎行得通,但是我不想使用这种方法,因为Google似乎真的不喜欢使用此权限的应用程序。
我创建了一个测试应用程序,可以使用不同的方法。也许我做错了什么?
服务:
class MainService : Service() {
private lateinit var wakeLock: PowerManager.WakeLock
override fun onBind(intent: Intent?): IBinder? = null
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= 26) {
val appName = getString(R.string.app_name)
val channelName = "$appName channel name"
val channelImportance = NotificationManager.IMPORTANCE_HIGH
val channelDescription = "$appName channel description"
createNotificationChannel(this, NOTIFICATION_CHANNEL_ID, channelName, channelImportance, channelDescription)
}
val notification = createOngoingNotification(this, NOTIFICATION_REQUEST_CODE, R.mipmap.ic_launcher_round, "Content Text")
startForeground(1000, notification)
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag").apply {
acquire(1 * 60 * 60 * 1000L)
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
intent?.action?.let {
if (it == "Heartbeat") {
val v = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE))
}
}
}
setNext()
return START_STICKY
}
private fun setNext() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val intent = Intent(applicationContext, MainService::class.java)
intent.action = "Heartbeat"
val pendingIntent = PendingIntent.getService(applicationContext, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5 * 1000, pendingIntent)
}
}
override fun onDestroy() {
stopForeground(true)
wakeLock.release()
super.onDestroy()
}
companion object {
const val REQUEST_CODE = 101
const val NOTIFICATION_REQUEST_CODE = 100
const val NOTIFICATION_CHANNEL_ID = "notification_channel_id"
fun createOngoingNotification(context: Context, requestCode: Int, icon: Int, text: String): Notification {
val contentIntent = Intent(context, MainActivity::class.java)
.setAction(Intent.ACTION_MAIN)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
val contentPendingIntent = PendingIntent.getActivity(context, requestCode, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT)
return NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setOngoing(true)
.setSmallIcon(icon)
.setContentTitle("Test Notification")
.setContentText(text)
.setContentIntent(contentPendingIntent)
.build()
}
@RequiresApi(api = 26)
fun createNotificationChannel(context: Context,
id: String, name: String, importance: Int,
description: String) {
val channel = NotificationChannel(id, name, importance)
channel.description = description
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
}
有什么办法解决我的问题吗?
答案 0 :(得分:0)
我认为,前台服务可能会停止,因为您在设置警报后未在其中执行任何操作。如果您正在使用前景服务,它将继续运行,因此,为了使其能够定期工作,我将放置一个可观察到的对象,例如每5秒发出一个值。您仅需要在4.5分钟后发出的一项,但这将使前台服务保持活动状态直到您需要它为止。使用rxjava:
Observable.intervalRange( 0 , 54, 0, 5, TimeUnit.SECONDS )
.doOnNext{
//You may not need this
}
.doOnComplete {
//heartbeat
//start this observable again for other 4.5 minutes
}
您将每5秒发出一次值54次。 54x5 = 270秒(4.5分钟)