问题描述
我正在使用天文钟-但在通知中保留天文钟-服务-应用程序对我来说很困难
场景-
- 点击按钮启动计时器
- 应用在后台运行时,请在自定义通知中启动计时器。
- 单击“计时器通知”,在通知托盘中启动带有计时器计数的应用程序
- Killing应用程序应在通知中继续运行计时器,从应用程序图标打开应用程序,或通知应从通知中的相同计数继续运行计时器。
方法-
- 在暂停时节省时间
- 恢复应用程序时-将计时器值设置为天文钟表
onPause代码-
override fun onPause() {
super.onPause()
MainActivity.appPauseTime = SystemClock.elapsedRealtime()
val intent = Intent(activity,MyTimerService::class.java)
intent.action = MyTimerService.START_FOREGROUND_SERVICE
intent.putExtra("timer",chronometer.base)
activity?.startService(intent)
}
onResume的代码-
override fun onResume() {
super.onResume()
if (MainActivity.appPauseTime > 0L) {
MainActivity.appResumeTime = SystemClock.elapsedRealtime()
startTimer(SystemClock.elapsedRealtime() - (MainActivity.appResumeTime - MainActivity.appPauseTime))
val intent = Intent(activity,MyTimerService::class.java)
intent.action = MyTimerService.STOP_FOREGROUND_SERVICE
activity?.stopService(intent)
}
}
没有寻找勺子饲料的答案,所以在下面发布了答案。
解决方法
我找到了一种运行计时器的方法-即天文钟
在片段或活动布局中设置天文钟表
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<Button
android:id="@+id/button_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/chronometer" />
<Chronometer
android:id="@+id/chronometer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textColor="@android:color/holo_red_dark"
android:textSize="48sp"
android:textStyle="bold"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
单击按钮或您想要的任何情况下启动计时器-
private fun startTimer(startTime: Long) {
chronometer.base = startTime
chronometer.setOnChronometerTickListener {
Log.i("Timer--->","Countdown---> " + chronometer.base)
// formattedTime = getFormattedTime(chronometer.base)
}
chronometer.start()
}
最主要的是通过天文钟发布通知-在这里,我会让您知道该怎么做
override fun onPause() {
super.onPause()
val intent = Intent(activity,MyTimerService::class.java)
intent.action = MyTimerService.START_FOREGROUND_SERVICE
intent.putExtra("timer",chronometer.base)
activity?.startService(intent)
}
这是Service类-确保您在清单中注册它并提供前台用户的权限
class MyTimerService : Service() {
private lateinit var notificationView: RemoteViews
private lateinit var notiBuilder: Notification
companion object {
const val NOTIFICATION_CHANNEL_ID = "100"
const val NOTIFICATION_ID = 10
const val START_FOREGROUND_SERVICE = "start_foreground_service"
const val STOP_FOREGROUND_SERVICE = "stop_foreground_service"
}
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
notificationView = RemoteViews(packageName,R.layout.notification_layout)
createNotification()
}
private fun getPendingIntent(): PendingIntent? {
// Create an explicit intent for an Activity in your app
val intent = Intent(this,MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
}
// intent.putExtra("timer",notificationView.)
return PendingIntent.getActivity(this,intent,0)
}
private fun createNotification() {
// Create the NotificationChannel,but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannelForOreo()
} else {
createNotificationBelowOreo()
}
}
private fun createNotificationBelowOreo() {
// Create notification builder.
val builder = NotificationCompat.Builder(this)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_baseline_timer_24)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationView)
.setContentIntent(getPendingIntent())
.setContentTitle(baseContext.getString(R.string.app_name))
.setContentText("Active Session")
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_MAX)
// Build the notification.
notiBuilder = builder.build()
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannelForOreo() {
val chan =
NotificationChannel(
NOTIFICATION_CHANNEL_ID,baseContext.getString(R.string.channel_name),NotificationManager.IMPORTANCE_DEFAULT
)
// chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val manager = (getSystemService(NOTIFICATION_SERVICE) as NotificationManager)
manager.createNotificationChannel(chan)
val notificationBuilder = NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID)
notiBuilder = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_baseline_timer_24)
.setContentTitle(baseContext.getString(R.string.app_name))
.setContentText("Active Session")
.setAutoCancel(true)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationView)
.setCategory(Notification.CATEGORY_SERVICE)
.setContentIntent(getPendingIntent())
.build()
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID,notificationBuilder.build())
}
private fun showNotification() {
// Start foreground service.
startForeground(NOTIFICATION_ID,notiBuilder)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onStartCommand(intent: Intent?,flags: Int,startId: Int): Int {
super.onStartCommand(intent,flags,startId)
if (intent?.extras != null) {
when (intent.action) {
START_FOREGROUND_SERVICE -> {
val timestamp = intent.getLongExtra("timer",0)
// set chronometer
notificationView.setChronometer(R.id.chronometer,timestamp,null,true)
// show notification
showNotification()
}
STOP_FOREGROUND_SERVICE -> {
stopForeground(true)
stopSelf()
}
}
}
return START_STICKY
}
}
要处理计时器持久性,请将计时器的时间保存在onPause中-
override fun onPause() {
super.onPause()
**Make sure you are saving this time at central place**
MainActivity.appPauseTime = chronometer.base
}
在onResume中-
override fun onResume() {
super.onResume()
if (MainActivity.appPauseTime > 0L) {
startTimer(MainActivity.appPauseTime)
val intent = Intent(activity,MyTimerService::class.java)
intent.action = MyTimerService.STOP_FOREGROUND_SERVICE
activity?.stopService(intent)
}
}
如果您认为有帮助,请告诉我并进行投票。