diff --git a/samples/user-interface/picture-in-picture/src/main/AndroidManifest.xml b/samples/user-interface/picture-in-picture/src/main/AndroidManifest.xml index 48cff2c7..2cd9a908 100644 --- a/samples/user-interface/picture-in-picture/src/main/AndroidManifest.xml +++ b/samples/user-interface/picture-in-picture/src/main/AndroidManifest.xml @@ -23,7 +23,6 @@ android:name=".PiPSampleActivity" android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" android:exported="true" - android:supportsPictureInPicture="true" android:launchMode="singleTask" android:theme="@style/PiPAppTheme" tools:targetApi="26" /> @@ -31,7 +30,6 @@ diff --git a/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPMovieActivity.kt b/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPMovieActivity.kt index 8a569c1d..434ee297 100644 --- a/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPMovieActivity.kt +++ b/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPMovieActivity.kt @@ -16,10 +16,7 @@ package com.example.android.pip -import android.app.PictureInPictureParams -import android.app.PictureInPictureUiState import android.content.res.Configuration -import android.graphics.Rect import android.os.Build import android.os.Bundle import android.support.v4.media.MediaMetadataCompat @@ -28,14 +25,12 @@ import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.PlaybackStateCompat import android.text.util.Linkify import android.util.Log -import android.util.Rational import android.view.View import androidx.activity.ComponentActivity import androidx.annotation.RequiresApi import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat -import androidx.core.view.doOnLayout import com.example.android.pip.databinding.PipMovieActivityBinding import com.example.android.pip.widget.MovieView @@ -90,11 +85,6 @@ class PiPMovieActivity : ComponentActivity() { binding.movie.getVideoResourceId(), ) } - - override fun onMovieMinimized() { - // The MovieView wants us to minimize it. We enter Picture-in-Picture mode now. - minimize() - } } override fun onCreate(savedInstanceState: Bundle?) { @@ -107,11 +97,6 @@ class PiPMovieActivity : ComponentActivity() { } catch (e: Exception) { Log.w("PiP", "Failed to add links", e) } - binding.pip.setOnClickListener { minimize() } - - // Configure parameters for the picture-in-picture mode. We do this at the first layout of - // the MovieView because we use its layout position and size. - binding.movie.doOnLayout { updatePictureInPictureParams() } // Set up the video; it automatically starts. binding.movie.setMovieListener(movieListener) @@ -175,58 +160,6 @@ class PiPMovieActivity : ComponentActivity() { } } - override fun onPictureInPictureModeChanged( - isInPictureInPictureMode: Boolean, newConfig: Configuration, - ) { - super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) - if (isInPictureInPictureMode) { - // Hide the controls in picture-in-picture mode. - binding.movie.hideControls() - } else { - // Show the video controls if the video is not playing - if (!binding.movie.isPlaying) { - binding.movie.showControls() - } - } - } - - @RequiresApi(35) - override fun onPictureInPictureUiStateChanged(pipState: PictureInPictureUiState) { - super.onPictureInPictureUiStateChanged(pipState) - if (pipState.isTransitioningToPip) { - binding.movie.hideControls() - } - } - - - private fun updatePictureInPictureParams(): PictureInPictureParams { - // Calculate the aspect ratio of the PiP screen. - val aspectRatio = Rational(binding.movie.width, binding.movie.height) - // The movie view turns into the picture-in-picture mode. - val visibleRect = Rect() - binding.movie.getGlobalVisibleRect(visibleRect) - val params = PictureInPictureParams.Builder() - .setAspectRatio(aspectRatio) - // Specify the portion of the screen that turns into the picture-in-picture mode. - // This makes the transition animation smoother. - .setSourceRectHint(visibleRect) - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - // The screen automatically turns into the picture-in-picture mode when it is hidden - // by the "Home" button. - params.setAutoEnterEnabled(true) - } - return params.build().also { - setPictureInPictureParams(it) - } - } - - /** - * Enters Picture-in-Picture mode. - */ - private fun minimize() { - enterPictureInPictureMode(updatePictureInPictureParams()) - } /** * Adjusts immersive full-screen flags depending on the screen orientation. diff --git a/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPSampleActivity.kt b/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPSampleActivity.kt index 1d5e967a..5e8502fe 100644 --- a/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPSampleActivity.kt +++ b/samples/user-interface/picture-in-picture/src/main/java/com/example/android/pip/PiPSampleActivity.kt @@ -16,44 +16,11 @@ package com.example.android.pip -import android.app.PendingIntent -import android.app.PictureInPictureParams -import android.app.PictureInPictureUiState -import android.app.RemoteAction -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.content.res.Configuration -import android.graphics.drawable.Icon -import android.os.Build import android.os.Bundle -import android.util.Rational -import android.view.View import androidx.activity.ComponentActivity -import androidx.activity.trackPipAnimationHintView import androidx.activity.viewModels -import androidx.annotation.DrawableRes import androidx.annotation.RequiresApi -import androidx.annotation.StringRes -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle import com.example.android.pip.databinding.PipActivityBinding -import kotlinx.coroutines.launch - -/** Intent action for stopwatch controls from Picture-in-Picture mode. */ -private const val ACTION_STOPWATCH_CONTROL = "stopwatch_control" - -/** Intent extra for stopwatch controls from Picture-in-Picture mode. */ -private const val EXTRA_CONTROL_TYPE = "control_type" -private const val CONTROL_TYPE_CLEAR = 1 -private const val CONTROL_TYPE_START_OR_PAUSE = 2 - -private const val REQUEST_CLEAR = 3 -private const val REQUEST_START_OR_PAUSE = 4 /** * Demonstrates usage of Picture-in-Picture mode on phones and tablets. @@ -64,23 +31,6 @@ class PiPSampleActivity : ComponentActivity() { private val viewModel: PiPViewModel by viewModels() private lateinit var binding: PipActivityBinding - /** - * A [BroadcastReceiver] for handling action items on the picture-in-picture mode. - */ - private val broadcastReceiver = object : BroadcastReceiver() { - - // Called when an item is clicked. - override fun onReceive(context: Context?, intent: Intent?) { - if (intent == null || intent.action != ACTION_STOPWATCH_CONTROL) { - return - } - when (intent.getIntExtra(EXTRA_CONTROL_TYPE, 0)) { - CONTROL_TYPE_START_OR_PAUSE -> viewModel.startOrPause() - CONTROL_TYPE_CLEAR -> viewModel.clear() - } - } - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = PipActivityBinding.inflate(layoutInflater) @@ -89,7 +39,6 @@ class PiPSampleActivity : ComponentActivity() { binding.clear.setOnClickListener { viewModel.clear() } binding.startOrPause.setOnClickListener { viewModel.startOrPause() } binding.pip.setOnClickListener { - enterPictureInPictureMode(updatePictureInPictureParams(viewModel.started.value == true)) } // Observe data from the viewModel. viewModel.time.observe(this) { time -> binding.time.text = time } @@ -97,122 +46,6 @@ class PiPSampleActivity : ComponentActivity() { binding.startOrPause.setImageResource( if (started) R.drawable.ic_pause_24dp else R.drawable.ic_play_arrow_24dp, ) - updatePictureInPictureParams(started) - } - - // Use trackPipAnimationHint view to make a smooth enter/exit pip transition. - // See https://android.devsite.corp.google.com/develop/ui/views/picture-in-picture#smoother-transition - lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.STARTED) { - trackPipAnimationHintView(binding.stopwatchBackground) - } - } - - // Handle events from the action icons on the picture-in-picture mode. - ActivityCompat.registerReceiver( - this, - broadcastReceiver, - IntentFilter(ACTION_STOPWATCH_CONTROL), - ContextCompat.RECEIVER_NOT_EXPORTED - ) - } - - // This is called when the activity gets into or out of the picture-in-picture mode. - override fun onPictureInPictureModeChanged( - isInPictureInPictureMode: Boolean, - newConfig: Configuration, - ) { - super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) - // Toggle visibility of in-app buttons. They cannot be interacted in the picture-in-picture - // mode, and their features are provided as the action icons. - toggleControls(if (isInPictureInPictureMode) View.GONE else View.VISIBLE) - } - - private fun toggleControls(view: Int) { - binding.clear.visibility = view - binding.startOrPause.visibility = view - } - - @RequiresApi(35) - override fun onPictureInPictureUiStateChanged(pipState: PictureInPictureUiState) { - super.onPictureInPictureUiStateChanged(pipState) - if (pipState.isTransitioningToPip) { - toggleControls(View.GONE) - } - } - - /** - * Updates the parameters of the picture-in-picture mode for this activity based on the current - * [started] state of the stopwatch. - */ - private fun updatePictureInPictureParams(started: Boolean): PictureInPictureParams { - val params = PictureInPictureParams.Builder() - // Set action items for the picture-in-picture mode. These are the only custom controls - // available during the picture-in-picture mode. - .setActions( - listOf( - // "Clear" action. - createRemoteAction( - R.drawable.ic_refresh_24dp, - R.string.clear, - REQUEST_CLEAR, - CONTROL_TYPE_CLEAR, - ), - if (started) { - // "Pause" action when the stopwatch is already started. - createRemoteAction( - R.drawable.ic_pause_24dp, - R.string.pause, - REQUEST_START_OR_PAUSE, - CONTROL_TYPE_START_OR_PAUSE, - ) - } else { - // "Start" action when the stopwatch is not started. - createRemoteAction( - R.drawable.ic_play_arrow_24dp, - R.string.start, - REQUEST_START_OR_PAUSE, - CONTROL_TYPE_START_OR_PAUSE, - ) - }, - ), - ) - // Set the aspect ratio of the picture-in-picture mode. - .setAspectRatio(Rational(16, 9)) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - // Turn the screen into the picture-in-picture mode if it's hidden by the "Home" button. - params.setAutoEnterEnabled(true) - // Disables the seamless resize. The seamless resize works great for videos where the - // content can be arbitrarily scaled, but you can disable this for non-video content so - // that the picture-in-picture mode is resized with a cross fade animation. - .setSeamlessResizeEnabled(false) } - return params.build().also { - setPictureInPictureParams(it) - } - } - - /** - * Creates a [RemoteAction]. It is used as an action icon on the overlay of the - * picture-in-picture mode. - */ - private fun createRemoteAction( - @DrawableRes iconResId: Int, - @StringRes titleResId: Int, - requestCode: Int, - controlType: Int, - ): RemoteAction { - return RemoteAction( - Icon.createWithResource(this, iconResId), - getString(titleResId), - getString(titleResId), - PendingIntent.getBroadcast( - this, - requestCode, - Intent(ACTION_STOPWATCH_CONTROL) - .putExtra(EXTRA_CONTROL_TYPE, controlType), - PendingIntent.FLAG_IMMUTABLE, - ), - ) } }