diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java index 8e9f63b..0588a46 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java @@ -143,7 +143,6 @@ public class ReceiverCastService extends Service { private void restartListening(String pin) { stopSessionOnly(); - closePlaybackUi(); resetStreamState(); phase = Phase.LISTENING; acquireWakeLock(); @@ -233,15 +232,16 @@ public class ReceiverCastService extends Service { }); session.start(); updateStatus(getString(R.string.receiver_ready, pin, settings.getTransport().toUpperCase())); + openPlaybackAwaiting(R.string.playback_listening); Log.i(TAG, "Listening PIN=" + pin + " audio=" + allowIncomingAudio); } private void onSenderConnected(String senderName) { phase = Phase.CONNECTED; audioAccepted = null; - playbackLaunched = false; updateStatus(getString(R.string.casting_from, senderName)); broadcastAuthenticated(senderName); + openPlaybackAwaiting(R.string.playback_awaiting_stream); Log.i(TAG, "Sender connected: " + senderName); } @@ -250,15 +250,16 @@ public class ReceiverCastService extends Service { audioAccepted = null; hasPendingConfig = false; awaitingKeyframe = true; + resetDecoderState(); detachSurfaceOnly(); broadcastDisconnected(); + openPlaybackAwaiting(R.string.playback_stream_lost); updateStatus(getString(R.string.waiting_sender)); Log.i(TAG, "Sender disconnected"); } private void resetStreamState() { hasPendingConfig = false; - playbackLaunched = false; awaitingKeyframe = true; pendingWidth = 0; pendingHeight = 0; @@ -328,26 +329,28 @@ public class ReceiverCastService extends Service { hasPendingConfig = true; decoderActive = false; mainHandler.postDelayed(() -> awaitingKeyframe = false, 2000); - if (!playbackLaunched) { - playbackLaunched = true; - launchPlaybackActivity(pendingWidth, pendingHeight); - } else { - notifyPlaybackDimensions(pendingWidth, pendingHeight); - } + notifyPlaybackDimensions(pendingWidth, pendingHeight); tryConfigureDecoder(); reconfiguring = false; Log.i(TAG, "Stream config " + pendingWidth + "x" + pendingHeight); } - private void launchPlaybackActivity(int width, int height) { + /** Opens or refreshes fullscreen UI with robot overlay (listening / waiting for stream). */ + private void openPlaybackAwaiting(int messageResId) { + playbackLaunched = true; + Intent intent = new Intent(this, ReceiverPlaybackActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(ReceiverPlaybackActivity.EXTRA_SHOW_AWAITING, true); + intent.putExtra(ReceiverPlaybackActivity.EXTRA_AWAITING_MESSAGE, messageResId); + startActivity(intent); + } + + private void notifyPlaybackDimensions(int width, int height) { Intent intent = new Intent(this, ReceiverPlaybackActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra(ReceiverPlaybackActivity.EXTRA_WIDTH, width); intent.putExtra(ReceiverPlaybackActivity.EXTRA_HEIGHT, height); startActivity(intent); - } - - private void notifyPlaybackDimensions(int width, int height) { broadcastStreamStarted(width, height); } @@ -510,6 +513,7 @@ public class ReceiverCastService extends Service { private void releaseAll() { phase = Phase.IDLE; resetStreamState(); + playbackLaunched = false; audioAccepted = null; stopSessionOnly(); closePlaybackUi(); diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java index 8a1fba2..d78b5a9 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java @@ -23,11 +23,16 @@ import com.foxx.androidcast.ICastStatusCallback; import com.foxx.androidcast.R; import com.foxx.androidcast.ui.AspectRatioFrameLayout; -/** Fullscreen video playback — robot overlay while waiting or after stream loss. */ +/** + * Fullscreen display: dancing-robot overlay while listening / waiting; + * video surface shown only after the first decoded frame. + */ public class ReceiverPlaybackActivity extends AppCompatActivity implements SurfaceHolder.Callback { public static final String EXTRA_WIDTH = "video_width"; public static final String EXTRA_HEIGHT = "video_height"; public static final String EXTRA_FINISH = "finish_playback"; + public static final String EXTRA_SHOW_AWAITING = "show_awaiting"; + public static final String EXTRA_AWAITING_MESSAGE = "awaiting_message"; private AspectRatioFrameLayout aspectContainer; private SurfaceView surfaceView; @@ -46,13 +51,7 @@ public class ReceiverPlaybackActivity extends AppCompatActivity implements Surfa private final ICastStatusCallback.Stub statusCallback = new ICastStatusCallback.Stub() { @Override - public void onStatus(String status) { - runOnUiThread(() -> { - if (status != null && status.toLowerCase().contains("waiting")) { - showAwaitingOverlay(R.string.playback_awaiting_stream); - } - }); - } + public void onStatus(String status) {} @Override public void onAuthenticated(String senderName) { @@ -85,10 +84,6 @@ public class ReceiverPlaybackActivity extends AppCompatActivity implements Surfa bound = true; try { receiverService.registerCallback(statusCallback); - String status = receiverService.getStatus(); - if (status != null && status.toLowerCase().contains("waiting")) { - showAwaitingOverlay(R.string.playback_awaiting_stream); - } } catch (RemoteException ignored) { } attachSurfaceIfReady(); @@ -119,9 +114,14 @@ public class ReceiverPlaybackActivity extends AppCompatActivity implements Surfa awaitingMessage = findViewById(R.id.text_awaiting_message); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); + surfaceView.setZOrderMediaOverlay(false); robotDance = AnimationUtils.loadAnimation(this, R.anim.robot_dance); applyAspectRatio(); - showAwaitingOverlay(R.string.playback_awaiting_stream); + + if (getIntent().getBooleanExtra(EXTRA_SHOW_AWAITING, true)) { + int msg = getIntent().getIntExtra(EXTRA_AWAITING_MESSAGE, R.string.playback_listening); + showAwaitingOverlay(msg); + } } @Override @@ -133,8 +133,9 @@ public class ReceiverPlaybackActivity extends AppCompatActivity implements Surfa } readSizeFromIntent(intent); updateVideoSize(videoWidth, videoHeight); - if (!streamRendering) { - showAwaitingOverlay(R.string.playback_awaiting_stream); + if (intent.getBooleanExtra(EXTRA_SHOW_AWAITING, false)) { + int msg = intent.getIntExtra(EXTRA_AWAITING_MESSAGE, R.string.playback_listening); + showAwaitingOverlay(msg); } } @@ -198,7 +199,11 @@ public class ReceiverPlaybackActivity extends AppCompatActivity implements Surfa if (awaitingOverlay == null) { return; } + if (surfaceView != null) { + surfaceView.setVisibility(View.INVISIBLE); + } awaitingOverlay.setVisibility(View.VISIBLE); + awaitingOverlay.bringToFront(); if (awaitingMessage != null) { awaitingMessage.setText(messageResId); } @@ -206,10 +211,12 @@ public class ReceiverPlaybackActivity extends AppCompatActivity implements Surfa } private void hideAwaitingOverlay() { - if (awaitingOverlay == null) { - return; + if (awaitingOverlay != null) { + awaitingOverlay.setVisibility(View.GONE); + } + if (surfaceView != null) { + surfaceView.setVisibility(View.VISIBLE); } - awaitingOverlay.setVisibility(View.GONE); stopRobotAnimation(); } diff --git a/app/src/main/res/layout/overlay_stream_awaiting.xml b/app/src/main/res/layout/overlay_stream_awaiting.xml index a441e81..ce7b1a7 100644 --- a/app/src/main/res/layout/overlay_stream_awaiting.xml +++ b/app/src/main/res/layout/overlay_stream_awaiting.xml @@ -5,6 +5,7 @@ android:layout_height="match_parent" android:background="#CC000000" android:clickable="true" + android:elevation="16dp" android:focusable="true"> Play incoming cast audio on this device Start listening (keeps running in background) Connected — waiting for video… + Listening for cast — awaiting sender… Awaiting for stream to come… Stream lost — awaiting for stream to come… Starting receiver service…