Skip to content

Commit

Permalink
Merge e76473a into 0d7d5f8
Browse files Browse the repository at this point in the history
  • Loading branch information
Steve-Mr authored May 28, 2024
2 parents 0d7d5f8 + e76473a commit 9aa3d24
Show file tree
Hide file tree
Showing 16 changed files with 379 additions and 117 deletions.
24 changes: 12 additions & 12 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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.
Expand Down Expand Up @@ -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"
Expand All @@ -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'
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@
</intent-filter>
</service>

<service android:name=".service.HistoryTileService"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:icon="@drawable/ic_action_history"
android:label="@string/history"
android:exported="true">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/>
</intent-filter>
</service>

<receiver android:name=".receiver.BootCompleteReceiver"
android:exported="false">
<intent-filter android:priority="1000">
Expand All @@ -62,6 +72,11 @@
android:exported="false">
<intent-filter>
<action android:name="com.maary.liveinpeace.MUTE_MEDIA" />
<action android:name="com.maary.liveinpeace.action.CANCEL" />
<action android:name="com.maary.liveinpeace.action.INCREMENT" />
<action android:name="com.maary.liveinpeace.action.DECREMENT" />
<action android:name="com.maary.liveinpeace.action.TOGGLE" />

</intent-filter>
</receiver>

Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/maary/liveinpeace/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand All @@ -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
// 延后时间
Expand All @@ -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"
}
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/com/maary/liveinpeace/HistoryActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
103 changes: 103 additions & 0 deletions app/src/main/java/com/maary/liveinpeace/SleepNotification.kt
Original file line number Diff line number Diff line change
@@ -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)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
18 changes: 18 additions & 0 deletions app/src/main/java/com/maary/liveinpeace/receiver/SleepReceiver.kt
Original file line number Diff line number Diff line change
@@ -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)
}
Loading

0 comments on commit 9aa3d24

Please sign in to comment.