一手遮天 Android - view(媒体类): MediaPlayer(在 TextureView 上播放,可截图)

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

一手遮天 Android - view(媒体类): MediaPlayer(在 TextureView 上播放,可截图)

示例如下:

/view/media/MediaPlayerDemo2.kt

/**
 * MediaPlayer(在 TextureView 上播放,可截图)
 *
 * 用 TextureView 的话效率相对较低,如果没有截图等特殊要求的话,建议用 SurfaceView,参见 MediaPlayerDemo1.kt
 */

package com.webabcd.androiddemo.view.media

import android.content.pm.ActivityInfo
import android.graphics.Bitmap
import android.graphics.SurfaceTexture
import android.media.MediaPlayer
import android.media.MediaPlayer.*
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.Surface
import android.view.TextureView
import android.view.View
import android.view.WindowInsets
import androidx.appcompat.app.AppCompatActivity
import com.webabcd.androiddemo.databinding.ActivityViewMediaMediaplayerdemo2Binding
import java.util.*


class MediaPlayerDemo2 : AppCompatActivity(), TextureView.SurfaceTextureListener,
    OnBufferingUpdateListener,
    OnCompletionListener,
    OnPreparedListener,
    OnErrorListener,
    OnInfoListener,
    OnSeekCompleteListener,
    OnVideoSizeChangedListener {

    private val _logTag = "MediaPlayerDemo2"
    private lateinit var mBinding: ActivityViewMediaMediaplayerdemo2Binding

    private var _surfaceTexture: SurfaceTexture? = null
    private var _mediaPlayer: MediaPlayer? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mBinding = ActivityViewMediaMediaplayerdemo2Binding.inflate(layoutInflater)
        setContentView(mBinding.root)

        // 横屏
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
        // 隐藏状态栏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val controller = window.insetsController
            controller!!.hide(WindowInsets.Type.statusBars())
        }

        mBinding.textureView.surfaceTextureListener = this

        mBinding.button1.setOnClickListener {
            playVideo()
        }

        mBinding.button2.setOnClickListener {
            stopVideo()
        }

        mBinding.button3.setOnClickListener {
            // 截图
            showFrameImage()
        }
    }

    override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {

        printLog(String.format(Locale.US, "onSurfaceTextureAvailable, width:%d, height:%d", width, height))

        if (_surfaceTexture == null) {
            _surfaceTexture = surface;
        }
    }

    override fun onSurfaceTextureSizeChanged(p0: SurfaceTexture, width: Int, height: Int) {
        printLog(String.format(Locale.US, "onSurfaceTextureSizeChanged, width:%d, height:%d", width, height))
    }

    override fun onSurfaceTextureDestroyed(p0: SurfaceTexture): Boolean {
        printLog("onSurfaceTextureDestroyed")
        return false
    }

    override fun onSurfaceTextureUpdated(p0: SurfaceTexture) {
        // printLog("onSurfaceTextureUpdated")
    }


    private fun playVideo() {
        stopVideo()
        try {
            _mediaPlayer = MediaPlayer()
            _mediaPlayer!!.setSurface(Surface(_surfaceTexture))
            _mediaPlayer!!.setOnBufferingUpdateListener(this)
            _mediaPlayer!!.setOnPreparedListener(this)
            _mediaPlayer!!.setOnCompletionListener(this)
            _mediaPlayer!!.setOnErrorListener(this)
            _mediaPlayer!!.setOnInfoListener(this)
            _mediaPlayer!!.setOnSeekCompleteListener(this)
            _mediaPlayer!!.setOnVideoSizeChangedListener(this)

            _mediaPlayer!!.setDataSource("https://d2zihajmogu5jn.cloudfront.net/sintel/master.m3u8")
            _mediaPlayer!!.prepareAsync()
        } catch (ex: Exception) {
            printLog("mediaPlayer error: $ex")
        }
    }

    private fun stopVideo() {
        if (_mediaPlayer != null) {
            _mediaPlayer!!.stop()
            _mediaPlayer!!.release()
            _mediaPlayer = null
        }
    }

    // 对 TextureView 截图
    private fun showFrameImage() {
        mBinding.imageView.visibility = View.VISIBLE
        val bitmap:Bitmap? = mBinding.textureView.bitmap // 对 TextureView 截图
        if (bitmap != null) {
            mBinding.imageView.setImageBitmap(bitmap)
        }
    }

    override fun onPrepared(p0: MediaPlayer?) {
        _mediaPlayer!!.start()
    }

    override fun onInfo(p0: MediaPlayer?, what: Int, extra: Int): Boolean {
        printLog(String.format(Locale.US, "onInfo, what:%d, extra:%d", what, extra))
        return false
    }

    override fun onError(p0: MediaPlayer?, what: Int, extra: Int): Boolean {
        printLog(String.format(Locale.US, "onError, what:%d, extra:%d", what, extra))
        return false
    }

    override fun onVideoSizeChanged(p0: MediaPlayer?, width: Int, height: Int) {
        printLog(String.format(Locale.US, "onVideoSizeChanged, width:%d, height:%d", width, height))
    }

    override fun onSeekComplete(p0: MediaPlayer?) {
        printLog("onSeekComplete")
    }

    override fun onCompletion(p0: MediaPlayer?) {
        printLog("onCompletion")
    }

    override fun onBufferingUpdate(p0: MediaPlayer?, percent: Int) {
        // printLog(String.format(Locale.US, "onBufferingUpdate, percent:%d", percent));
    }



    private fun printLog(message: String) {
        Log.d(_logTag, message)
        mBinding.txtLog.post(Runnable {
            mBinding.txtLog.append(message)
            mBinding.txtLog.append("\n")
            val offset: Int = mBinding.txtLog.lineCount * mBinding.txtLog.lineHeight
            if (offset > mBinding.txtLog.height) {
                mBinding.txtLog.scrollTo(0, offset - mBinding.txtLog.height)
            }
        })
    }
}

/layout/activity_view_media_mediaplayerdemo2.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black">

    <TextureView
        android:id="@+id/textureView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="160dp"
        android:layout_height="90dp"
        android:scaleType="fitXY"
        android:visibility="gone"
        android:layout_gravity="bottom|end"/>

    <LinearLayout
        android:id="@+id/buttonContainer"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:alpha="0.85">

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/selector_button_background"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            android:textAllCaps="false"
            android:text="播放"
            android:textColor="#fff" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:background="@drawable/selector_button_background"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            android:textAllCaps="false"
            android:text="停止"
            android:textColor="#fff" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:background="@drawable/selector_button_background"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            android:textAllCaps="false"
            android:text="截屏"
            android:textColor="#fff" />

    </LinearLayout>

    <TextView
        android:id="@+id/txtStatus"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_gravity="bottom"
        android:background="#9933b8fc"
        android:gravity="center"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/txtLog"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_marginBottom="40dp"
        android:padding="5dp"
        android:layout_gravity="right"
        android:background="#7733b8fc"
        android:gravity="top"
        android:textColor="#fff" />

</FrameLayout>

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

posted @ 2023-04-04 11:40  webabcd  阅读(254)  评论(0编辑  收藏  举报