From faf64bb815b6406f5fba9ee69e94d1361424977d Mon Sep 17 00:00:00 2001 From: Chenhe Date: Wed, 22 Sep 2021 21:38:01 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cc/chenhe/qqnotifyevo/MyApplication.kt | 19 ++--- .../chenhe/qqnotifyevo/core/AvatarManager.kt | 12 ++-- .../core/InnerNotificationProcessor.kt | 27 ++++--- .../core/NevoNotificationProcessor.kt | 72 ++++++++++++------- .../cc/chenhe/qqnotifyevo/log/LogWriter.kt | 4 +- .../qqnotifyevo/preference/PermissionFr.kt | 54 ++++++++------ .../qqnotifyevo/preference/PreferenceAty.kt | 41 ++++++----- .../qqnotifyevo/preference/UpgradingFr.kt | 6 +- .../service/AccessibilityMonitorService.kt | 11 ++- .../qqnotifyevo/service/NevoDecorator.kt | 33 +++++---- .../service/NotificationMonitorService.kt | 17 +++-- .../qqnotifyevo/service/UpgradeService.kt | 48 +++++++------ .../qqnotifyevo/utils/PreferencesUtils.kt | 14 ++-- .../cc/chenhe/qqnotifyevo/utils/SpLiveData.kt | 39 ++++++---- .../core/NotificationProcessorTest.kt | 6 +- 15 files changed, 252 insertions(+), 151 deletions(-) diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/MyApplication.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/MyApplication.kt index 7b15dd1..a3a1153 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/MyApplication.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/MyApplication.kt @@ -36,7 +36,7 @@ class MyApplication : Application() { Thread.setDefaultUncaughtExceptionHandler(CrashHandler) Timber.tag(TAG).i("\n\n") Timber.tag(TAG).i("==================================================") - Timber.tag(TAG).i("= App Create") + Timber.tag(TAG).i("= App Create ver: ${getVersion(this)}") Timber.tag(TAG).i("==================================================\n") registerNotificationChannel() @@ -76,16 +76,19 @@ class MyApplication : Application() { private fun registerNotificationChannel() { Timber.tag(TAG).d("Register system notification channels") - val group = NotificationChannelGroup(NOTIFY_QQ_GROUP_ID, getString(R.string.notify_group_base)) + val group = + NotificationChannelGroup(NOTIFY_QQ_GROUP_ID, getString(R.string.notify_group_base)) val att = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .build() - val tipChannel = NotificationChannel(NOTIFY_SELF_TIPS_CHANNEL_ID, - getString(R.string.notify_self_tips_channel_name), - NotificationManager.IMPORTANCE_DEFAULT).apply { + .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build() + val tipChannel = NotificationChannel( + NOTIFY_SELF_TIPS_CHANNEL_ID, + getString(R.string.notify_self_tips_channel_name), + NotificationManager.IMPORTANCE_DEFAULT + ).apply { setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), att) } diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/core/AvatarManager.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/core/AvatarManager.kt index 571c1a4..b46e268 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/core/AvatarManager.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/core/AvatarManager.kt @@ -20,8 +20,8 @@ import kotlin.math.min * @param period 缓存有效期(毫秒)。 */ class AvatarManager private constructor( - private val cacheDir: File, - var period: Long + private val cacheDir: File, + var period: Long ) { companion object { @@ -41,8 +41,9 @@ class AvatarManager private constructor( } } - private class AvatarLruCache : LruCache(min((Runtime.getRuntime().freeMemory() / 4), - MAX_MEMORY_CACHE_SIZE).toInt()) { + private class AvatarLruCache : LruCache( + min((Runtime.getRuntime().freeMemory() / 4), MAX_MEMORY_CACHE_SIZE).toInt() + ) { override fun sizeOf(key: Int, value: Bitmap): Int { return value.allocationByteCount } @@ -81,7 +82,8 @@ class AvatarManager private constructor( lru.put(conversionId, it) } } catch (e: Exception) { - Timber.tag(TAG).e("Decode avatar file error, delete the cache. conversionId=$conversionId") + Timber.tag(TAG) + .e("Decode avatar file error, delete the cache. conversionId=$conversionId") e.printStackTrace() file.delete() lru.remove(conversionId) diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/core/InnerNotificationProcessor.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/core/InnerNotificationProcessor.kt index 3c627b5..d039ce7 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/core/InnerNotificationProcessor.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/core/InnerNotificationProcessor.kt @@ -20,8 +20,8 @@ import java.util.* * 将会遍历所有历史会话并分别发送通知。 */ class InnerNotificationProcessor( - private val commander: Commander, - context: Context + private val commander: Commander, + context: Context, ) : NotificationProcessor(context) { companion object { @@ -57,14 +57,15 @@ class InnerNotificationProcessor( } } - private fun sendNotification(context: Context, tag: Tag, id: Int, - notification: Notification) { + private fun sendNotification(context: Context, tag: Tag, id: Int, notification: Notification) { NotificationManagerCompat.from(context).notify(id, notification) addNotifyId(tag, id) } - override fun renewQzoneNotification(context: Context, tag: Tag, conversation: Conversation, - sbn: StatusBarNotification, original: Notification): Notification { + override fun renewQzoneNotification( + context: Context, tag: Tag, conversation: Conversation, + sbn: StatusBarNotification, original: Notification + ): Notification { val notification = createQZoneNotification(context, tag, conversation, original).apply { contentIntent = original.contentIntent @@ -76,14 +77,20 @@ class InnerNotificationProcessor( return notification } - override fun renewConversionNotification(context: Context, tag: Tag, channel: NotifyChannel, - conversation: Conversation, sbn: StatusBarNotification, - original: Notification): Notification { + override fun renewConversionNotification( + context: Context, + tag: Tag, + channel: NotifyChannel, + conversation: Conversation, + sbn: StatusBarNotification, + original: Notification + ): Notification { val history = getHistoryMessage(tag) var notification: Notification? = null for (c in history) { if (c.name != conversation.name || c.isGroup && channel != NotifyChannel.GROUP || - !c.isGroup && channel == NotifyChannel.GROUP) { + !c.isGroup && channel == NotifyChannel.GROUP + ) { // 确保只刷新新增的通知 continue } diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/core/NevoNotificationProcessor.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/core/NevoNotificationProcessor.kt index 1b76b3f..ce104b3 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/core/NevoNotificationProcessor.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/core/NevoNotificationProcessor.kt @@ -22,14 +22,24 @@ class NevoNotificationProcessor(context: Context) : NotificationProcessor(contex private const val REQ_MULTI_MSG_DONT_SHOW = 2 } - override fun renewQzoneNotification(context: Context, tag: Tag, conversation: Conversation, - sbn: StatusBarNotification, original: Notification): Notification { + override fun renewQzoneNotification( + context: Context, + tag: Tag, + conversation: Conversation, + sbn: StatusBarNotification, + original: Notification + ): Notification { return createQZoneNotification(context, tag, conversation, original) } - override fun renewConversionNotification(context: Context, tag: Tag, channel: NotifyChannel, - conversation: Conversation, sbn: StatusBarNotification, - original: Notification): Notification { + override fun renewConversionNotification( + context: Context, + tag: Tag, + channel: NotifyChannel, + conversation: Conversation, + sbn: StatusBarNotification, + original: Notification + ): Notification { return createConversationNotification(context, tag, channel, conversation, original) } @@ -40,30 +50,42 @@ class NevoNotificationProcessor(context: Context) : NotificationProcessor(contex return } if (nevoMultiMsgTip(ctx)) { - val dontShow = PendingIntent.getBroadcast(ctx, REQ_MULTI_MSG_DONT_SHOW, - Intent(ctx, StaticReceiver::class.java).also { - it.action = ACTION_MULTI_MSG_DONT_SHOW - }, PendingIntent.FLAG_UPDATE_CURRENT) + val dontShow = PendingIntent.getBroadcast( + ctx, REQ_MULTI_MSG_DONT_SHOW, + Intent(ctx, StaticReceiver::class.java).also { + it.action = ACTION_MULTI_MSG_DONT_SHOW + }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) - val learnMore = PendingIntent.getActivity(ctx, REQ_MULTI_MSG_LEARN_MORE, - Intent(ctx, PreferenceAty::class.java).also { - it.putExtra(PreferenceAty.EXTRA_NEVO_MULTI_MSG, true) - it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - }, PendingIntent.FLAG_UPDATE_CURRENT) + val learnMore = PendingIntent.getActivity( + ctx, REQ_MULTI_MSG_LEARN_MORE, + Intent(ctx, PreferenceAty::class.java).also { + it.putExtra(PreferenceAty.EXTRA_NEVO_MULTI_MSG, true) + it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) val style = NotificationCompat.BigTextStyle() - .setBigContentTitle(ctx.getString(R.string.notify_multi_msg_title)) - .bigText(ctx.getString(R.string.notify_multi_msg_content)) + .setBigContentTitle(ctx.getString(R.string.notify_multi_msg_title)) + .bigText(ctx.getString(R.string.notify_multi_msg_content)) val n = NotificationCompat.Builder(ctx, NOTIFY_SELF_TIPS_CHANNEL_ID) - .setStyle(style) - .setAutoCancel(true) - .setContentTitle(ctx.getString(R.string.notify_multi_msg_title)) - .setContentText(ctx.getString(R.string.notify_multi_msg_content)) - .setSmallIcon(R.drawable.ic_notify_warning) - .setContentIntent(learnMore) - .addAction(R.drawable.ic_notify_action_dnot_show, ctx.getString(R.string.dont_show), dontShow) - .addAction(R.drawable.ic_notify_action_learn_more, ctx.getString(R.string.learn_more), learnMore) - .build() + .setStyle(style) + .setAutoCancel(true) + .setContentTitle(ctx.getString(R.string.notify_multi_msg_title)) + .setContentText(ctx.getString(R.string.notify_multi_msg_content)) + .setSmallIcon(R.drawable.ic_notify_warning) + .setContentIntent(learnMore) + .addAction( + R.drawable.ic_notify_action_dnot_show, + ctx.getString(R.string.dont_show), + dontShow + ) + .addAction( + R.drawable.ic_notify_action_learn_more, + ctx.getString(R.string.learn_more), + learnMore + ) + .build() NotificationManagerCompat.from(ctx).notify(NOTIFY_ID_MULTI_MSG, n) } diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/log/LogWriter.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/log/LogWriter.kt index eecf08d..6353975 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/log/LogWriter.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/log/LogWriter.kt @@ -7,8 +7,8 @@ import java.util.* import kotlin.math.abs class LogWriter( - private val logDir: File, - time: Long = System.currentTimeMillis() + private val logDir: File, + time: Long = System.currentTimeMillis() ) : AutoCloseable { companion object { diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PermissionFr.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PermissionFr.kt index 0192987..dab5816 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PermissionFr.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PermissionFr.kt @@ -66,10 +66,10 @@ class PermissionFr : PreferenceFragmentCompat() { } "auto_start" -> { AlertDialog.Builder(context) - .setTitle(R.string.pref_auto_start) - .setMessage(R.string.pref_auto_start_message) - .setPositiveButton(R.string.confirm, null) - .show() + .setTitle(R.string.pref_auto_start) + .setMessage(R.string.pref_auto_start_message) + .setPositiveButton(R.string.confirm, null) + .show() return true } } @@ -77,14 +77,20 @@ class PermissionFr : PreferenceFragmentCompat() { } private fun refreshSummary() { - notification.summary = getString(if (isNotificationListenerEnabled(ctx)) - R.string.pref_enable_permit else R.string.pref_disable_permit) - - accessibility.summary = getString(if (isAccessibilitySettingsOn(ctx)) - R.string.pref_enable_permit else R.string.pref_disable_permit) - - battery.summary = getString(if (isIgnoreBatteryOptimization(ctx)) - R.string.pref_battery_optimize_disable else R.string.pref_battery_optimize_enable) + notification.summary = getString( + if (isNotificationListenerEnabled(ctx)) + R.string.pref_enable_permit else R.string.pref_disable_permit + ) + + accessibility.summary = getString( + if (isAccessibilitySettingsOn(ctx)) + R.string.pref_enable_permit else R.string.pref_disable_permit + ) + + battery.summary = getString( + if (isIgnoreBatteryOptimization(ctx)) + R.string.pref_battery_optimize_disable else R.string.pref_battery_optimize_enable + ) } private fun isNotificationListenerEnabled(context: Context): Boolean { @@ -94,10 +100,13 @@ class PermissionFr : PreferenceFragmentCompat() { private fun isAccessibilitySettingsOn(context: Context): Boolean { var accessibilityEnabled = 0 - val service = context.packageName + "/" + AccessibilityMonitorService::class.java.canonicalName + val service = + context.packageName + "/" + AccessibilityMonitorService::class.java.canonicalName try { - accessibilityEnabled = Settings.Secure.getInt(context.applicationContext.contentResolver, - Settings.Secure.ACCESSIBILITY_ENABLED) + accessibilityEnabled = Settings.Secure.getInt( + context.applicationContext.contentResolver, + Settings.Secure.ACCESSIBILITY_ENABLED + ) } catch (e: Settings.SettingNotFoundException) { e.printStackTrace() } @@ -105,8 +114,10 @@ class PermissionFr : PreferenceFragmentCompat() { val mStringColonSplitter = TextUtils.SimpleStringSplitter(':') if (accessibilityEnabled == 1) { - val settingValue = Settings.Secure.getString(context.applicationContext.contentResolver, - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES) + val settingValue = Settings.Secure.getString( + context.applicationContext.contentResolver, + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES + ) if (settingValue != null) { mStringColonSplitter.setString(settingValue) while (mStringColonSplitter.hasNext()) { @@ -140,11 +151,12 @@ class PermissionFr : PreferenceFragmentCompat() { @SuppressLint("BatteryLife") private fun ignoreBatteryOptimization(activity: Activity) { val powerManager = activity.getSystemService(POWER_SERVICE) as PowerManager - val hasIgnored: Boolean - hasIgnored = powerManager.isIgnoringBatteryOptimizations(activity.packageName) + val hasIgnored: Boolean = powerManager.isIgnoringBatteryOptimizations(activity.packageName) if (!hasIgnored) { - Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, - Uri.parse("package:" + activity.packageName)).let { + Intent( + Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, + Uri.parse("package:" + activity.packageName) + ).let { activity.startActivity(it) } } diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PreferenceAty.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PreferenceAty.kt index 963b52a..3013182 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PreferenceAty.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/preference/PreferenceAty.kt @@ -37,19 +37,22 @@ class PreferenceAty : AppCompatActivity() { initPreferenceFragment() } else { supportFragmentManager.beginTransaction() - .replace(R.id.frameLayout, UpgradingFr()) - .commit() + .replace(R.id.frameLayout, UpgradingFr()) + .commit() upgradeReceiver = object : BroadcastReceiver() { override fun onReceive(ctx: Context, i: Intent?) { if (i?.action == ACTION_APPLICATION_UPGRADE_COMPLETE) { - LocalBroadcastManager.getInstance(this@PreferenceAty).unregisterReceiver(this) + LocalBroadcastManager.getInstance(this@PreferenceAty) + .unregisterReceiver(this) upgradeReceiver = null initPreferenceFragment() } } } - LocalBroadcastManager.getInstance(this).registerReceiver(upgradeReceiver!!, - IntentFilter(ACTION_APPLICATION_UPGRADE_COMPLETE)) + LocalBroadcastManager.getInstance(this).registerReceiver( + upgradeReceiver!!, + IntentFilter(ACTION_APPLICATION_UPGRADE_COMPLETE) + ) if (!UpgradeService.isRunningOrPrepared()) { // 避免极端情况下在注册监听器之前更新完成 initPreferenceFragment() @@ -72,8 +75,8 @@ class PreferenceAty : AppCompatActivity() { } mainPreferenceFr = MainPreferenceFr().also { fr -> supportFragmentManager.beginTransaction() - .replace(R.id.frameLayout, fr) - .commit() + .replace(R.id.frameLayout, fr) + .commit() } } @@ -87,18 +90,18 @@ class PreferenceAty : AppCompatActivity() { if (intent?.extras?.getBoolean(EXTRA_NEVO_MULTI_MSG, false) == true) { NotificationManagerCompat.from(this).cancel(NOTIFY_ID_MULTI_MSG) AlertDialog.Builder(this) - .setTitle(R.string.tip) - .setMessage(R.string.multi_msg_dialog) - .setNeutralButton(R.string.multi_msg_dialog_neutral, null) - .setPositiveButton(R.string.multi_msg_dialog_positive) { _, _ -> - mainPreferenceFr?.setMode(MODE_LEGACY) - } - .setNegativeButton(R.string.dont_show) { _, _ -> - sendBroadcast(Intent(this, StaticReceiver::class.java).also { - it.action = ACTION_MULTI_MSG_DONT_SHOW - }) - } - .show() + .setTitle(R.string.tip) + .setMessage(R.string.multi_msg_dialog) + .setNeutralButton(R.string.multi_msg_dialog_neutral, null) + .setPositiveButton(R.string.multi_msg_dialog_positive) { _, _ -> + mainPreferenceFr?.setMode(MODE_LEGACY) + } + .setNegativeButton(R.string.dont_show) { _, _ -> + sendBroadcast(Intent(this, StaticReceiver::class.java).also { + it.action = ACTION_MULTI_MSG_DONT_SHOW + }) + } + .show() } } diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/preference/UpgradingFr.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/preference/UpgradingFr.kt index d4dadda..1e17470 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/preference/UpgradingFr.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/preference/UpgradingFr.kt @@ -9,7 +9,11 @@ import cc.chenhe.qqnotifyevo.R class UpgradingFr : Fragment() { - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fr_upgrading, container, false) } } \ No newline at end of file diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/service/AccessibilityMonitorService.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/service/AccessibilityMonitorService.kt index ce17d91..094b987 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/service/AccessibilityMonitorService.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/service/AccessibilityMonitorService.kt @@ -29,10 +29,15 @@ class AccessibilityMonitorService : AccessibilityService() { val tag = NotificationProcessor.getTagFromPackageName(event.packageName.toString()) val className = event.className.toString() if ("com.tencent.mobileqq.activity.SplashActivity" == event.className || - "com.dataline.activities.LiteActivity" == event.className) { - startService(Intent(this, NotificationMonitorService::class.java).putExtra("tag", tag.name)) + "com.dataline.activities.LiteActivity" == event.className + ) { + Intent(this, NotificationMonitorService::class.java) + .putExtra("tag", tag.name) + .also { startService(it) } } else if (className.startsWith("cooperation.qzone.")) { - startService(Intent(this, NotificationMonitorService::class.java).putExtra("tag", tag.name)) + Intent(this, NotificationMonitorService::class.java) + .putExtra("tag", tag.name) + .also { startService(it) } } } diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/service/NevoDecorator.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/service/NevoDecorator.kt index d67a98e..fdecaae 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/service/NevoDecorator.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/service/NevoDecorator.kt @@ -120,18 +120,27 @@ class NevoDecorator : NevoDecoratorService(), LifecycleOwner { } private fun createChannels(packageName: String?) { - if (!notificationChannelCreated.contains(packageName)) { - Timber.tag(TAG).d("Register nevo notification channel for ${packageName ?: "All"}") - if (packageName != null) { - notificationChannelCreated.add(packageName) - createNotificationChannels(packageName, Process.myUserHandle(), getNotificationChannels(this, true)) - } else { - packageNameList.forEach { pkg -> - try { - createNotificationChannels(pkg, Process.myUserHandle(), getNotificationChannels(this, true)) - } catch (e: SecurityException) { - Timber.tag(TAG).w(e, "Register nevo notification channel error.") - } + if (notificationChannelCreated.contains(packageName)) { + return + } + Timber.tag(TAG).d("Register nevo notification channel for ${packageName ?: "All"}") + if (packageName != null) { + notificationChannelCreated.add(packageName) + createNotificationChannels( + packageName, + Process.myUserHandle(), + getNotificationChannels(this, true) + ) + } else { + packageNameList.forEach { pkg -> + try { + createNotificationChannels( + pkg, + Process.myUserHandle(), + getNotificationChannels(this, true) + ) + } catch (e: SecurityException) { + Timber.tag(TAG).w(e, "Register nevo notification channel error.") } } } diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/service/NotificationMonitorService.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/service/NotificationMonitorService.kt index 035b0fc..38151ce 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/service/NotificationMonitorService.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/service/NotificationMonitorService.kt @@ -1,5 +1,6 @@ package cc.chenhe.qqnotifyevo.service +import android.annotation.SuppressLint import android.app.Service import android.content.Context import android.content.Intent @@ -16,12 +17,14 @@ import cc.chenhe.qqnotifyevo.utils.fetchAvatarCachePeriod import cc.chenhe.qqnotifyevo.utils.getMode import timber.log.Timber -class NotificationMonitorService : NotificationListenerService(), InnerNotificationProcessor.Commander, - LifecycleOwner { +class NotificationMonitorService : NotificationListenerService(), + InnerNotificationProcessor.Commander, + LifecycleOwner { companion object { private const val TAG = "NotifyMonitor" + @SuppressLint("StaticFieldLeak") private var instance: NotificationMonitorService? = null fun isRunning(): Boolean { @@ -69,7 +72,9 @@ class NotificationMonitorService : NotificationListenerService(), InnerNotificat if (getMode(this) != MODE_LEGACY) return Service.START_STICKY if (intent?.hasExtra("tag") == true) { - processor.clearHistory(ctx, Tag.valueOf(intent.getStringExtra("tag") ?: Tag.UNKNOWN.name)) + (intent.getStringExtra("tag") ?: Tag.UNKNOWN.name) + .let { Tag.valueOf(it) } + .also { processor.clearHistory(it) } } return Service.START_STICKY } @@ -93,7 +98,11 @@ class NotificationMonitorService : NotificationListenerService(), InnerNotificat processor.resolveNotification(ctx, sbn.packageName, sbn) } - override fun onNotificationRemoved(sbn: StatusBarNotification?, rankingMap: RankingMap?, reason: Int) { + override fun onNotificationRemoved( + sbn: StatusBarNotification?, + rankingMap: RankingMap?, + reason: Int + ) { if (sbn == null || getMode(this) != MODE_LEGACY) return processor.onNotificationRemoved(sbn, reason) super.onNotificationRemoved(sbn, rankingMap, reason) diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/service/UpgradeService.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/service/UpgradeService.kt index 1bc248e..c795bc5 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/service/UpgradeService.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/service/UpgradeService.kt @@ -1,5 +1,6 @@ package cc.chenhe.qqnotifyevo.service +import android.annotation.SuppressLint import android.app.NotificationChannel import android.app.NotificationManager import android.app.Service @@ -35,6 +36,7 @@ class UpgradeService : Service() { private const val VERSION_2_0_2 = 20023 + @SuppressLint("StaticFieldLeak") private var instance: UpgradeService? = null private var preparedToRunning = false @@ -62,7 +64,8 @@ class UpgradeService : Service() { return false } else if (old > new) { // should never happen - Timber.tag(TAG).e("Current version is lower than old version! current=$new, old=$old") + Timber.tag(TAG) + .e("Current version is lower than old version! current=$new, old=$old") return false } @@ -76,7 +79,8 @@ class UpgradeService : Service() { context.startService(i) true } else { - Timber.tag(TAG).i("No need to perform data migration, update version code directly $old → $new.") + Timber.tag(TAG) + .i("No need to perform data migration, update version code directly $old → $new.") UpgradeUtils.setOldVersion(context, new) false } @@ -106,9 +110,11 @@ class UpgradeService : Service() { } private fun createNotificationChannel() { - val channel = NotificationChannel(NOTIFY_SELF_FOREGROUND_SERVICE_CHANNEL_ID, - getString(R.string.notify_self_foreground_service_channel_name), - NotificationManager.IMPORTANCE_LOW).apply { + val channel = NotificationChannel( + NOTIFY_SELF_FOREGROUND_SERVICE_CHANNEL_ID, + getString(R.string.notify_self_foreground_service_channel_name), + NotificationManager.IMPORTANCE_LOW + ).apply { description = getString(R.string.notify_self_foreground_service_channel_name_des) } NotificationManagerCompat.from(this).createNotificationChannel(channel) @@ -120,13 +126,13 @@ class UpgradeService : Service() { preparedToRunning = false val notify = NotificationCompat.Builder(this, NOTIFY_SELF_FOREGROUND_SERVICE_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_notify_upgrade) - .setContentTitle(getString(R.string.notify_upgrade)) - .setContentText(getString(R.string.notify_upgrade_text)) - .setPriority(NotificationCompat.PRIORITY_LOW) - .setOngoing(true) - .setOnlyAlertOnce(true) - .build() + .setSmallIcon(R.drawable.ic_notify_upgrade) + .setContentTitle(getString(R.string.notify_upgrade)) + .setContentText(getString(R.string.notify_upgrade_text)) + .setPriority(NotificationCompat.PRIORITY_LOW) + .setOngoing(true) + .setOnlyAlertOnce(true) + .build() startForeground(NOTIFY_ID_UPGRADE, notify) GlobalScope.launch { @@ -155,20 +161,22 @@ class UpgradeService : Service() { } else { Timber.tag(TAG).e("Upgrade error!") } - LocalBroadcastManager.getInstance(this).sendBroadcast(Intent(ACTION_APPLICATION_UPGRADE_COMPLETE)) + LocalBroadcastManager.getInstance(this) + .sendBroadcast(Intent(ACTION_APPLICATION_UPGRADE_COMPLETE)) stopForeground(true) stopSelf() } - private suspend fun startUpgrade(oldVersion: Long, currentVersion: Long) = withContext(Dispatchers.Main) { - Timber.tag(TAG).d("Start upgrade process. $oldVersion → $currentVersion") + private suspend fun startUpgrade(oldVersion: Long, currentVersion: Long) = + withContext(Dispatchers.Main) { + Timber.tag(TAG).d("Start upgrade process. $oldVersion → $currentVersion") - if (oldVersion in 1..VERSION_2_0_2) { - migrate_1_to_2_0_2() - } + if (oldVersion in 1..VERSION_2_0_2) { + migrate_1_to_2_0_2() + } - complete(true, currentVersion) - } + complete(true, currentVersion) + } private suspend fun migrate_1_to_2_0_2() = withContext(Dispatchers.Main) { if (UserManagerCompat.isUserUnlocked(ctx)) { diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/utils/PreferencesUtils.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/utils/PreferencesUtils.kt index b36ee34..cbb1048 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/utils/PreferencesUtils.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/utils/PreferencesUtils.kt @@ -38,7 +38,7 @@ const val ICON_TIM = 2 annotation class Icon private fun sp(context: Context): SharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context.createDeviceProtectedStorageContext()) + .getDefaultSharedPreferences(context.createDeviceProtectedStorageContext()) // --------------------------------------------------------- // Tips @@ -52,7 +52,8 @@ fun nevoMultiMsgTip(context: Context, shouldShow: Boolean) { } } -fun nevoMultiMsgTip(context: Context): Boolean = sp(context).getBoolean(PREF_NEVO_MULTI_MSG_TIP, true) +fun nevoMultiMsgTip(context: Context): Boolean = + sp(context).getBoolean(PREF_NEVO_MULTI_MSG_TIP, true) // --------------------------------------------------------- @@ -87,14 +88,16 @@ fun getIconMode(context: Context): Int { } } -fun showSpecialPrefix(context: Context): Boolean = sp(context).getBoolean("show_special_prefix", false) +fun showSpecialPrefix(context: Context): Boolean = + sp(context).getBoolean("show_special_prefix", false) /** * 特别关注的群消息通知渠道。 * * @return `true` 为特别关心渠道,`false` 为群消息渠道。 */ -fun specialGroupMsgChannel(context: Context): Boolean = sp(context).getString("special_group_channel", "group") == "special" +fun specialGroupMsgChannel(context: Context): Boolean = + sp(context).getString("special_group_channel", "group") == "special" fun wrapNickname(context: Context): Boolean = sp(context).getBoolean("wrap_nickname", false) @@ -126,7 +129,8 @@ fun getShowInRecent(context: Context): Boolean { return sp(context).getBoolean("show_in_recent", true) } -fun fetchLog(context: Context): SpBooleanLiveData = SpBooleanLiveData(sp(context), "log", false, init = true) +fun fetchLog(context: Context): SpBooleanLiveData = + SpBooleanLiveData(sp(context), "log", false, init = true) fun getVersion(context: Context): String { var versionName = "" diff --git a/app/src/main/java/cc/chenhe/qqnotifyevo/utils/SpLiveData.kt b/app/src/main/java/cc/chenhe/qqnotifyevo/utils/SpLiveData.kt index 5d3f8f2..5de60a2 100644 --- a/app/src/main/java/cc/chenhe/qqnotifyevo/utils/SpLiveData.kt +++ b/app/src/main/java/cc/chenhe/qqnotifyevo/utils/SpLiveData.kt @@ -7,16 +7,17 @@ import androidx.lifecycle.LiveData * An common wrapper that trans [SharedPreferences] to [LiveData]. */ sealed class SpLiveData( - private val sp: SharedPreferences, - private val key: String, - private val default: T + private val sp: SharedPreferences, + private val key: String, + private val default: T ) : LiveData() { - private val preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key -> - if (key == this.key) { - setNewValue(getValueFromSp(sp, key, default)) + private val preferenceChangeListener = + SharedPreferences.OnSharedPreferenceChangeListener { _, key -> + if (key == this.key) { + setNewValue(getValueFromSp(sp, key, default)) + } } - } override fun onActive() { super.onActive() @@ -38,8 +39,8 @@ sealed class SpLiveData( abstract fun getValueFromSp(sp: SharedPreferences, key: String, default: T): T } -class SpIntLiveData(sp: SharedPreferences, key: String, default: Int, init: Boolean = false) - : SpLiveData(sp, key, default) { +class SpIntLiveData(sp: SharedPreferences, key: String, default: Int, init: Boolean = false) : + SpLiveData(sp, key, default) { init { if (init) { @@ -52,8 +53,8 @@ class SpIntLiveData(sp: SharedPreferences, key: String, default: Int, init: Bool } } -class SpFloatLiveData(sp: SharedPreferences, key: String, default: Float, init: Boolean = false) - : SpLiveData(sp, key, default) { +class SpFloatLiveData(sp: SharedPreferences, key: String, default: Float, init: Boolean = false) : + SpLiveData(sp, key, default) { init { if (init) { @@ -66,8 +67,12 @@ class SpFloatLiveData(sp: SharedPreferences, key: String, default: Float, init: } } -class SpBooleanLiveData(sp: SharedPreferences, key: String, default: Boolean, init: Boolean = false) - : SpLiveData(sp, key, default) { +class SpBooleanLiveData( + sp: SharedPreferences, + key: String, + default: Boolean, + init: Boolean = false +) : SpLiveData(sp, key, default) { init { if (init) { @@ -80,8 +85,12 @@ class SpBooleanLiveData(sp: SharedPreferences, key: String, default: Boolean, in } } -class SpStringLiveData(sp: SharedPreferences, key: String, default: String?, init: Boolean = false) - : SpLiveData(sp, key, default) { +class SpStringLiveData( + sp: SharedPreferences, + key: String, + default: String?, + init: Boolean = false +) : SpLiveData(sp, key, default) { init { if (init) { diff --git a/app/src/test/java/cc/chenhe/qqnotifyevo/core/NotificationProcessorTest.kt b/app/src/test/java/cc/chenhe/qqnotifyevo/core/NotificationProcessorTest.kt index a406833..36b9481 100644 --- a/app/src/test/java/cc/chenhe/qqnotifyevo/core/NotificationProcessorTest.kt +++ b/app/src/test/java/cc/chenhe/qqnotifyevo/core/NotificationProcessorTest.kt @@ -18,7 +18,11 @@ class NotificationProcessorTest { return "$nickName: $message" } - private fun generateFriendTitle(nickName: String, messageNum: Int, special: Boolean = false): String { + private fun generateFriendTitle( + nickName: String, + messageNum: Int, + special: Boolean = false + ): String { return (if (special) "[特别关心]" else "") + nickName + if (messageNum > 1) " (${messageNum}条新消息)" else "" }