diff --git a/app/src/main/java/com/maary/liveinpeace/Constants.kt b/app/src/main/java/com/maary/liveinpeace/Constants.kt index 48ffd8d..2c5079b 100644 --- a/app/src/main/java/com/maary/liveinpeace/Constants.kt +++ b/app/src/main/java/com/maary/liveinpeace/Constants.kt @@ -14,11 +14,13 @@ class Constants { const val PREF_ICON = "icon_type" const val PREF_NOTIFY_TEXT_SIZE = "notification_text_size" const val PREF_WATCHING_CONNECTING_TIME = "watching_connecting" + const val PREF_ENABLE_EAR_PROTECTION = "ear_protection_enabled" // 设置通知 id const val ID_NOTIFICATION_SETTINGS = 3 // 前台通知 id const val ID_NOTIFICATION_FOREGROUND = 1 const val ID_NOTIFICATION_ALERT = 2 + const val ID_NOTIFICATION_PROTECT = 4 // 设置图像式图标 Action const val ACTION_NAME_SET_IMG = "com.maary.liveinpeace.receiver.SettingsReceiver.SetIconImg" // 设置字符式图标 Action @@ -27,6 +29,8 @@ class Constants { const val ACTION_ENABLE_WATCHING = "com.maary.liveinpeace.receiver.SettingsReceiver.EnableWatching" // 禁用长时间连接提醒 Action const val ACTION_DISABLE_WATCHING = "com.maary.liveinpeace.receiver.SettingsReceiver.DisableWatching" + // toggle 设备连接调整音量 Action + const val ACTION_TOGGLE_AUTO_CONNECTION_ADJUSTMENT = "com.maary.liveinpeace.receiver.SettingsReceiver.ToggleAdjustment" // 设置 Action const val ACTION_NAME_SETTINGS = "com.maary.liveinpeace.receiver.SettingsReceiver" // 静音广播名称 @@ -40,6 +44,7 @@ class Constants { const val CHANNEL_ID_DEFAULT = "LIP_FOREGROUND" const val CHANNEL_ID_SETTINGS = "LIP_SETTINGS" const val CHANNEL_ID_ALERT = "LIP_ALERT" + const val CHANNEL_ID_PROTECT = "LIP_PROTECT" // 提醒时间 const val ALERT_TIME: Long = 2*60*60*1000 // 延后时间 @@ -48,6 +53,7 @@ class Constants { const val ID_NOTIFICATION_GROUP_FORE = "LIP_notification_group_foreground" 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 PATTERN_DATE_DATABASE = "yyyy-MM-dd" const val PATTERN_DATE_BUTTON = "MM/dd" } diff --git a/app/src/main/java/com/maary/liveinpeace/receiver/SettingsReceiver.kt b/app/src/main/java/com/maary/liveinpeace/receiver/SettingsReceiver.kt index cc6d151..8042468 100644 --- a/app/src/main/java/com/maary/liveinpeace/receiver/SettingsReceiver.kt +++ b/app/src/main/java/com/maary/liveinpeace/receiver/SettingsReceiver.kt @@ -12,11 +12,13 @@ import com.maary.liveinpeace.Constants.Companion.ACTION_ENABLE_WATCHING import com.maary.liveinpeace.Constants.Companion.ACTION_NAME_SETTINGS import com.maary.liveinpeace.Constants.Companion.ACTION_NAME_SET_IMG import com.maary.liveinpeace.Constants.Companion.ACTION_NAME_SET_NUM +import com.maary.liveinpeace.Constants.Companion.ACTION_TOGGLE_AUTO_CONNECTION_ADJUSTMENT import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_SETTINGS import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_GROUP_SETTINGS import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_SETTINGS import com.maary.liveinpeace.Constants.Companion.MODE_IMG import com.maary.liveinpeace.Constants.Companion.MODE_NUM +import com.maary.liveinpeace.Constants.Companion.PREF_ENABLE_EAR_PROTECTION import com.maary.liveinpeace.Constants.Companion.PREF_ICON import com.maary.liveinpeace.Constants.Companion.PREF_WATCHING_CONNECTING_TIME import com.maary.liveinpeace.Constants.Companion.SHARED_PREF @@ -166,6 +168,24 @@ class SettingsReceiver: BroadcastReceiver() { } } + if (ACTION_TOGGLE_AUTO_CONNECTION_ADJUSTMENT == p1?.action){ + val sharedPreferences = p0?.getSharedPreferences( + SHARED_PREF, + Context.MODE_PRIVATE + ) + if (sharedPreferences != null) { + with(sharedPreferences.edit()){ + putBoolean(PREF_ENABLE_EAR_PROTECTION, + !sharedPreferences.getBoolean(PREF_ENABLE_EAR_PROTECTION, false) + ) + apply() + val foregroundServiceIntent = Intent(p0, ForegroundService::class.java) + p0.stopService(foregroundServiceIntent) + p0.startForegroundService(foregroundServiceIntent) + } + } + } + if (ACTION_CANCEL == p1?.action){ val notificationManager: NotificationManager = p0?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 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 8f55f6d..a1eca08 100644 --- a/app/src/main/java/com/maary/liveinpeace/service/ForegroundService.kt +++ b/app/src/main/java/com/maary/liveinpeace/service/ForegroundService.kt @@ -22,16 +22,21 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.graphics.drawable.IconCompat import com.maary.liveinpeace.Constants.Companion.ACTION_NAME_SETTINGS +import com.maary.liveinpeace.Constants.Companion.ACTION_TOGGLE_AUTO_CONNECTION_ADJUSTMENT 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_FOREGROUND_INTENT_EXTRA import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_DEFAULT +import com.maary.liveinpeace.Constants.Companion.CHANNEL_ID_PROTECT import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_ALERT import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_FOREGROUND import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_GROUP_FORE +import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_GROUP_PROTECT +import com.maary.liveinpeace.Constants.Companion.ID_NOTIFICATION_PROTECT import com.maary.liveinpeace.Constants.Companion.MODE_IMG import com.maary.liveinpeace.Constants.Companion.MODE_NUM +import com.maary.liveinpeace.Constants.Companion.PREF_ENABLE_EAR_PROTECTION import com.maary.liveinpeace.Constants.Companion.PREF_ICON import com.maary.liveinpeace.Constants.Companion.PREF_NOTIFY_TEXT_SIZE import com.maary.liveinpeace.Constants.Companion.PREF_WATCHING_CONNECTING_TIME @@ -159,6 +164,7 @@ class ForegroundService: Service() { override fun onAudioDevicesAdded(addedDevices: Array?) { val connectedTime = System.currentTimeMillis() + val sharedPreferences = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE) // 在设备连接时记录设备信息和接入时间 addedDevices?.forEach { deviceInfo -> @@ -187,10 +193,26 @@ class ForegroundService: Service() { date = LocalDate.now().toString() ) notifyDeviceMapChange() + if (sharedPreferences.getBoolean(PREF_ENABLE_EAR_PROTECTION, false)){ + val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager + var boolProtected = false + while (getVolumePercentage(applicationContext)>25) { + boolProtected = true + audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0) + } + while (getVolumePercentage(applicationContext)<10) { + boolProtected = true + audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0) + } + if (boolProtected){ + with(NotificationManagerCompat.from(applicationContext)){ + notify(ID_NOTIFICATION_PROTECT, createProtectionNotification()) + } + } + } // 执行其他逻辑,比如将设备信息保存到数据库或日志中 } - val sharedPreferences = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE) if (sharedPreferences.getBoolean(PREF_WATCHING_CONNECTING_TIME, false)){ for ((productName, _) in deviceMap){ if (deviceTimerMap.containsKey(productName)) continue @@ -341,6 +363,30 @@ class ForegroundService: Service() { snoozePendingIntent ).build() + val sharedPreferences = getSharedPreferences( + SHARED_PREF, + Context.MODE_PRIVATE + ) + + var protectionActionTitle = R.string.protection + if (sharedPreferences != null){ + if (sharedPreferences.getBoolean(PREF_ENABLE_EAR_PROTECTION, false)){ + protectionActionTitle = R.string.dont_protect + } + } + + val protectionIntent = Intent(this, SettingsReceiver::class.java).apply { + action = ACTION_TOGGLE_AUTO_CONNECTION_ADJUSTMENT + } + val protectionPendingIntent: PendingIntent = + PendingIntent.getBroadcast(this, 0, protectionIntent, PendingIntent.FLAG_IMMUTABLE) + + val actionProtection : NotificationCompat.Action = NotificationCompat.Action.Builder( + R.drawable.ic_headphones_protection, + resources.getString(protectionActionTitle), + protectionPendingIntent + ).build() + val historyIntent = Intent(this, HistoryActivity::class.java) historyIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK @@ -370,11 +416,22 @@ class ForegroundService: Service() { .setPriority(NotificationCompat.PRIORITY_LOW) .addAction(actionSettings) .addAction(actionHistory) + .addAction(actionProtection) .setGroup(ID_NOTIFICATION_GROUP_FORE) .setGroupSummary(false) .build() } + fun createProtectionNotification(): Notification { + return NotificationCompat.Builder(this, CHANNEL_ID_PROTECT) + .setContentTitle(getString(R.string.ears_protected)) + .setSmallIcon(R.drawable.ic_headphones_protection) + .setPriority(NotificationCompat.PRIORITY_LOW) + .setGroup(ID_NOTIFICATION_GROUP_PROTECT) + .setTimeoutAfter(3000) + .build() + } + private val textBounds = Rect() private fun generateNotificationIcon(context: Context, iconMode: Int): IconCompat { 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 db3250f..478944c 100644 --- a/app/src/main/java/com/maary/liveinpeace/service/QSTileService.kt +++ b/app/src/main/java/com/maary/liveinpeace/service/QSTileService.kt @@ -20,6 +20,7 @@ import com.maary.liveinpeace.Constants.Companion.BROADCAST_ACTION_FOREGROUND import com.maary.liveinpeace.Constants.Companion.BROADCAST_FOREGROUND_INTENT_EXTRA 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.REQUESTING_WAIT_MILLIS import com.maary.liveinpeace.R @@ -73,6 +74,18 @@ class QSTileService: TileService() { resources.getString(R.string.alert_channel_description) ) } + if (notificationManager.getNotificationChannel(CHANNEL_ID_PROTECT) == null) { + val channel = NotificationChannel( + CHANNEL_ID_PROTECT, + resources.getString(R.string.channel_protection), + NotificationManager.IMPORTANCE_LOW).apply { + description = resources.getString(R.string.protection_channel_description) + enableVibration(false) + setSound(null, null) + } + // Register the channel with the system + notificationManager.createNotificationChannel(channel) + } applicationContext.startForegroundService(intent) tile.state = Tile.STATE_ACTIVE diff --git a/app/src/main/res/drawable/ic_headphones_protection.xml b/app/src/main/res/drawable/ic_headphones_protection.xml new file mode 100644 index 0000000..a3fda25 --- /dev/null +++ b/app/src/main/res/drawable/ic_headphones_protection.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index cc19025..ca862f1 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -38,4 +38,9 @@ 已连接 设备连接状态指示 选择日期 + 保护耳朵 + 不保护耳朵 + 保护了耳朵 + 保护耳朵 + 有新设备连接时自动将音量调节至 25 以下 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d9dd0a..28eedd9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,6 +30,11 @@ Already connected Device connection state indicator Select a Date + Protect My Ears + Stop protecting ears + Ears Protected + Protecting ears + Auto adjust volume below 25 when connecting to a new device. Shhhhhhh… Perfectly Balanced, As All Things Should Be…