我提供的服务实际上是一个简单的后台计数器。
仅将1加到最后一个数字,然后转到UI。
我以前的问题是,当智能手机关闭或不充电时,Handler()有时工作非常缓慢。最近我找到了the same problem in this forum。我在服务中添加了PowerManager.WakeLock
,并且一切正常...
但是我决定测试更长的时间,并同时在三部智能手机上启动该应用,并将其放置约一个半小时。当我回来时,我发现他们三个之间完全不同。
第一个显示5100(1小时25分钟),第二个显示2800(46分钟),第三个显示5660(1小时34分钟)。我非常确定唤醒锁将正确完成这项工作,但现在我不知道那里发生了什么。
这是我的服务代码:
class Timer_Service : Service() {
companion object {
val PARAM_OUT_MSG = "0"
}
var i = 0
private lateinit var wakeLock: PowerManager.WakeLock
private lateinit var mHandler: Handler
private lateinit var mRunnable: Runnable
override fun onBind(p0: Intent?): IBinder? {
TODO("not implemented")
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"ExampleApp:Wakelock"
)
wakeLock.acquire()
val broadcastIntent = Intent()
broadcastIntent.action = "com.example.infocell.action.RESPONSE"
mHandler = Handler()
mRunnable = Runnable {
showOrderNumber()
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
broadcastIntent.putExtra(PARAM_OUT_MSG, i.toString())
sendBroadcast(broadcastIntent)
}
mHandler.postDelayed(mRunnable, 1000)
return START_NOT_STICKY
}
override fun onDestroy() {
super.onDestroy()
mHandler.removeCallbacks(mRunnable)
}
private fun showOrderNumber() {
i += 1
mHandler.postDelayed(mRunnable, 1000)
}
}
清单还包含<uses-permission android:name="android.permission.WAKE_LOCK" />
最后经过各种测试,我得到了最精确的方法来做一个简单的计数器。我建议使用Handle()
代替相对可靠的Timer()
方法。在我所有的四款智能手机上,它的工作性能都绝对相等。为此还需要唤醒锁。我也将测试JobScheduler()
和CountDownTimer()
以获取所有测试结果,但到目前为止我对计时器感到满意。
如果有人正在寻找此类任务的解决方案,我将共享我的代码。
class Timer_Service : Service() {
companion object {
val PARAM_OUT_MSG = "0"
}
var i = 0
private lateinit var wakeLock: PowerManager.WakeLock
private lateinit var timer: Timer
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"ExampleApp:Wakelock"
)
wakeLock.acquire()
val broadcastIntent = Intent()
broadcastIntent.action = "com.example.infocell.action.RESPONSE"
timer = Timer()
val task = object : TimerTask() {
override fun run() {
if (Trigger.getTrigger() == 0){
showOrderNumber()
// bring 'i' value to main activity
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
broadcastIntent.putExtra(PARAM_OUT_MSG, i.toString())
sendBroadcast(broadcastIntent)
}
}
}
timer.schedule(task,0, 1000)
return START_STICKY
}
override fun onCreate() {
super.onCreate()
var notification = createNotification()
startForeground(1, notification)
}
private fun createNotification(): Notification {
val notificationChannelId = "ENDLESS SERVICE CHANNEL"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
val channel = NotificationChannel(
notificationChannelId,
"My Service",
NotificationManager.IMPORTANCE_HIGH
).let {
it.description = "Service channel"
it.enableLights(true)
it.lightColor = Color.RED
it.enableVibration(true)
it.vibrationPattern = longArrayOf(100)
it
}
notificationManager.createNotificationChannel(channel)
}
val pendingIntent: PendingIntent = Intent(this, MainActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, 0)
}
val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Notification.Builder(
this,
notificationChannelId
) else Notification.Builder(this)
return builder
.setContentTitle("My Service")
.setContentText("Endless service working...")
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker("Ticker text")
.setPriority(Notification.PRIORITY_HIGH) // for under android 26 compatibility
.build()
}
override fun onDestroy() {
super.onDestroy()
// Trigger is a separate kotlin class with variables
if (Trigger.getTrigger() == 1){
timer.cancel()
timer.purge()
}
}
private fun showOrderNumber() {
i += 1
}
}