aboutsummaryrefslogtreecommitdiff
path: root/media
diff options
context:
space:
mode:
authorYuichi Araki <yaraki@google.com>2017-05-19 11:51:48 -0700
committerYuichi Araki <yaraki@google.com>2017-05-21 05:59:09 -0700
commit675a94fd7685663fe694def51f89b84a0833e0eb (patch)
tree1d80152ec85d47d18e29f7456f6cf1a039a683db /media
parent8df02996fbcbeae332a12e8ac9d4cc4486039008 (diff)
downloadandroid-675a94fd7685663fe694def51f89b84a0833e0eb.tar.gz
Tidy up some Kotlin implementation
Test: Existing tests pass Change-Id: Id24d314798be483ea4682358882539bf9da72e7f
Diffstat (limited to 'media')
-rw-r--r--media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/MainActivity.kt121
-rw-r--r--media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/widget/MovieView.kt170
2 files changed, 132 insertions, 159 deletions
diff --git a/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/MainActivity.kt b/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/MainActivity.kt
index a09e5f53..c1fc2ba2 100644
--- a/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/MainActivity.kt
+++ b/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/MainActivity.kt
@@ -40,27 +40,61 @@ import java.util.*
*/
class MainActivity : AppCompatActivity() {
+ companion object {
+
+ /** Intent action for media controls from Picture-in-Picture mode. */
+ private val ACTION_MEDIA_CONTROL = "media_control"
+
+ /** Intent extra for media controls from Picture-in-Picture mode. */
+ private val EXTRA_CONTROL_TYPE = "control_type"
+
+ /** The request code for play action PendingIntent. */
+ private val REQUEST_PLAY = 1
+
+ /** The request code for pause action PendingIntent. */
+ private val REQUEST_PAUSE = 2
+
+ /** The request code for info action PendingIntent. */
+ private val REQUEST_INFO = 3
+
+ /** The intent extra value for play action. */
+ private val CONTROL_TYPE_PLAY = 1
+
+ /** The intent extra value for pause action. */
+ private val CONTROL_TYPE_PAUSE = 2
+
+ }
+
/** The arguments to be used for Picture-in-Picture mode. */
private val mPictureInPictureArgs = PictureInPictureArgs()
/** This shows the video. */
- private var mMovieView: MovieView? = null
+ private lateinit var mMovieView: MovieView
/** The bottom half of the screen; hidden on landscape */
- private var mScrollView: ScrollView? = null
+ private lateinit var mScrollView: ScrollView
/** A [BroadcastReceiver] to receive action item events from Picture-in-Picture mode. */
- private var mReceiver: BroadcastReceiver? = null
-
- private val labelPlay: String by lazy { getString(R.string.play) }
- private val labelPause: String by lazy { getString(R.string.pause) }
+ private val mReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent?) {
+ intent?.let { intent ->
+ if (intent.action != ACTION_MEDIA_CONTROL) {
+ return
+ }
- private val mOnClickListener = View.OnClickListener { view ->
- when (view.id) {
- R.id.pip -> minimize()
+ // This is where we are called back from Picture-in-Picture action items.
+ val controlType = intent.getIntExtra(EXTRA_CONTROL_TYPE, 0)
+ when (controlType) {
+ CONTROL_TYPE_PLAY -> mMovieView.play()
+ CONTROL_TYPE_PAUSE -> mMovieView.pause()
+ }
+ }
}
}
+ private val labelPlay: String by lazy { getString(R.string.play) }
+ private val labelPause: String by lazy { getString(R.string.pause) }
+
/**
* Callbacks from the [MovieView] showing the video playback.
*/
@@ -137,22 +171,22 @@ class MainActivity : AppCompatActivity() {
mScrollView = findViewById(R.id.scroll) as ScrollView
// Set up the video; it automatically starts.
- mMovieView?.setMovieListener(mMovieListener)
- findViewById(R.id.pip).setOnClickListener(mOnClickListener)
+ mMovieView.setMovieListener(mMovieListener)
+ findViewById(R.id.pip).setOnClickListener { minimize() }
}
override fun onStop() {
// On entering Picture-in-Picture mode, onPause is called, but not onStop.
// For this reason, this is the place where we should pause the video playback.
- mMovieView?.pause()
+ mMovieView.pause()
super.onStop()
}
override fun onRestart() {
super.onRestart()
// Show the video controls so the video can be easily resumed.
- if (!isInPictureInPictureMode()) {
- mMovieView?.showControls()
+ if (!isInPictureInPictureMode) {
+ mMovieView.showControls()
}
}
@@ -173,28 +207,13 @@ class MainActivity : AppCompatActivity() {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
if (isInPictureInPictureMode) {
// Starts receiving events from action items in PiP mode.
- mReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent?) {
- if (intent == null || ACTION_MEDIA_CONTROL != intent.action) {
- return
- }
-
- // This is where we are called back from Picture-in-Picture action items.
- val controlType = intent.getIntExtra(EXTRA_CONTROL_TYPE, 0)
- when (controlType) {
- CONTROL_TYPE_PLAY -> mMovieView?.play()
- CONTROL_TYPE_PAUSE -> mMovieView?.pause()
- }
- }
- }
registerReceiver(mReceiver, IntentFilter(ACTION_MEDIA_CONTROL))
} else {
// We are out of PiP mode. We can stop receiving events from it.
unregisterReceiver(mReceiver)
- mReceiver = null
// Show the video controls if the video is not playing
- if (mMovieView != null && !mMovieView!!.isPlaying) {
- mMovieView!!.showControls()
+ if (!mMovieView.isPlaying) {
+ mMovieView.showControls()
}
}
}
@@ -203,14 +222,10 @@ class MainActivity : AppCompatActivity() {
* Enters Picture-in-Picture mode.
*/
internal fun minimize() {
- if (mMovieView == null) {
- return
- }
// Hide the controls in picture-in-picture mode.
- mMovieView!!.hideControls()
+ mMovieView.hideControls()
// Calculate the aspect ratio of the PiP screen.
- val aspectRatio = mMovieView!!.width.toFloat() / mMovieView!!.height
- mPictureInPictureArgs.setAspectRatio(aspectRatio)
+ mPictureInPictureArgs.setAspectRatio(mMovieView.width.toFloat() / mMovieView.height)
enterPictureInPictureMode(mPictureInPictureArgs)
}
@@ -228,37 +243,13 @@ class MainActivity : AppCompatActivity() {
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- mScrollView?.visibility = View.GONE
- mMovieView?.setAdjustViewBounds(false)
+ mScrollView.visibility = View.GONE
+ mMovieView.setAdjustViewBounds(false)
} else {
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- mScrollView?.visibility = View.VISIBLE
- mMovieView?.setAdjustViewBounds(true)
+ mScrollView.visibility = View.VISIBLE
+ mMovieView.setAdjustViewBounds(true)
}
}
- companion object {
-
- /** Intent action for media controls from Picture-in-Picture mode. */
- private val ACTION_MEDIA_CONTROL = "media_control"
-
- /** Intent extra for media controls from Picture-in-Picture mode. */
- private val EXTRA_CONTROL_TYPE = "control_type"
-
- /** The request code for play action PendingIntent. */
- private val REQUEST_PLAY = 1
-
- /** The request code for pause action PendingIntent. */
- private val REQUEST_PAUSE = 2
-
- /** The request code for info action PendingIntent. */
- private val REQUEST_INFO = 3
-
- /** The intent extra value for play action. */
- private val CONTROL_TYPE_PLAY = 1
-
- /** The intent extra value for pause action. */
- private val CONTROL_TYPE_PAUSE = 2
- }
-
}
diff --git a/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/widget/MovieView.kt b/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/widget/MovieView.kt
index e6081c72..04f10aae 100644
--- a/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/widget/MovieView.kt
+++ b/media/PictureInPicture/kotlinApp/app/src/main/java/com/example/android/pictureinpicture/widget/MovieView.kt
@@ -47,6 +47,18 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
defStyleAttr: Int = 0) :
RelativeLayout(context, attrs, defStyleAttr) {
+ companion object {
+
+ private val TAG = "MovieView"
+
+ /** The amount of time we are stepping forward or backward for fast-forward and fast-rewind. */
+ private val FAST_FORWARD_REWIND_INTERVAL = 5000 // ms
+
+ /** The amount of time until we fade out the controls. */
+ private val TIMEOUT_CONTROLS = 3000L // ms
+
+ }
+
/**
* Monitors all events related to [MovieView].
*/
@@ -101,12 +113,12 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
// Inflate the content
View.inflate(context, R.layout.view_movie, this)
- mSurfaceView = findViewById<View>(R.id.surface) as SurfaceView
+ mSurfaceView = findViewById<SurfaceView>(R.id.surface)
mShade = findViewById<View>(R.id.shade)
- mToggle = findViewById<View>(R.id.toggle) as ImageButton
- mFastForward = findViewById<View>(R.id.fast_forward) as ImageButton
- mFastRewind = findViewById<View>(R.id.fast_rewind) as ImageButton
- mMinimize = findViewById<View>(R.id.minimize) as ImageButton
+ mToggle = findViewById<ImageButton>(R.id.toggle)
+ mFastForward = findViewById<ImageButton>(R.id.fast_forward)
+ mFastRewind = findViewById<ImageButton>(R.id.fast_rewind)
+ mMinimize = findViewById<ImageButton>(R.id.minimize)
// Attributes
val a = context.obtainStyledAttributes(attrs, R.styleable.MovieView,
@@ -125,14 +137,16 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
R.id.minimize -> mMovieListener?.onMovieMinimized()
}
// Start or reset the timeout to hide controls
- if (mMediaPlayer != null) {
+ mMediaPlayer?.let { player ->
if (mTimeoutHandler == null) {
mTimeoutHandler = TimeoutHandler(this@MovieView)
}
- mTimeoutHandler!!.removeMessages(TimeoutHandler.MESSAGE_HIDE_CONTROLS)
- if (mMediaPlayer!!.isPlaying) {
- mTimeoutHandler!!.sendEmptyMessageDelayed(
- TimeoutHandler.MESSAGE_HIDE_CONTROLS, TIMEOUT_CONTROLS.toLong())
+ mTimeoutHandler?.let { handler ->
+ handler.removeMessages(TimeoutHandler.MESSAGE_HIDE_CONTROLS)
+ if (player.isPlaying) {
+ handler.sendEmptyMessageDelayed(TimeoutHandler.MESSAGE_HIDE_CONTROLS,
+ TIMEOUT_CONTROLS)
+ }
}
}
}
@@ -148,23 +162,22 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
openVideo(holder.surface)
}
- override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
+ override fun surfaceChanged(holder: SurfaceHolder, format: Int,
+ width: Int, height: Int) {
// Do nothing
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
- if (mMediaPlayer != null) {
- mSavedCurrentPosition = mMediaPlayer!!.currentPosition
- }
+ mMediaPlayer?.let { mSavedCurrentPosition = it.currentPosition }
closeVideo()
}
})
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- if (mMediaPlayer != null) {
- val videoWidth = mMediaPlayer!!.videoWidth
- val videoHeight = mMediaPlayer!!.videoHeight
+ mMediaPlayer?.let { player ->
+ val videoWidth = player.videoWidth
+ val videoHeight = player.videoHeight
if (videoWidth != 0 && videoHeight != 0) {
val aspectRatio = videoHeight.toFloat() / videoWidth
val width = View.MeasureSpec.getSize(widthMeasureSpec)
@@ -172,11 +185,13 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
val height = View.MeasureSpec.getSize(heightMeasureSpec)
val heightMode = View.MeasureSpec.getMode(heightMeasureSpec)
if (mAdjustViewBounds) {
- if (widthMode == View.MeasureSpec.EXACTLY && heightMode != View.MeasureSpec.EXACTLY) {
+ if (widthMode == View.MeasureSpec.EXACTLY
+ && heightMode != View.MeasureSpec.EXACTLY) {
super.onMeasure(widthMeasureSpec,
View.MeasureSpec.makeMeasureSpec((width * aspectRatio).toInt(),
View.MeasureSpec.EXACTLY))
- } else if (widthMode != View.MeasureSpec.EXACTLY && heightMode == View.MeasureSpec.EXACTLY) {
+ } else if (widthMode != View.MeasureSpec.EXACTLY
+ && heightMode == View.MeasureSpec.EXACTLY) {
super.onMeasure(View.MeasureSpec.makeMeasureSpec((height / aspectRatio).toInt(),
View.MeasureSpec.EXACTLY), heightMeasureSpec)
} else {
@@ -202,10 +217,8 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
}
override fun onDetachedFromWindow() {
- if (mTimeoutHandler != null) {
- mTimeoutHandler!!.removeMessages(TimeoutHandler.MESSAGE_HIDE_CONTROLS)
- mTimeoutHandler = null
- }
+ mTimeoutHandler?.removeMessages(TimeoutHandler.MESSAGE_HIDE_CONTROLS)
+ mTimeoutHandler = null
super.onDetachedFromWindow()
}
@@ -276,24 +289,18 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
* Fast-forward the video.
*/
fun fastForward() {
- if (mMediaPlayer == null) {
- return
- }
- mMediaPlayer!!.seekTo(mMediaPlayer!!.currentPosition + FAST_FORWARD_REWIND_INTERVAL)
+ mMediaPlayer?.let { it.seekTo(it.currentPosition + FAST_FORWARD_REWIND_INTERVAL) }
}
/**
* Fast-rewind the video.
*/
fun fastRewind() {
- if (mMediaPlayer == null) {
- return
- }
- mMediaPlayer!!.seekTo(mMediaPlayer!!.currentPosition - FAST_FORWARD_REWIND_INTERVAL)
+ mMediaPlayer?.let { it.seekTo(it.currentPosition - FAST_FORWARD_REWIND_INTERVAL) }
}
val isPlaying: Boolean
- get() = mMediaPlayer != null && mMediaPlayer!!.isPlaying
+ get() = mMediaPlayer?.isPlaying ?: false
fun play() {
if (mMediaPlayer == null) {
@@ -302,9 +309,7 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
mMediaPlayer!!.start()
adjustToggleState()
keepScreenOn = true
- if (mMovieListener != null) {
- mMovieListener!!.onMovieStarted()
- }
+ mMovieListener?.onMovieStarted()
}
fun pause() {
@@ -315,9 +320,7 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
mMediaPlayer!!.pause()
adjustToggleState()
keepScreenOn = false
- if (mMovieListener != null) {
- mMovieListener!!.onMovieStopped()
- }
+ mMovieListener?.onMovieStopped()
}
internal fun openVideo(surface: Surface) {
@@ -325,52 +328,42 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
return
}
mMediaPlayer = MediaPlayer()
- mMediaPlayer!!.setSurface(surface)
- try {
- resources.openRawResourceFd(mVideoResourceId).use { fd ->
- mMediaPlayer!!.setDataSource(fd)
- mMediaPlayer!!.setOnPreparedListener { mediaPlayer ->
- // Adjust the aspect ratio of this view
- requestLayout()
- if (mSavedCurrentPosition > 0) {
- mediaPlayer.seekTo(mSavedCurrentPosition)
- mSavedCurrentPosition = 0
- } else {
- // Start automatically
- play()
+ mMediaPlayer?.let { player ->
+ player.setSurface(surface)
+ try {
+ resources.openRawResourceFd(mVideoResourceId).use { fd ->
+ player.setDataSource(fd)
+ player.setOnPreparedListener { mediaPlayer ->
+ // Adjust the aspect ratio of this view
+ requestLayout()
+ if (mSavedCurrentPosition > 0) {
+ mediaPlayer.seekTo(mSavedCurrentPosition)
+ mSavedCurrentPosition = 0
+ } else {
+ // Start automatically
+ play()
+ }
}
- }
- mMediaPlayer!!.setOnCompletionListener {
- adjustToggleState()
- keepScreenOn = false
- if (mMovieListener != null) {
- mMovieListener!!.onMovieStopped()
+ player.setOnCompletionListener {
+ adjustToggleState()
+ keepScreenOn = false
+ mMovieListener?.onMovieStopped()
}
+ player.prepare()
}
- mMediaPlayer!!.prepare()
+ } catch (e: IOException) {
+ Log.e(TAG, "Failed to open video", e)
}
- } catch (e: IOException) {
- Log.e(TAG, "Failed to open video", e)
}
-
}
internal fun closeVideo() {
- if (mMediaPlayer != null) {
- mMediaPlayer!!.release()
- mMediaPlayer = null
- }
+ mMediaPlayer?.release()
+ mMediaPlayer = null
}
internal fun toggle() {
- if (mMediaPlayer == null) {
- return
- }
- if (mMediaPlayer!!.isPlaying) {
- pause()
- } else {
- play()
- }
+ mMediaPlayer?.let { if (it.isPlaying) pause() else play() }
}
internal fun toggleControls() {
@@ -382,24 +375,25 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
}
internal fun adjustToggleState() {
- if (mMediaPlayer != null && mMediaPlayer!!.isPlaying) {
- mToggle.contentDescription = resources.getString(R.string.pause)
- mToggle.setImageResource(R.drawable.ic_pause_64dp)
- } else {
- mToggle.contentDescription = resources.getString(R.string.play)
- mToggle.setImageResource(R.drawable.ic_play_arrow_64dp)
+ mMediaPlayer?.let {
+ if (it.isPlaying) {
+ mToggle.contentDescription = resources.getString(R.string.pause)
+ mToggle.setImageResource(R.drawable.ic_pause_64dp)
+ } else {
+ mToggle.contentDescription = resources.getString(R.string.play)
+ mToggle.setImageResource(R.drawable.ic_play_arrow_64dp)
+ }
}
}
- private class TimeoutHandler internal constructor(view: MovieView) : Handler() {
+ private class TimeoutHandler(view: MovieView) : Handler() {
private val mMovieViewRef: WeakReference<MovieView> = WeakReference(view)
override fun handleMessage(msg: Message) {
when (msg.what) {
MESSAGE_HIDE_CONTROLS -> {
- val movieView = mMovieViewRef.get()
- movieView?.hideControls()
+ mMovieViewRef.get()?.hideControls()
}
else -> super.handleMessage(msg)
}
@@ -411,16 +405,4 @@ class MovieView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
}
- companion object {
-
- private val TAG = "MovieView"
-
- /** The amount of time we are stepping forward or backward for fast-forward and fast-rewind. */
- private val FAST_FORWARD_REWIND_INTERVAL = 5000 // ms
-
- /** The amount of time until we fade out the controls. */
- private val TIMEOUT_CONTROLS = 3000 // ms
-
- }
-
}