Skip to content

Commit d901208

Browse files
authored
Merge pull request #4 from Priveetee/dev
fix: restore player surface after screen wake
2 parents 7a8ef19 + c5d875f commit d901208

5 files changed

Lines changed: 51 additions & 21 deletions

File tree

‎.github/workflows/android.yml‎

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ on:
1818
tag_name:
1919
description: Release tag
2020
required: true
21-
default: v1.1.0
21+
default: v1.1.1
2222

2323
permissions:
2424
contents: write
@@ -107,7 +107,7 @@ jobs:
107107
if [ -n "$INPUT_TAG_NAME" ]; then
108108
echo "RELEASE_TAG=$INPUT_TAG_NAME" >> "$GITHUB_ENV"
109109
else
110-
echo "RELEASE_TAG=v1.1.0" >> "$GITHUB_ENV"
110+
echo "RELEASE_TAG=v1.1.1" >> "$GITHUB_ENV"
111111
fi
112112
113113
- name: Prepare signing
@@ -154,20 +154,15 @@ jobs:
154154
tag_name: ${{ env.RELEASE_TAG }}
155155
name: ${{ env.RELEASE_TAG }}
156156
body: |
157-
TypeType for Android 1.1.0 focuses on player polish, stability and production readiness.
158-
159-
This version improves the video experience across embedded playback, fullscreen, mini player, picture-in-picture, notifications and lockscreen controls while keeping the account-backed TypeType experience stable.
160-
161-
Highlights:
162-
- Cleaner player quick actions without heavy pill backgrounds.
163-
- More complete picture-in-picture controls with rewind, play/pause, forward and audio-only actions.
164-
- Media notification and lockscreen controls for rewind, play/pause and forward.
165-
- Smoother player resize mode transitions for Original, Zoom and Stretch.
166-
- Better embedded player scrubber alignment and sizing.
167-
- Improved mini-player and fullscreen drag behavior.
168-
- SponsorBlock segments displayed directly in the player timeline.
169-
- Playlist video deduplication for library surfaces such as Favorites.
170-
- Startup route stability to avoid blank launch screens.
171-
- Signed production release APK built from main.
157+
TypeType for Android 1.1.1 is a production hotfix focused on player wake stability.
158+
159+
This version fixes the gray screen that could appear after turning the phone screen off and back on while a video was still playing. Playback now keeps the media session alive and restores the video surface when Android resumes the app.
160+
161+
Changes:
162+
- Recreate the player surface after screen wake and unlock events.
163+
- Reattach the active Media3 player view when the activity resumes.
164+
- Avoid pausing the player view lifecycle while playback continues in the background.
165+
- Show the startup loader if the app is still resolving its first route.
166+
- Build and publish a signed production APK from main.
172167
files: artifacts/*.apk
173168
fail_on_unmatched_files: true

‎app/build.gradle.kts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ android {
2424
applicationId = "dev.typetype.android"
2525
minSdk = 33
2626
targetSdk = 36
27-
versionCode = 10100
28-
versionName = "1.1.0"
27+
versionCode = 10101
28+
versionName = "1.1.1"
2929
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
3030
resValue("string", "app_name", "TypeType")
3131
}

‎app/src/main/java/dev/typetype/android/MainActivity.kt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import androidx.media3.session.MediaController
1919
import androidx.media3.session.SessionToken
2020
import com.google.common.util.concurrent.MoreExecutors
2121
import dagger.hilt.android.AndroidEntryPoint
22+
import dev.typetype.android.core.ui.components.FullScreenLoader
2223
import dev.typetype.android.core.ui.theme.TypeTypeTheme
2324
import dev.typetype.android.feature.player.components.PIP_ACTION_AUDIO_ONLY
2425
import dev.typetype.android.feature.player.components.PIP_ACTION_FORWARD
@@ -60,6 +61,8 @@ class MainActivity : ComponentActivity() {
6061
val startRoute = state.startRoute
6162
if (startRoute != null) {
6263
AppNavHost(startRoute = startRoute, mainViewModel = viewModel)
64+
} else {
65+
FullScreenLoader()
6366
}
6467
}
6568
}

‎app/src/main/java/dev/typetype/android/feature/player/components/PlayerSurfaceLifecycle.kt‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
package dev.typetype.android.feature.player.components
22

3+
import android.content.BroadcastReceiver
4+
import android.content.Context
5+
import android.content.Intent
6+
import android.content.IntentFilter
37
import androidx.compose.runtime.Composable
48
import androidx.compose.runtime.DisposableEffect
59
import androidx.compose.runtime.getValue
610
import androidx.compose.runtime.mutableIntStateOf
711
import androidx.compose.runtime.remember
812
import androidx.compose.runtime.setValue
13+
import androidx.compose.ui.platform.LocalContext
14+
import androidx.core.content.ContextCompat
915
import androidx.lifecycle.Lifecycle
1016
import androidx.lifecycle.LifecycleEventObserver
1117
import androidx.lifecycle.compose.LocalLifecycleOwner
1218

1319
@Composable
1420
internal fun rememberPlayerSurfaceKey(streamId: String): String {
21+
val context = LocalContext.current
1522
val lifecycleOwner = LocalLifecycleOwner.current
1623
var epoch by remember(streamId) { mutableIntStateOf(0) }
1724
DisposableEffect(lifecycleOwner, streamId) {
@@ -23,5 +30,23 @@ internal fun rememberPlayerSurfaceKey(streamId: String): String {
2330
lifecycleOwner.lifecycle.addObserver(observer)
2431
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
2532
}
33+
DisposableEffect(context, streamId) {
34+
val receiver = object : BroadcastReceiver() {
35+
override fun onReceive(context: Context, intent: Intent) {
36+
epoch += 1
37+
}
38+
}
39+
val filter = IntentFilter().apply {
40+
addAction(Intent.ACTION_SCREEN_ON)
41+
addAction(Intent.ACTION_USER_PRESENT)
42+
}
43+
ContextCompat.registerReceiver(
44+
context.applicationContext,
45+
receiver,
46+
filter,
47+
ContextCompat.RECEIVER_NOT_EXPORTED,
48+
)
49+
onDispose { context.applicationContext.unregisterReceiver(receiver) }
50+
}
2651
return "$streamId:$epoch"
2752
}

‎app/src/main/java/dev/typetype/android/feature/player/components/ResilientPlayerSurface.kt‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,17 @@ internal fun ResilientPlayerSurface(
108108
when (event) {
109109
Lifecycle.Event.ON_START,
110110
Lifecycle.Event.ON_RESUME,
111-
-> playerView.onResume()
111+
-> {
112+
if (playerView.player !== player) {
113+
playerView.player = player
114+
}
115+
playerView.onResume()
116+
}
112117
Lifecycle.Event.ON_PAUSE,
113118
Lifecycle.Event.ON_STOP,
114-
-> playerView.onPause()
119+
-> if (!player.isPlaying) {
120+
playerView.onPause()
121+
}
115122
else -> Unit
116123
}
117124
}

0 commit comments

Comments
 (0)