diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 401824f..b0139c7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -23,8 +23,8 @@ android { applicationId = "com.radiola" minSdk = 26 targetSdk = 34 - versionCode = 7 - versionName = "1.6" + versionCode = 8 + versionName = "1.7" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/com/radiola/MainActivity.kt b/app/src/main/java/com/radiola/MainActivity.kt index 28fc9dc..e9d5db1 100644 --- a/app/src/main/java/com/radiola/MainActivity.kt +++ b/app/src/main/java/com/radiola/MainActivity.kt @@ -370,18 +370,64 @@ class MainActivity : ComponentActivity() { private fun maybeRequestBatteryExemption() { val pm = getSystemService(Context.POWER_SERVICE) as android.os.PowerManager - if (pm.isIgnoringBatteryOptimizations(packageName)) return - // Спрашиваем один раз на установку, чтобы не надоедать. val prefs = getSharedPreferences("radiola_prefs", MODE_PRIVATE) - if (prefs.getBoolean("battery_opt_asked", false)) return - prefs.edit().putBoolean("battery_opt_asked", true).apply() - runCatching { - startActivity( - Intent( - android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, - android.net.Uri.parse("package:$packageName") + // Спрашиваем один раз на установку, чтобы не надоедать. + if (!pm.isIgnoringBatteryOptimizations(packageName) && + !prefs.getBoolean("battery_opt_asked", false) + ) { + prefs.edit().putBoolean("battery_opt_asked", true).apply() + runCatching { + startActivity( + Intent( + android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, + android.net.Uri.parse("package:$packageName") + ) ) - ) + } + } + maybeGuideColorOsBackground() + } + + /** + * ColorOS/OxygenOS (Oppo, OnePlus, Realme) агрессивно «схлопывают» приложение в + * фоне при выключённом экране — стандартного исключения из оптимизации батареи + * мало. Реально помогает галочка «Разрешить работу в фоновом режиме» в разделе + * «Использование батареи» приложения. Прямого API для неё нет, поэтому один раз + * показываем пояснение и открываем экран настроек приложения, чтобы юзер включил. + */ + private fun maybeGuideColorOsBackground() { + val m = android.os.Build.MANUFACTURER.lowercase() + val isColorOs = m.contains("oppo") || m.contains("oneplus") || m.contains("realme") + if (!isColorOs) return + val prefs = getSharedPreferences("radiola_prefs", MODE_PRIVATE) + if (prefs.getBoolean("bg_activity_guided", false)) return + prefs.edit().putBoolean("bg_activity_guided", true).apply() + runCatching { + android.app.AlertDialog.Builder(this) + .setTitle("Фоновое воспроизведение") + .setMessage( + "На вашем устройстве система может выгружать приложение при " + + "выключённом экране, и радио прерывается.\n\n" + + "Чтобы этого не происходило, откройте «Использование батареи» " + + "и включите «Разрешить работу в фоновом режиме»." + ) + .setPositiveButton("Открыть настройки") { _, _ -> openAppBatterySettings() } + .setNegativeButton("Позже", null) + .show() + } + } + + /** Экран «Использование батареи» приложения; фолбэк — страница «О приложении». */ + private fun openAppBatterySettings() { + val uri = android.net.Uri.parse("package:$packageName") + val candidates = listOf( + // На части ColorOS открывает прямо управление батареей приложения. + Intent("android.settings.APP_BATTERY_SETTINGS").apply { data = uri }, + // Универсальный фолбэк — «О приложении», оттуда «Использование батареи». + Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri) + ) + for (intent in candidates) { + if (runCatching { startActivity(intent); true }.getOrDefault(false)) return } } }