diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cc387e59e5..0da0478af8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -358,10 +358,6 @@ android:windowSoftInputMode="adjustResize|stateAlwaysHidden" android:launchMode="singleTop" android:theme="@style/AppTheme.Blur" /> - = Build.VERSION_CODES.P && !RomUtil.isEmui) { + getSystemService()?.isBackgroundRestricted == true } else { - openIgnoreBatteryOptimizationSetting(newTask) + getSystemService()?.isIgnoringBatteryOptimizations(packageName) == false } } -fun Context.requestIgnoreBatteryOptimization(newTask: Boolean = false) { - Intent().apply { - action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS - data = Uri.parse("package:$packageName") - if (newTask) { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) +@SuppressLint("BatteryLife") +fun Context.openBatteryOptimizationSetting() { + val appDetailsIntent = + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.parse("package:$packageName") } - try { - startActivity(this) - } catch (e: ActivityNotFoundException) { - Timber.w("Battery optimization activity not found") + val requestIntent = + Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply { + data = Uri.parse("package:$packageName") + } + val intents = + if (RomUtil.isOneUi) { + listOf(appDetailsIntent, requestIntent) + } else if ( + Build.MANUFACTURER.equals("google", ignoreCase = true) || + Build.MANUFACTURER.equals("samsung", ignoreCase = true) || + Build.MANUFACTURER.equals("huawei", ignoreCase = true) || + Build.MANUFACTURER.equals("honor", ignoreCase = true) + ) { + listOf(requestIntent, appDetailsIntent) + } else { + listOf(appDetailsIntent, requestIntent) } + + if (!intents.any(::tryStartActivity)) { + Timber.w("Battery optimization page activity not found") } } -fun Context.openIgnoreBatteryOptimizationSetting(newTask: Boolean = false) { - Intent().apply { - action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS - if (newTask) { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - } - try { - startActivity(this) - } catch (e: ActivityNotFoundException) { - Timber.w("Power setting activity not found") +private fun Context.tryStartActivity(intent: Intent): Boolean { + val launchIntent = + Intent(intent).apply { + if (this@tryStartActivity !is Activity) { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } } + if (launchIntent.resolveActivity(packageManager) == null) { + return false + } + return try { + startActivity(launchIntent) + true + } catch (e: ActivityNotFoundException) { + false + } catch (e: SecurityException) { + false } } diff --git a/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt b/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt index 5ca31ef1c6..146220dbdc 100644 --- a/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt +++ b/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt @@ -1,18 +1,14 @@ package one.mixin.android.job import android.annotation.SuppressLint -import android.app.ActivityManager import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.pm.ServiceInfo -import android.os.Build import android.os.IBinder -import android.os.PowerManager import androidx.core.app.NotificationCompat import androidx.core.app.ServiceCompat import androidx.core.content.ContextCompat -import androidx.core.content.getSystemService import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleService import androidx.lifecycle.lifecycleScope @@ -47,6 +43,7 @@ import one.mixin.android.db.pending.PendingDatabase import one.mixin.android.event.ExpiredEvent import one.mixin.android.extension.base64Encode import one.mixin.android.extension.currentTimeSeconds +import one.mixin.android.extension.isBatteryOptimizationRestricted import one.mixin.android.extension.networkConnected import one.mixin.android.extension.notificationManager import one.mixin.android.extension.supportsOreo @@ -58,11 +55,9 @@ import one.mixin.android.messenger.HedwigImp import one.mixin.android.receiver.ExitBroadcastReceiver import one.mixin.android.session.CurrentUserScopeManager import one.mixin.android.session.Session -import one.mixin.android.ui.common.BatteryOptimizationDialogActivity import one.mixin.android.ui.home.MainActivity import one.mixin.android.util.ChannelManager.Companion.createNodeChannel import one.mixin.android.util.GsonHelper -import one.mixin.android.util.RomUtil import one.mixin.android.util.reportException import one.mixin.android.vo.CallStateLiveData import one.mixin.android.vo.MessageStatus @@ -164,8 +159,6 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C private val gson = GsonHelper.customGson - private val powerManager by lazy { getSystemService() } - private val activityManager by lazy { getSystemService() } private var isIgnoringBatteryOptimizations = false private var disposable: Disposable? = null private val destroyScope = scope(Lifecycle.Event.ON_DESTROY) @@ -246,9 +239,6 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C if (intent.action == ACTION_TO_BACKGROUND) { stopForeground(STOP_FOREGROUND_REMOVE) - if (!isIgnoringBatteryOptimizations) { - BatteryOptimizationDialogActivity.show(this, true) - } return START_STICKY } @@ -293,11 +283,7 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C } private fun updateIgnoringBatteryOptimizations() { - isIgnoringBatteryOptimizations = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !RomUtil.isEmui) { - activityManager?.isBackgroundRestricted?.not() - } else { - powerManager?.isIgnoringBatteryOptimizations(packageName) - } ?: false + isIgnoringBatteryOptimizations = !applicationContext.isBatteryOptimizationRestricted() } @SuppressLint("NewApi") diff --git a/app/src/main/java/one/mixin/android/ui/common/BatteryOptimizationDialogActivity.kt b/app/src/main/java/one/mixin/android/ui/common/BatteryOptimizationDialogActivity.kt deleted file mode 100644 index 103388159a..0000000000 --- a/app/src/main/java/one/mixin/android/ui/common/BatteryOptimizationDialogActivity.kt +++ /dev/null @@ -1,106 +0,0 @@ -package one.mixin.android.ui.common - -import android.content.Context -import android.content.Intent -import android.content.Intent.FLAG_ACTIVITY_NEW_TASK -import android.graphics.Typeface -import android.os.Build -import android.os.Bundle -import android.text.Spannable -import android.text.SpannableStringBuilder -import android.text.style.StyleSpan -import one.mixin.android.R -import one.mixin.android.extension.alertDialogBuilder -import one.mixin.android.extension.handleIgnoreBatteryOptimization -import one.mixin.android.session.Session -import one.mixin.android.util.RomUtil -import timber.log.Timber - -class BatteryOptimizationDialogActivity : BaseActivity() { - companion object { - const val ARGS_NEW_TASK = "args_new_task" - - fun show( - context: Context, - newTask: Boolean = false, - ) { - if (!Session.hasSafe()) return - Intent(context, BatteryOptimizationDialogActivity::class.java).apply { - putExtra(ARGS_NEW_TASK, newTask) - if (newTask) { - addFlags(FLAG_ACTIVITY_NEW_TASK) - } - context.startActivity(this) - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val newTask = intent.getBooleanExtra(ARGS_NEW_TASK, false) - alertDialogBuilder() - .setMessage( - replaceTags( - getString( - if (RomUtil.isOneUi) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - R.string.setting_battery_optimize_title_one_ui_above_s - } else { - R.string.setting_battery_optimize_title_one_ui_below_s - } - } else { - R.string.setting_battery_optimize_title - }, - ), - ), - ) - .setCancelable(false) - .setNegativeButton(R.string.Cancel) { dialog, _ -> - dialog.dismiss() - finish() - } - .setPositiveButton(R.string.Go_settings) { dialog, _ -> - handleIgnoreBatteryOptimization(newTask) - dialog.dismiss() - finish() - } - .show() - } - - private fun replaceTags(str: String): SpannableStringBuilder { - try { - var start: Int - var end: Int - val stringBuilder = StringBuilder(str) - val bolds: ArrayList = ArrayList() - while (stringBuilder.indexOf("").also { start = it } != -1) { - stringBuilder.replace(start, start + 3, "") - end = stringBuilder.indexOf("") - if (end == -1) { - end = stringBuilder.indexOf("") - } - stringBuilder.replace(end, end + 4, "") - bolds.add(start) - bolds.add(end) - } - while (stringBuilder.indexOf("**").also { start = it } != -1) { - stringBuilder.replace(start, start + 2, "") - end = stringBuilder.indexOf("**") - if (end >= 0) { - stringBuilder.replace(end, end + 2, "") - bolds.add(start) - bolds.add(end) - } - } - - val spannableStringBuilder = SpannableStringBuilder(stringBuilder) - for (a in 0 until bolds.count() / 2) { - spannableStringBuilder.setSpan(StyleSpan(Typeface.BOLD), bolds[a * 2], bolds[a * 2 + 1], Spannable.SPAN_INCLUSIVE_EXCLUSIVE) - } - return spannableStringBuilder - } catch (e: Exception) { - Timber.e(e) - } - return SpannableStringBuilder(str) - } -} diff --git a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt index 61ed8fc18d..8cc28eab3d 100644 --- a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt @@ -3,7 +3,6 @@ package one.mixin.android.ui.home import android.Manifest import android.annotation.SuppressLint import android.app.Activity -import android.app.ActivityManager import android.app.Dialog import android.app.NotificationManager import android.content.Context @@ -11,7 +10,6 @@ import android.content.Intent import android.content.IntentSender import android.os.Build import android.os.Bundle -import android.os.PowerManager import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.getSystemService import androidx.fragment.app.DialogFragment @@ -50,7 +48,6 @@ import one.mixin.android.Constants import one.mixin.android.Constants.APP_VERSION import one.mixin.android.Constants.Account import one.mixin.android.Constants.Account.PREF_BACKUP -import one.mixin.android.Constants.Account.PREF_BATTERY_OPTIMIZE import one.mixin.android.Constants.Account.PREF_CHECK_STORAGE import one.mixin.android.Constants.Account.PREF_DEVICE_SDK import one.mixin.android.Constants.Account.PREF_LOGIN_OR_SIGN_UP @@ -137,7 +134,6 @@ import one.mixin.android.tip.wc.WCEvent import one.mixin.android.tip.wc.WalletConnect import one.mixin.android.tip.wc.WalletConnectV2 import one.mixin.android.ui.common.BaseFragment -import one.mixin.android.ui.common.BatteryOptimizationDialogActivity import one.mixin.android.ui.common.BlazeBaseActivity import one.mixin.android.ui.common.LoginVerifyBottomSheetDialogFragment import one.mixin.android.ui.common.NavigationController @@ -179,7 +175,6 @@ import one.mixin.android.util.BiometricUtil import one.mixin.android.util.ErrorHandler import one.mixin.android.util.ErrorHandler.Companion.SERVER import one.mixin.android.util.GsonHelper -import one.mixin.android.util.RomUtil import one.mixin.android.util.RootUtil import one.mixin.android.util.analytics.AnalyticsTracker import one.mixin.android.util.database.databaseFile @@ -503,7 +498,6 @@ class MainActivity : BlazeBaseActivity(), WalletMissingBtcAddressFragment.Callba refreshStickerAlbum() refreshExternalSchemes() cleanCache() - checkBatteryOptimization() if (!defaultSharedPreferences.getBoolean(PREF_SYNC_CIRCLE, false)) { jobManager.addJobInBackground(RefreshCircleJob()) @@ -654,28 +648,6 @@ class MainActivity : BlazeBaseActivity(), WalletMissingBtcAddressFragment.Callba return currentVersion > MINI_VERSION && CURRENT_VERSION != currentVersion } - @SuppressLint("BatteryLife") - private fun checkBatteryOptimization() { - val batteryOptimize = defaultSharedPreferences.getLong(PREF_BATTERY_OPTIMIZE, 0) - val cur = System.currentTimeMillis() - if (cur - batteryOptimize > INTERVAL_24_HOURS) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !RomUtil.isEmui) { - getSystemService()?.let { am -> - if (am.isBackgroundRestricted) { - BatteryOptimizationDialogActivity.show(this) - } - } - } else { - getSystemService()?.let { pm -> - if (!pm.isIgnoringBatteryOptimizations(packageName)) { - BatteryOptimizationDialogActivity.show(this) - } - } - } - defaultSharedPreferences.putLong(PREF_BATTERY_OPTIMIZE, cur) - } - } - private fun delayShowModifyMobile() = lifecycleScope.launch { delay(2000) diff --git a/app/src/main/java/one/mixin/android/ui/home/reminder/ReminderBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/ui/home/reminder/ReminderBottomSheetDialogFragment.kt index 0a69a2df9a..ffba334ca2 100644 --- a/app/src/main/java/one/mixin/android/ui/home/reminder/ReminderBottomSheetDialogFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/home/reminder/ReminderBottomSheetDialogFragment.kt @@ -3,17 +3,21 @@ package one.mixin.android.ui.home.reminder import android.annotation.SuppressLint import android.app.Dialog import android.content.Context +import android.os.Build import android.view.Gravity import android.view.View import android.view.ViewGroup +import androidx.annotation.StringRes import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.core.app.NotificationManagerCompat import dagger.hilt.android.AndroidEntryPoint import one.mixin.android.BuildConfig +import one.mixin.android.Constants.Account.PREF_BATTERY_OPTIMIZE import one.mixin.android.Constants.INTERVAL_24_HOURS import one.mixin.android.Constants.INTERVAL_48_HOURS import one.mixin.android.R @@ -22,7 +26,9 @@ import one.mixin.android.compose.theme.languageBasedImage import one.mixin.android.extension.booleanFromAttribute import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.getSafeAreaInsetsTop +import one.mixin.android.extension.isBatteryOptimizationRestricted import one.mixin.android.extension.isNightMode +import one.mixin.android.extension.openBatteryOptimizationSetting import one.mixin.android.extension.openNotificationSetting import one.mixin.android.extension.putLong import one.mixin.android.extension.screenHeight @@ -30,7 +36,6 @@ import one.mixin.android.extension.withArgs import one.mixin.android.session.Session import one.mixin.android.ui.common.MixinComposeBottomSheetDialogFragment import one.mixin.android.ui.home.MainActivity -import one.mixin.android.ui.setting.SettingActivity import one.mixin.android.util.SystemUIManager @AndroidEntryPoint @@ -69,6 +74,13 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( return PopupType.NotificationPermissionReminder } + val lastBatteryOptimizationReminderTime = sharedPreferences.getLong(PREF_BATTERY_OPTIMIZE, 0) + if (System.currentTimeMillis() - lastBatteryOptimizationReminderTime > INTERVAL_24_HOURS && + context.isBatteryOptimizationRestricted() + ) { + return PopupType.BatteryOptimizationReminder + } + return null } @@ -87,6 +99,19 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( } return 0 } + + @StringRes + private fun getBatteryOptimizationContentResId(): Int { + return if (one.mixin.android.util.RomUtil.isOneUi) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + R.string.setting_battery_optimize_title_one_ui_above_s + } else { + R.string.setting_battery_optimize_title_one_ui_below_s + } + } else { + R.string.setting_battery_optimize_title + } + } } private val popupType by lazy { @@ -94,6 +119,7 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( when (typeName) { PopupType.NewVersionReminder::class.java.simpleName -> PopupType.NewVersionReminder PopupType.NotificationPermissionReminder::class.java.simpleName -> PopupType.NotificationPermissionReminder + PopupType.BatteryOptimizationReminder::class.java.simpleName -> PopupType.BatteryOptimizationReminder else -> throw IllegalArgumentException("Unknown PopupType") } } @@ -138,7 +164,9 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( title = R.string.New_Update_Available, actionStr = R.string.Update_Now, action = { - Session.getAccount()?.system?.messenger?.let { it -> (requireActivity() as? MainActivity)?.showUpdate(it.releaseUrl) } + Session.getAccount()?.system?.messenger?.let { it -> + (requireActivity() as? MainActivity)?.showUpdate(it.releaseUrl) + } dismissAllowingStateLoss() }, dismiss = { @@ -153,9 +181,9 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( text = stringResource(R.string.New_Update_Available_desc), color = MixinAppTheme.colors.textAssist, modifier = Modifier.fillMaxWidth(), - textAlign = androidx.compose.ui.text.style.TextAlign.Center + textAlign = TextAlign.Center, ) - } + }, ) } @@ -163,7 +191,7 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( ReminderPage( contentImage = languageBasedImage( R.drawable.bg_reminder_notifaction, - R.drawable.bg_reminder_notifaction_cn + R.drawable.bg_reminder_notifaction_cn, ), title = R.string.Turn_On_Notifications, actionStr = R.string.Enable_Notifications, @@ -183,12 +211,42 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( text = stringResource(R.string.notification_content), color = MixinAppTheme.colors.textAssist, modifier = Modifier.fillMaxWidth(), - textAlign = androidx.compose.ui.text.style.TextAlign.Center + textAlign = TextAlign.Center, ) - } + }, ) } + is PopupType.BatteryOptimizationReminder -> { + ReminderPage( + contentImage = R.drawable.bg_reminder_battery_optimization, + title = R.string.Battery_Optimization, + actionStr = R.string.Go_settings, + action = { + requireContext().defaultSharedPreferences.putLong( + PREF_BATTERY_OPTIMIZE, + System.currentTimeMillis(), + ) + requireContext().openBatteryOptimizationSetting() + dismissAllowingStateLoss() + }, + dismiss = { + requireContext().defaultSharedPreferences.putLong( + PREF_BATTERY_OPTIMIZE, + System.currentTimeMillis(), + ) + dismissAllowingStateLoss() + }, + contentSlot = { + Text( + text = batteryOptimizationContent(), + color = MixinAppTheme.colors.textAssist, + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + ) + }, + ) + } } } } @@ -200,8 +258,16 @@ class ReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment( override fun showError(error: String) { } + private fun batteryOptimizationContent(): String { + return getString(getBatteryOptimizationContentResId()) + .replace("", "") + .replace("", "") + .replace("**", "") + } + sealed class PopupType { object NewVersionReminder : PopupType() object NotificationPermissionReminder : PopupType() + object BatteryOptimizationReminder : PopupType() } } diff --git a/app/src/main/res/drawable-xxhdpi/bg_reminder_battery_optimization.png b/app/src/main/res/drawable-xxhdpi/bg_reminder_battery_optimization.png new file mode 100644 index 0000000000..511aecc65f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_reminder_battery_optimization.png differ diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 30d58128ec..a0f089a6f8 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -834,6 +834,7 @@ Se ha establecido el PIN con éxito Aprobado: %1$s, último acceso: %2$s ID de Mixin, nombre + Optimización de batería Esto mejorará la confiabilidad de las notificaciones entrantes y las llamadas de Mixin. Esto mejorará la confiabilidad de las notificaciones entrantes y las llamadas de Mixin. Selecciona **Optimizado** o **Sin restricciones** en Configuración > Batería. Esto mejorará la confiabilidad de las notificaciones entrantes y las llamadas de Mixin. Pulsa Configuración -> Batería y activa **Permitir actividad en segundo plano**. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 45679256d8..59f858c5a1 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -783,6 +783,7 @@ PINコードの設定が完了しました。 許可: %1$s, 最終アクセス: %2$s Mixin ID, 名前 + バッテリー最適化 これにより、通知の受信や Mixinの呼び出しに対する確実性が向上します これにより、通知の受信やMixinの呼び出しに対する確実性が向上します。「設定」→「バッテリー」をタップしてください。そして**「最適化」** もしくは **「制限なし」**を選択してください。 これにより、通知の受信やMixinの呼び出しに対する確実性が向上します。「設定」→「バッテリー」をタップしてください。そして**「バックグラウンドでの活動を許可」**をオンにしてください。 diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ebe4849b53..312fdfa0d0 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -804,6 +804,7 @@ ПИН-код успешно установлен Одобрено: %1$s, последнее обращение: %2$s Mixin ID, имя + Оптимизация батареи Это повысит надежность входящих уведомлений и вызовов Mixin. Это повысит надежность входящих уведомлений и вызовов Mixin. Выберите **Оптимизированный** или **Неограниченный** в меню «Настройки» > «Аккумулятор». Это повысит надежность входящих уведомлений и вызовов Mixin. Нажмите «Настройки» -> «Аккумулятор» и включите **Разрешить фоновую активность**. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index f14a03a92c..b64b63a2f4 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -979,6 +979,7 @@ PIN 设置成功 授权时间:%1$s, 上次访问:%2$s Mixin ID, 昵称 + 电池优化 这将提高 Mixin 通知和呼叫的可靠性。 这将提高 Mixin 通知和呼叫的可靠性. 请在设置 > 电池中选择 **已优化** 或者 **不受限制**。 这将提高 Mixin 通知和呼叫的可靠性。点击设置 -> 电池,开启**允许后台活动**。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 244d6b020d..dd95feeeaa 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -790,6 +790,7 @@ PIN 設定成功 授權時間:%1$s, 上次訪問:%2$s Mixin ID, 暱稱 + 電池最佳化 這將提高 Mixin 通知和呼叫的可靠性。 這將提高 Mixin 通知和呼叫的可靠性. 請在設定 > 電池中選擇 **已最佳化** 或者 **不受限制**。 這將提高 Mixin 通知和呼叫的可靠性。點選設定 -> 電池,開啟**允許後臺活動**。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74f44a1052..55648db90c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1005,6 +1005,7 @@ Set PIN successfully Approved: %1$s, Last Accessed: %2$s Mixin ID, Name + Battery Optimization This will improve reliability for incoming notifications and Mixin calls This will improve reliability for incoming notifications and Mixin calls. Please select **Optimised** or **Unrestricted** in Settings > Battery. This will improve reliability for incoming notifications and Mixin calls. Tap Settings -> Battery and turn **Allow background activity** on.