Merge branch 'dev' into feat/comprehensive-pr-auto-labeling
This commit is contained in:
2 files changed
+85
-1
No files matched your search
@@ -89,11 +89,20 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
ExternalActivityLifecycleGuard.onHostPaused()
|
ExternalActivityLifecycleGuard.onHostPaused()
|
||||||
NotificationHelper.setAppForeground(this, false)
|
// Prepare the FGS while still eligible to start it. A pause alone does
|
||||||
|
// not mean background: rotation also pauses and recreates this activity.
|
||||||
NotificationHelper.start(this)
|
NotificationHelper.start(this)
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
// isChangingConfigurations is reliable here, not during onPause.
|
||||||
|
// Keep the shared socket alive across recreation, but still release an
|
||||||
|
// idle connection when the user really leaves the app or locks the phone.
|
||||||
|
if (!isChangingConfigurations) NotificationHelper.setAppForeground(this, false)
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
private fun consumeNotificationIntent(intent: Intent?) {
|
private fun consumeNotificationIntent(intent: Intent?) {
|
||||||
// Issue #832: MainActivity is exported (launcher requirement) — only
|
// Issue #832: MainActivity is exported (launcher requirement) — only
|
||||||
// honor intents stamped with our own notification action.
|
// honor intents stamped with our own notification action.
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package com.m57.hermescontrol
|
||||||
|
|
||||||
|
import com.m57.hermescontrol.notification.NotificationHelper
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkObject
|
||||||
|
import io.mockk.unmockkAll
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Test
|
||||||
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
|
class MainActivityLifecycleTest {
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
unmockkAll()
|
||||||
|
ExternalActivityLifecycleGuard.resetForTest()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `pause prepares notifications without declaring the app backgrounded`() {
|
||||||
|
mockkObject(NotificationHelper)
|
||||||
|
every { NotificationHelper.start(any()) } returns Unit
|
||||||
|
every { NotificationHelper.setAppForeground(any(), any()) } returns Unit
|
||||||
|
val activity = mockk<MainActivity>(relaxed = true)
|
||||||
|
every { activity invoke "onPause" withArguments emptyList() } answers { callOriginal() }
|
||||||
|
|
||||||
|
invokeLifecycle(activity, "onPause")
|
||||||
|
|
||||||
|
verify(exactly = 1) { NotificationHelper.start(activity) }
|
||||||
|
verify(exactly = 0) { NotificationHelper.setAppForeground(activity, false) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `configuration stop keeps the shared connection foregrounded`() {
|
||||||
|
mockkObject(NotificationHelper)
|
||||||
|
every { NotificationHelper.setAppForeground(any(), any()) } returns Unit
|
||||||
|
val activity = mockk<MainActivity>(relaxed = true)
|
||||||
|
every { activity.isChangingConfigurations } returns true
|
||||||
|
every { activity invoke "onStop" withArguments emptyList() } answers { callOriginal() }
|
||||||
|
|
||||||
|
invokeLifecycle(activity, "onStop")
|
||||||
|
|
||||||
|
verify(exactly = 0) { NotificationHelper.setAppForeground(activity, false) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `real background stop still enables idle socket cleanup`() {
|
||||||
|
mockkObject(NotificationHelper)
|
||||||
|
every { NotificationHelper.setAppForeground(any(), any()) } returns Unit
|
||||||
|
val activity = mockk<MainActivity>(relaxed = true)
|
||||||
|
every { activity.isChangingConfigurations } returns false
|
||||||
|
every { activity invoke "onStop" withArguments emptyList() } answers { callOriginal() }
|
||||||
|
|
||||||
|
invokeLifecycle(activity, "onStop")
|
||||||
|
|
||||||
|
verify(exactly = 1) { NotificationHelper.setAppForeground(activity, false) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invokeLifecycle(
|
||||||
|
activity: MainActivity,
|
||||||
|
method: String,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
MainActivity::class.java
|
||||||
|
.getDeclaredMethod(method)
|
||||||
|
.apply { isAccessible = true }
|
||||||
|
.invoke(activity)
|
||||||
|
} catch (error: InvocationTargetException) {
|
||||||
|
// Execute real app code; only the trailing Android framework stub is unavailable on the JVM.
|
||||||
|
val expected = "Method $method in android.app.Activity not mocked."
|
||||||
|
if (error.targetException.message?.startsWith(expected) != true) throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user