diff --git a/app/build.gradle b/app/build.gradle index 131a3bd..15fd828 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id 'kotlin-android' - id 'kotlin-kapt' + id 'com.google.devtools.ksp' } def keystorePropertiesFile = rootProject.file("key.properties") @@ -18,14 +18,14 @@ android { applicationId "com.maary.liveinpeace" minSdk 31 targetSdk 34 - versionCode 4 - versionName "2.1_beta" + versionCode 5 + versionName "2.2_beta" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildFeatures { viewBinding true - dataBinding true + dataBinding false } splits { // Configures multiple APKs based on ABI. @@ -85,16 +85,16 @@ android { dependencies { - implementation 'androidx.core:core-ktx:1.10.1' + implementation 'androidx.core:core-ktx:1.13.1' implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.9.0' + implementation 'com.google.android.material:material:1.12.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation "androidx.activity:activity-ktx:1.7.2" - implementation 'androidx.databinding:databinding-runtime:8.0.2' + implementation 'androidx.activity:activity-ktx:1.9.0' + implementation 'androidx.databinding:databinding-runtime:8.4.1' - def lifecycle_version = "2.6.1" + def lifecycle_version = '2.8.0' // LiveData implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" @@ -103,12 +103,12 @@ dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version" - def room_version = "2.6.0-alpha01" + def room_version = '2.6.1' implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" - implementation "androidx.room:room-ktx:2.5.1" - kapt "androidx.room:room-compiler:$room_version" + implementation 'androidx.room:room-ktx:2.6.1' + ksp "androidx.room:room-compiler:$room_version" testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b9f10f1..4c04858 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,16 @@ + + + + + + @@ -62,6 +72,11 @@ android:exported="false"> + + + + + diff --git a/app/src/main/java/com/maary/liveinpeace/Constants.kt b/app/src/main/java/com/maary/liveinpeace/Constants.kt index 0974f07..67c7a22 100644 --- a/app/src/main/java/com/maary/liveinpeace/Constants.kt +++ b/app/src/main/java/com/maary/liveinpeace/Constants.kt @@ -23,6 +23,7 @@ class Constants { const val ID_NOTIFICATION_ALERT = 2 const val ID_NOTIFICATION_PROTECT = 4 const val ID_NOTIFICATION_WELCOME = 0 + const val ID_NOTIFICATION_SLEEPTIMER = 5 // 设置图像式图标 Action const val ACTION_NAME_SET_IMG = "com.maary.liveinpeace.receiver.SettingsReceiver.SetIconImg" // 设置字符式图标 Action @@ -37,6 +38,11 @@ class Constants { const val ACTION_NAME_SETTINGS = "com.maary.liveinpeace.receiver.SettingsReceiver" // 静音广播名称 const val BROADCAST_ACTION_MUTE = "com.maary.liveinpeace.MUTE_MEDIA" + const val BROADCAST_ACTION_SLEEPTIMER_CANCEL = "com.maary.liveinpeace.action.CANCEL" + const val BROADCAST_ACTION_SLEEPTIMER_INCREMENT = "com.maary.liveinpeace.action.INCREMENT" + const val BROADCAST_ACTION_SLEEPTIMER_DECREMENT = "com.maary.liveinpeace.action.DECREMENT" + const val BROADCAST_ACTION_SLEEPTIMER_TOGGLE = "com.maary.liveinpeace.sleeptimer.TOGGLE" + const val BROADCAST_ACTION_SLEEPTIMER_UPDATE = "com.maary.liveinpeace.sleeptimer.UPDATE" // 前台服务状态改变广播 const val BROADCAST_ACTION_FOREGROUND = "com.maary.liveinpeace.ACTION_FOREGROUND_SERVICE_STATE" const val BROADCAST_FOREGROUND_INTENT_EXTRA = "isForegroundServiceRunning" @@ -48,6 +54,7 @@ class Constants { const val CHANNEL_ID_ALERT = "LIP_ALERT" const val CHANNEL_ID_PROTECT = "LIP_PROTECT" const val CHANNEL_ID_WELCOME = "LIP_WELCOME" + const val CHANNEL_ID_SLEEPTIMER = "LIP_SLEEPTIMER" // 提醒时间 const val ALERT_TIME: Long = 2*60*60*1000 // 延后时间 @@ -57,6 +64,7 @@ class Constants { const val ID_NOTIFICATION_GROUP_SETTINGS = "LIP_notification_group_settings" const val ID_NOTIFICATION_GROUP_ALERTS = "LIP_notification_group_alerts" const val ID_NOTIFICATION_GROUP_PROTECT = "LIP_notification_group_protect" + const val ID_NOTIFICATION_GROUP_SLEEPTIMER = "LIP_notification_group_sleeptimer" const val PATTERN_DATE_DATABASE = "yyyy-MM-dd" const val PATTERN_DATE_BUTTON = "MM/dd" } diff --git a/app/src/main/java/com/maary/liveinpeace/HistoryActivity.kt b/app/src/main/java/com/maary/liveinpeace/HistoryActivity.kt index e9ec9ee..19043be 100644 --- a/app/src/main/java/com/maary/liveinpeace/HistoryActivity.kt +++ b/app/src/main/java/com/maary/liveinpeace/HistoryActivity.kt @@ -5,7 +5,6 @@ import android.view.View import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat -import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.datepicker.CalendarConstraints import com.google.android.material.datepicker.DateValidatorPointBackward @@ -61,7 +60,7 @@ class HistoryActivity : AppCompatActivity(), DeviceMapChangeListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) - binding = DataBindingUtil.setContentView(this, R.layout.activity_history) + binding = ActivityHistoryBinding.inflate(layoutInflater) setContentView(binding.root) var pickedDate : String = LocalDate.now().toString() diff --git a/app/src/main/java/com/maary/liveinpeace/SleepNotification.kt b/app/src/main/java/com/maary/liveinpeace/SleepNotification.kt new file mode 100644 index 0000000..53e2384 --- /dev/null +++ b/app/src/main/java/com/maary/liveinpeace/SleepNotification.kt @@ -0,0 +1,103 @@ +package com.maary.liveinpeace + +import android.app.Notification +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.graphics.drawable.Icon +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_MUTE +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_CANCEL +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_DECREMENT +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_INCREMENT +import java.text.DateFormat +import java.util.Date +import java.util.concurrent.TimeUnit +import com.maary.liveinpeace.SleepNotification.Action.CANCEL +import com.maary.liveinpeace.SleepNotification.Action.INCREMENT +import com.maary.liveinpeace.SleepNotification.Action.DECREMENT +import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_SLEEPTIMER +import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_GROUP_SLEEPTIMER +import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_SLEEPTIMER +import com.maary.liveinpeace.receiver.MuteMediaReceiver + + +object SleepNotification { + + private val TIMEOUT_INITIAL_MILLIS = TimeUnit.MINUTES.toMillis(30) + private val TIMEOUT_INCREMENT_MILLIS = TimeUnit.MINUTES.toMillis(10) + private val TIMEOUT_DECREMENT_MILLIS = TimeUnit.MINUTES.toMillis(10) + + private enum class Action(private val value: String) { + CANCEL(BROADCAST_ACTION_SLEEPTIMER_CANCEL) { + override fun title(context: Context) = context.getText(android.R.string.cancel) + }, + INCREMENT(BROADCAST_ACTION_SLEEPTIMER_INCREMENT) { + override fun title(context: Context) = "+" + TimeUnit.MILLISECONDS.toMinutes(TIMEOUT_INCREMENT_MILLIS) + }, + DECREMENT(BROADCAST_ACTION_SLEEPTIMER_DECREMENT) { + override fun title(context: Context) = "-" + TimeUnit.MILLISECONDS.toMinutes(TIMEOUT_DECREMENT_MILLIS) + }, + ; + + companion object { + fun parse(value: String?): Action? = entries.firstOrNull { it.value == value } + } + + fun intent(context: Context): Intent = Intent(context, MuteMediaReceiver::class.java).setAction(value) + + fun pendingIntent(context: Context, cancel: Boolean = false): PendingIntent? = + PendingIntent.getBroadcast(context, 0, intent(context), PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ).apply { if (cancel) cancel() } + + fun action(context: Context, cancel: Boolean = false): Notification.Action.Builder = + Notification.Action.Builder(Icon.createWithResource(context, 0), title(context), pendingIntent(context, cancel)) + + abstract fun title(context: Context): CharSequence? + } + + fun Context.notificationManager(): NotificationManager? = getSystemService(NotificationManager::class.java) + + fun Context.find() = notificationManager()?.activeNotifications?.firstOrNull { it.id == ID_NOTIFICATION_SLEEPTIMER }?.notification + + fun Context.handle(intent: Intent?) = when (Action.parse(intent?.action)) { + INCREMENT -> update(TIMEOUT_INCREMENT_MILLIS) + DECREMENT -> update(-TIMEOUT_DECREMENT_MILLIS) + CANCEL -> cancel() + null -> Unit + } + + fun Context.toggle() = if (find() == null) show() else cancel() + + private fun Context.cancel() = notificationManager()?.cancel(ID_NOTIFICATION_SLEEPTIMER) ?: Unit + + private fun Context.update(timeout: Long) = find()?.let { it.`when` - System.currentTimeMillis() }?.let { if (it > -timeout) it + timeout else it }?.let { show(it) } + + private fun Context.show(timeout: Long = TIMEOUT_INITIAL_MILLIS) { + require(timeout > 0) + val eta = System.currentTimeMillis() + timeout + + val muteMediaIntent = Intent(this, MuteMediaReceiver::class.java) + muteMediaIntent.action = BROADCAST_ACTION_MUTE + val pendingMuteIntent = PendingIntent.getBroadcast(this, 0, muteMediaIntent, PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) + + + val notification = Notification.Builder(this, CHANNEL_ID_SLEEPTIMER) + .setCategory(Notification.CATEGORY_EVENT) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setOnlyAlertOnce(true) + .setOngoing(true) + .setSmallIcon(R.drawable.ic_tile) + .setSubText(DateFormat.getTimeInstance(DateFormat.SHORT).format(Date(eta))) + .setShowWhen(true).setWhen(eta) + .setGroup(ID_NOTIFICATION_GROUP_SLEEPTIMER) + .setUsesChronometer(true).setChronometerCountDown(true) + .setTimeoutAfter(timeout) + .setDeleteIntent(pendingMuteIntent) + .addAction(INCREMENT.action(this).build()) + .addAction(DECREMENT.action(this, cancel = timeout <= TIMEOUT_DECREMENT_MILLIS).build()) + .addAction(CANCEL.action(this).build()) + .build() + notificationManager()?.notify(ID_NOTIFICATION_SLEEPTIMER, notification) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/maary/liveinpeace/receiver/MuteMediaReceiver.kt b/app/src/main/java/com/maary/liveinpeace/receiver/MuteMediaReceiver.kt index 91effb2..d80cb32 100644 --- a/app/src/main/java/com/maary/liveinpeace/receiver/MuteMediaReceiver.kt +++ b/app/src/main/java/com/maary/liveinpeace/receiver/MuteMediaReceiver.kt @@ -4,15 +4,36 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.media.AudioManager -import com.maary.liveinpeace.Constants +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_MUTE +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_CANCEL +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_DECREMENT +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_INCREMENT +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_TOGGLE +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_UPDATE +import com.maary.liveinpeace.SleepNotification.handle +import com.maary.liveinpeace.SleepNotification.toggle class MuteMediaReceiver: BroadcastReceiver() { override fun onReceive(p0: Context?, p1: Intent?) { - if (p1?.action == Constants.BROADCAST_ACTION_MUTE){ + if (p1?.action == BROADCAST_ACTION_MUTE){ val audioManager = p0?.getSystemService(Context.AUDIO_SERVICE) as AudioManager do { audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0) } while (audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) > 0) } + + if (p1?.action == BROADCAST_ACTION_SLEEPTIMER_CANCEL || + p1?.action == BROADCAST_ACTION_SLEEPTIMER_INCREMENT || + p1?.action == BROADCAST_ACTION_SLEEPTIMER_DECREMENT) { + p0?.handle(p1) + val intent = Intent(BROADCAST_ACTION_SLEEPTIMER_UPDATE) + p0?.sendBroadcast(intent) + } + + if (p1?.action == BROADCAST_ACTION_SLEEPTIMER_TOGGLE) { + p0?.toggle() + val intent = Intent(BROADCAST_ACTION_SLEEPTIMER_UPDATE) + p0?.sendBroadcast(intent) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/maary/liveinpeace/receiver/SleepReceiver.kt b/app/src/main/java/com/maary/liveinpeace/receiver/SleepReceiver.kt new file mode 100644 index 0000000..cab5619 --- /dev/null +++ b/app/src/main/java/com/maary/liveinpeace/receiver/SleepReceiver.kt @@ -0,0 +1,18 @@ +package com.maary.liveinpeace.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_UPDATE + +abstract class SleepReceiver: BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent) { + if (intent.action == BROADCAST_ACTION_SLEEPTIMER_UPDATE + ) { + updateNotification(context) + } + } + + abstract fun updateNotification(context: Context) +} \ No newline at end of file diff --git a/app/src/main/java/com/maary/liveinpeace/service/ForegroundService.kt b/app/src/main/java/com/maary/liveinpeace/service/ForegroundService.kt index a1eca08..d7b6574 100644 --- a/app/src/main/java/com/maary/liveinpeace/service/ForegroundService.kt +++ b/app/src/main/java/com/maary/liveinpeace/service/ForegroundService.kt @@ -16,8 +16,10 @@ import android.graphics.Rect import android.media.AudioDeviceCallback import android.media.AudioDeviceInfo import android.media.AudioManager +import android.os.Build import android.os.IBinder import android.util.Log +import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.graphics.drawable.IconCompat @@ -26,6 +28,8 @@ import com.maary.liveinpeace.Constants.Companion.ACTION_TOGGLE_AUTO_CONNECTION_A import com.maary.liveinpeace.Constants.Companion.ALERT_TIME import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_FOREGROUND import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_MUTE +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_TOGGLE +import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_SLEEPTIMER_UPDATE import com.maary.liveinpeace.Constants.Companion.BROADCAST_FOREGROUND_INTENT_EXTRA import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_DEFAULT import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_PROTECT @@ -45,16 +49,20 @@ import com.maary.liveinpeace.DeviceMapChangeListener import com.maary.liveinpeace.DeviceTimer import com.maary.liveinpeace.HistoryActivity import com.maary.liveinpeace.R +import com.maary.liveinpeace.SleepNotification.find import com.maary.liveinpeace.database.Connection import com.maary.liveinpeace.database.ConnectionDao import com.maary.liveinpeace.database.ConnectionRoomDatabase import com.maary.liveinpeace.receiver.MuteMediaReceiver import com.maary.liveinpeace.receiver.SettingsReceiver +import com.maary.liveinpeace.receiver.SleepReceiver import com.maary.liveinpeace.receiver.VolumeReceiver import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import java.text.DateFormat import java.time.LocalDate +import java.util.Date class ForegroundService: Service() { @@ -134,6 +142,15 @@ class ForegroundService: Service() { } } + private val sleepReceiver = object : SleepReceiver() { + @SuppressLint("MissingPermission") + override fun updateNotification(context: Context) { + with(NotificationManagerCompat.from(applicationContext)){ + notify(ID_NOTIFICATION_FOREGROUND, createForegroundNotification(applicationContext)) + } } + + } + private fun saveDataWhenStop(){ val disconnectedTime = System.currentTimeMillis() @@ -287,6 +304,7 @@ class ForegroundService: Service() { } } + @RequiresApi(Build.VERSION_CODES.TIRAMISU) override fun onCreate() { super.onCreate() @@ -301,6 +319,11 @@ class ForegroundService: Service() { } registerReceiver(volumeChangeReceiver, filter) + val sleepFilter = IntentFilter().apply { + addAction(BROADCAST_ACTION_SLEEPTIMER_UPDATE) + } + registerReceiver(sleepReceiver, sleepFilter, RECEIVER_NOT_EXPORTED) + database = ConnectionRoomDatabase.getDatabase(applicationContext) connectionDao = database.connectionDao() startForeground(ID_NOTIFICATION_FOREGROUND, createForegroundNotification(context = applicationContext)) @@ -323,11 +346,11 @@ class ForegroundService: Service() { saveDataWhenStop() // 取消注册音量变化广播接收器 unregisterReceiver(volumeChangeReceiver) + unregisterReceiver(sleepReceiver) audioManager.unregisterAudioDeviceCallback(audioDeviceCallback) val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.cancel(ID_NOTIFICATION_FOREGROUND) -// stopForeground(STOP_FOREGROUND_REMOVE) Log.v("MUTE_TEST", "ON_DESTROY_FINISH") super.onDestroy() } @@ -387,15 +410,29 @@ class ForegroundService: Service() { protectionPendingIntent ).build() - val historyIntent = Intent(this, HistoryActivity::class.java) - historyIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK - - val pendingHistoryIntent = PendingIntent.getActivity(context, 0, historyIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) - - val actionHistory: NotificationCompat.Action = NotificationCompat.Action.Builder( - R.drawable.ic_action_history, - resources.getString(R.string.history), - pendingHistoryIntent +// val historyIntent = Intent(this, HistoryActivity::class.java) +// historyIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK +// +// val pendingHistoryIntent = PendingIntent.getActivity(context, 0, historyIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) +// +// val actionHistory: NotificationCompat.Action = NotificationCompat.Action.Builder( +// R.drawable.ic_action_history, +// resources.getString(R.string.history), +// pendingHistoryIntent +// ).build() + + val sleepIntent = Intent(context, MuteMediaReceiver::class.java) + sleepIntent.action = BROADCAST_ACTION_SLEEPTIMER_TOGGLE + val pendingSleepIntent = PendingIntent.getBroadcast(context, 0, sleepIntent, PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) + val sleepNotification = find() + var sleepTitle = resources.getString(R.string.sleep) + if (sleepNotification != null ){ + sleepTitle = DateFormat.getTimeInstance(DateFormat.SHORT).format(Date(sleepNotification.`when`)) + } + val actionSleepTimer: NotificationCompat.Action = NotificationCompat.Action.Builder ( + R.drawable.ic_tile, + sleepTitle, + pendingSleepIntent ).build() val muteMediaIntent = Intent(context, MuteMediaReceiver::class.java) @@ -415,7 +452,8 @@ class ForegroundService: Service() { .setContentIntent(pendingMuteIntent) .setPriority(NotificationCompat.PRIORITY_LOW) .addAction(actionSettings) - .addAction(actionHistory) +// .addAction(actionHistory) + .addAction(actionSleepTimer) .addAction(actionProtection) .setGroup(ID_NOTIFICATION_GROUP_FORE) .setGroupSummary(false) diff --git a/app/src/main/java/com/maary/liveinpeace/service/HistoryTileService.kt b/app/src/main/java/com/maary/liveinpeace/service/HistoryTileService.kt new file mode 100644 index 0000000..df92bda --- /dev/null +++ b/app/src/main/java/com/maary/liveinpeace/service/HistoryTileService.kt @@ -0,0 +1,31 @@ +package com.maary.liveinpeace.service + +import android.app.PendingIntent +import android.content.Intent +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK +import android.os.Build +import android.service.quicksettings.TileService +import com.maary.liveinpeace.HistoryActivity + +class HistoryTileService: TileService() { + override fun onClick() { + super.onClick() + + val intent = Intent(this, HistoryActivity::class.java) + .addFlags(FLAG_ACTIVITY_NEW_TASK) + + val pendingIntent = PendingIntent.getActivity( + this, + 0, + intent, + PendingIntent.FLAG_UPDATE_CURRENT or + PendingIntent.FLAG_IMMUTABLE) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE){ + startActivityAndCollapse(pendingIntent) + }else { + startActivityAndCollapse(intent) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/maary/liveinpeace/service/QSTileService.kt b/app/src/main/java/com/maary/liveinpeace/service/QSTileService.kt index 7fe9171..357eeac 100644 --- a/app/src/main/java/com/maary/liveinpeace/service/QSTileService.kt +++ b/app/src/main/java/com/maary/liveinpeace/service/QSTileService.kt @@ -29,6 +29,7 @@ import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_ALERT import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_DEFAULT import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_PROTECT import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_SETTINGS +import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_SLEEPTIMER import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_WELCOME import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_GROUP_SETTINGS import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_SETTINGS @@ -92,6 +93,15 @@ class QSTileService: TileService() { ) } + if (notificationManager.getNotificationChannel(CHANNEL_ID_SLEEPTIMER) == null){ + createNotificationChannel( + NotificationManager.IMPORTANCE_MIN, + CHANNEL_ID_SLEEPTIMER, + resources.getString(R.string.sleeptimer_channel), + resources.getString(R.string.sleeptimer_channel_description) + ) + } + val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager while(ActivityCompat.checkSelfPermission( diff --git a/app/src/main/res/drawable/ic_tile.xml b/app/src/main/res/drawable/ic_tile.xml new file mode 100644 index 0000000..835032e --- /dev/null +++ b/app/src/main/res/drawable/ic_tile.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/app/src/main/res/layout/activity_history.xml b/app/src/main/res/layout/activity_history.xml index 2fa8e22..86219f4 100644 --- a/app/src/main/res/layout/activity_history.xml +++ b/app/src/main/res/layout/activity_history.xml @@ -1,105 +1,105 @@ - - + + + android:layout_height="wrap_content" + android:background="?attr/colorSurfaceContainerHighest" + android:fitsSystemWindows="true" + app:liftOnScroll="true"> - + android:layout_height="?attr/collapsingToolbarLayoutLargeSize" + app:contentScrim="?attr/colorSurfaceContainerHighest" + app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> - + - + - + - + android:background="@android:color/transparent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:selectionRequired="true" + app:singleSelection="true"> - -