diff --git a/CHANGELOG.md b/CHANGELOG.md index baf2c8e4..7d0dae99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 4.1.1 +* [Android] Show app on lock screen when alarm rings. + ## 4.1.0 * Migrated to Pigeon. diff --git a/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmPlugin.kt b/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmPlugin.kt index 230df040..9eff0275 100644 --- a/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmPlugin.kt +++ b/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmPlugin.kt @@ -2,10 +2,22 @@ package com.gdelataillade.alarm.alarm import AlarmApi import AlarmTriggerApi +import android.app.Activity +import android.app.KeyguardManager +import android.content.Context +import android.os.Build +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.Observer import com.gdelataillade.alarm.api.AlarmApiImpl +import com.gdelataillade.alarm.services.AlarmRingingLiveData +import io.flutter.Log import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding + +class AlarmPlugin : FlutterPlugin, ActivityAware { + private var activity: Activity? = null -class AlarmPlugin : FlutterPlugin { companion object { @JvmStatic var alarmTriggerApi: AlarmTriggerApi? = null @@ -14,9 +26,51 @@ class AlarmPlugin : FlutterPlugin { override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { AlarmApi.setUp(binding.binaryMessenger, AlarmApiImpl(binding.applicationContext)) alarmTriggerApi = AlarmTriggerApi(binding.binaryMessenger) + } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { alarmTriggerApi = null } + + override fun onAttachedToActivity(binding: ActivityPluginBinding) { + activity = binding.activity + AlarmRingingLiveData.instance.observe( + binding.activity as LifecycleOwner, + notificationObserver + ) + } + + override fun onDetachedFromActivity() { + activity = null + AlarmRingingLiveData.instance.removeObserver(notificationObserver) + } + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + onAttachedToActivity(binding) + } + + override fun onDetachedFromActivityForConfigChanges() { + onDetachedFromActivity() + } + + private val notificationObserver = Observer { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) { + Log.w("AlarmPlugin", "Making app visible on lock screen is not supported on this version of Android.") + return@Observer + } + val activity = activity ?: return@Observer + if (it) { + Log.d("AlarmPlugin", "Making app visible on lock screen...") + activity.setShowWhenLocked(true) + activity.setTurnScreenOn(true) + val keyguardManager = + activity.applicationContext.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager + keyguardManager.requestDismissKeyguard(activity, null) + } else { + Log.d("AlarmPlugin", "Reverting making app visible on lock screen...") + activity.setShowWhenLocked(false) + activity.setTurnScreenOn(false) + } + } } diff --git a/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmService.kt b/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmService.kt index 3f0f4f34..f3778d53 100644 --- a/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmService.kt +++ b/android/src/main/kotlin/com/gdelataillade/alarm/alarm/AlarmService.kt @@ -17,6 +17,7 @@ import android.content.pm.ServiceInfo import android.os.IBinder import android.os.PowerManager import android.os.Build +import com.gdelataillade.alarm.services.AlarmRingingLiveData import com.gdelataillade.alarm.services.NotificationHandler import io.flutter.Log @@ -106,6 +107,10 @@ class AlarmService : Service() { return START_NOT_STICKY } + if (fullScreenIntent) { + AlarmRingingLiveData.instance.update(true) + } + // Proceed with handling the new alarm val assetAudioPath = intent.getStringExtra("assetAudioPath") ?: return START_NOT_STICKY val loopAudio = intent.getBooleanExtra("loopAudio", true) @@ -176,6 +181,7 @@ class AlarmService : Service() { } private fun stopAlarm(id: Int) { + AlarmRingingLiveData.instance.update(false) try { val playingIds = audioService?.getPlayingMediaPlayersIds() ?: listOf() ringingAlarmIds = playingIds @@ -208,6 +214,8 @@ class AlarmService : Service() { volumeService?.restorePreviousVolume(showSystemUI) volumeService?.abandonAudioFocus() + AlarmRingingLiveData.instance.update(false) + stopForeground(true) // Call the superclass method diff --git a/android/src/main/kotlin/com/gdelataillade/alarm/services/AlarmRingingLiveData.kt b/android/src/main/kotlin/com/gdelataillade/alarm/services/AlarmRingingLiveData.kt new file mode 100644 index 00000000..913476c1 --- /dev/null +++ b/android/src/main/kotlin/com/gdelataillade/alarm/services/AlarmRingingLiveData.kt @@ -0,0 +1,14 @@ +package com.gdelataillade.alarm.services + +import androidx.lifecycle.LiveData + +class AlarmRingingLiveData : LiveData() { + companion object { + @JvmStatic + var instance: AlarmRingingLiveData = AlarmRingingLiveData() + } + + fun update(alarmIsRinging: Boolean) { + postValue(alarmIsRinging) + } +} diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 909dc51f..25b7ff71 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,16 +1,16 @@ - - - - - - - - - - - - + + + + + + + + + + + @@ -22,20 +22,18 @@ android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" - android:showWhenLocked="true" - android:turnScreenOn="true" android:windowSoftInputMode="adjustResize"> + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> - - + +