android - Android Kotlin 服务问题
问题描述
我已经实现了一个在应用程序后台运行的服务。服务每分钟调用一次该函数,检查是否到了触发通知的时间-提醒(检索当前日期和时间并与数据库中保存的数据进行比较。如果日期和时间匹配,则触发通知. 该函数每 1 分钟调用一次。该函数必须每 1 分钟检查一次用户使用应用程序时的情况,应用程序在后台运行,不使用应用程序以及手机如何处于睡眠状态。通过实现提醒前面一天晚上到晚上和第二天。提醒出现在晚上的同一天,第二天的第一个提醒。下一个不出现。另一方面,设置为 5 分钟的提醒有效,设置为 30不再。
- 时间漂移 - 当屏幕打开并且手机完全唤醒时,两个连续事件之间的间隔大部分时间会保持不变,但可能会不时跳跃(加长)
- 手机进入睡眠模式
你们中的任何人都知道如何解决这个问题,绕过它?
前台服务
class ForegroundService : Service() {
companion object {
val CHANNEL_ID = "ForegroundServiceChannel"
val CHANNEL_ID_CHILD = "ForegroundServiceChannelCHILD"
private var isRunning = true
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val input = intent.getIntExtra("time",15)
createNotificationChannel()
val notificationIntent = Intent(this, Menu::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
0, notificationIntent, 0
)
val wakeLock: PowerManager.WakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::AR_Apteczka").apply {
acquire()
}
}
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Twoja Elektroniczna Apteczka")
.setContentText("Dbamy o Twoje zdrowie")
.setSmallIcon(com.example.agnieszka.ar_apteczka.R.drawable.pills)
.setOnlyAlertOnce(true)
//.setContentIntent(pendingIntent)
//.setSound(null)
.build()
startForeground(1, notification)
isRunning = true
val context = this
val intent = Intent(this, ShowAllTodaysMedicines::class.java)
val pendingIntentNotification = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
doAsync {
while(true)
{
var message= createReminderMessage(context)
uiThread {
if(true) {
if (message != "Nadszedł czas by zażyć: ") {
val notification =
NotificationCompat.Builder(context, CHANNEL_ID_CHILD)
.setContentTitle("Zażyj leki")
.setContentText(message)
.setSmallIcon(com.example.agnieszka.ar_apteczka.R.drawable.pills)
.setContentIntent(pendingIntentNotification)
.setAutoCancel(true)
.build()
with(NotificationManagerCompat.from(context)) {
notificationManager.notify(2, notification)
}
}
}
}
//SystemClock.sleep(60000)
SystemClock.sleep(60*1000-SystemClock.elapsedRealtime()%1000)
// SystemClock.sleep(50000) //10*1000-SystemClock.elapsedRealtime()%1000
}
}
return START_NOT_STICKY
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onDestroy() {
super.onDestroy()
isRunning = false
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val serviceChannel = NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
//NotificationManager.IMPORTANCE_DEFAULT
NotificationManager.IMPORTANCE_DEFAULT
)
//serviceChannel.setSound(null, null) //
val serviceChannel2 = NotificationChannel(
CHANNEL_ID_CHILD,
"Foreground Service ChannelChild ",
NotificationManager.IMPORTANCE_DEFAULT
//NotificationManager.IMPORTANCE_LOW
)
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(serviceChannel)
manager.createNotificationChannel(serviceChannel2)
}
}
fun reminderForNow(context: Context) : ArrayList<Reminder> {
var listOfReminder : ArrayList<Reminder> = ArrayList()
var timetoday = takeTimeNow()
var dateToday = takeTodayDate()
val dbHelper = SQLConector(context)
val allRemindersList = dbHelper.getAllReminders()
for (i: Reminder in allRemindersList) {
if (i.reminderDate == dateToday && i.ReminderTime == timetoday) {
var reminder = Reminder(
i.idReminder,
i.medicineName,
i.reminderDate,
i.ReminderTime
)
listOfReminder.add(reminder)
}
}
return listOfReminder
}
private fun createReminderMessage(p0: Context) : String{
var message = "Nadszedł czas by zażyć: "
var listOfReminders = reminderForNow(p0)
if(listOfReminders.count() > 0){
for (i: Reminder in listOfReminders) {
message += i.medicineName + ", "
}
}
return message
}
private fun takeTodayDate():String{
val current = LocalDateTime.now()
val formatDate = DateTimeFormatter.ofPattern("yyyy-MM-dd")
var currentDate = current.format(formatDate).toString()
return currentDate
}
private fun takeTimeNow() : String{
val current = LocalDateTime.now()
val formatTime = DateTimeFormatter.ofPattern("HH:mm")
return current.format(formatTime).toString()
}
}
**Main Activity**
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
binding.buttonStart.setOnClickListener { startService() }
binding.buttonStop.setOnClickListener {stopService() }
startService()
}
private fun startService() {
val serviceIntent = Intent(this, ForegroundService::class.java)
serviceIntent.putExtra("time", 1)
ContextCompat.startForegroundService(this, serviceIntent)
}
private fun stopService() {
val serviceIntent = Intent(this, ForegroundService::class.java)
stopService(serviceIntent)
}
}
*Manifest*
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="false"
android:icon="@drawable/pills"
android:label="@string/nameOfApplications"
android:roundIcon="@drawable/icon"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".ForegroundService"
android:enabled="true"
android:exported="true"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
解决方案
推荐阅读
- django - 为什么我的 django 网络服务器在尝试发送密码重置邮件后停止
- c - 如何在 GBDK 上获得随机数?
- maven - 如何使用 curl 从 REST API 在 Nexus 2 上上传具有不同分类器和相同 pom.xml 的 jar?
- spring-boot - osbwservlet.support.ErrorPageFilter : 从请求 [0] Primefaces 转发到错误页面
- mysql - 如何使用 regexp_substr MariaDB 从字符串中提取最后一个日期
- wpf - 如何将正确的上下文传递给 WPF ListView 的 ItemTemplate 中的 DataTemplate
- javascript - 赛普拉斯 waitUntil 元素被聚焦
- r - 数据管理:使用 R 展平数据
- python - 如何修复数据框拆分和爆炸方法无法正常工作?
- python - 如何解决电视节目 UnboundLocalError