android中提供了两种View供用户播放视频,一种是利用SurfaceView另一是利用TextureView来播放视频。下面将介绍两种方式的使用方法:
利用SurfeceView播放视频
1、利用直接创建SurfaceView对象的方式:
初始化SurfaceView
val surfaceView = SurfaceView(this)
将SurfaceView加入到根布局中
frameLayout.addView(surfaceView)
2、利用xml中添加SurfaceView控件的方式:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TextureViewMainActivity"
android:id="@+id/frameLayout">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/surfaceView"
/>
<Button
android:id="@+id/btn_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:padding="8dp"
android:text="开始" />
</FrameLayout>
最后将SurfaceView中的SurfaceHolder设置到MediaPlayer中进行渲染
mediaPlayer.setDisplay(surfaceView.holder)
整体的代码:
import android.Manifest
import android.media.MediaPlayer
import android.os.Bundle
import android.os.Environment
import android.view.SurfaceView
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_surface_view.*
class SurfaceViewMainActivity : AppCompatActivity() {
private val mediaPlayer: MediaPlayer by lazy {
MediaPlayer()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_surface_view)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 100)
}
mediaPlayer.setScreenOnWhilePlaying(true)
mediaPlayer.setOnPreparedListener {
mediaPlayer.start()
}
mediaPlayer.setOnCompletionListener {
btn_play.text = "开始"
mediaPlayer.reset()
}
val surfaceView = SurfaceView(this)
frameLayout.addView(surfaceView)
btn_play.setOnClickListener {
if (btn_play.text == "开始") {
mediaPlayer.reset()
btn_play.text = "停止"
val openNonAssetFd = assets.openFd("test.mp4")
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
mediaPlayer.setDataSource(openNonAssetFd)
} else {
mediaPlayer.setDataSource(
Environment.getExternalStorageDirectory()
.absolutePath + "/Movies/test.mp4"
)
}
mediaPlayer.setDisplay(surfaceView.holder)
mediaPlayer.prepareAsync()
} else {
btn_play.text = "开始"
mediaPlayer.stop()
}
}
}
override fun onDestroy() {
super.onDestroy()
if (mediaPlayer.isPlaying) {
mediaPlayer.stop()
}
mediaPlayer.release()
}
}
利用TextureView播放视频
1、利用直接创建TextureView对象的方式:
初始化TextureView
val textureView = TextureView(this)
将TextureView加入到根布局中
frameLayout.addView(textureView)
2、利用xml中添加SurfaceView控件的方式:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TextureViewMainActivity"
android:id="@+id/frameLayout">
<TextureView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/textureView"
/>
<Button
android:id="@+id/btn_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:padding="8dp"
android:text="开始" />
</FrameLayout>
最后将TextureView中的SurfaceTexture设置到MediaPlayer中进行渲染
val surface = Surface(textureView.surfaceTexture)
mediaPlayer.setSurface(surface)
整体的代码:
import android.Manifest
import android.media.MediaPlayer
import android.os.Bundle
import android.os.Environment
import android.view.Surface
import android.view.TextureView
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_texture_view.*
class TextureViewMainActivity : AppCompatActivity() {
private val mediaPlayer: MediaPlayer by lazy {
MediaPlayer()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_texture_view)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 100)
}
mediaPlayer.setScreenOnWhilePlaying(true)
mediaPlayer.setOnPreparedListener {
mediaPlayer.start()
}
mediaPlayer.setOnCompletionListener {
btn_play.text = "开始"
mediaPlayer.reset()
}
val textureView = TextureView(this)
frameLayout.addView(textureView)
btn_play.setOnClickListener {
if (btn_play.text == "开始") {
mediaPlayer.reset()
btn_play.text = "停止"
val openNonAssetFd = assets.openFd("test.mp4")
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
mediaPlayer.setDataSource(openNonAssetFd)
} else {
mediaPlayer.setDataSource(
Environment.getExternalStorageDirectory()
.absolutePath + "/Movies/test.mp4"
)
}
val surface = Surface(textureView.surfaceTexture)
mediaPlayer.setSurface(surface)
mediaPlayer.prepareAsync()
} else {
btn_play.text = "开始"
mediaPlayer.stop()
}
}
}
override fun onDestroy() {
super.onDestroy()
if (mediaPlayer.isPlaying) {
mediaPlayer.stop()
}
mediaPlayer.release()
}
}
利用VideoView播放视频
1、利用直接创建VideoView对象的方式:
由于VideoView是SurfaceView的封装,其中的SurfaceView宽度和高度是获取的实际Video的宽高并在VideoView的onMeasure方法中进行均匀缩放的,因此需要重写onMeasure方法,直接获取新的测量值设置给VideoView。
MyVideoView重写OnMeasure()方法
class MyVideoView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : VideoView(context, attrs, defStyleAttr) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//由于VideoView是MatchParent getDefaultSize计算宽高和第一个参数没有关系
val measuredWidth = getDefaultSize(0,widthMeasureSpec)
val measuredHeight = getDefaultSize(0,heightMeasureSpec)
setMeasuredDimension(measuredWidth,measuredHeight)
}
}
初始化MyVideoView
val videoView = MyVideoView(this)
将MyVideoView加入到根布局中
frameLayout.addView(videoView)
2、利用xml中添加MyVideoView控件的方式:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TextureViewMainActivity"
android:id="@+id/frameLayout">
<com.jp.mediaplayer.video.MyVideoView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/videoView"
/>
<Button
android:id="@+id/btn_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:padding="8dp"
android:text="开始" />
</FrameLayout>
最后将TextureView中的SurfaceTexture设置到MediaPlayer中进行渲染
val surface = Surface(textureView.surfaceTexture)
mediaPlayer.setSurface(surface)
整体的代码:
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.jp.mediaplayer.video.MyVideoView
import kotlinx.android.synthetic.main.activity_video_view.*
class VideoViewActivity : AppCompatActivity() {
lateinit var videoView: MyVideoView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_video_view)
/*
//https://blog.csdn.net/jingzz1/article/details/111468726
val controller = ViewCompat.getWindowInsetsController(videoView)
controller?.hide(WindowInsetsCompat.Type.systemBars())
controller?.hide(WindowInsetsCompat.Type.navigationBars())*/
videoView = MyVideoView(this)
frameLayout.addView(videoView)
btn_play.setOnClickListener {
if (btn_play.text == "开始") {
btn_play.text = "停止"
videoView.setVideoURI(Uri.parse("android.resource://" + packageName + "/" + R.raw.test))
videoView.setOnCompletionListener {
btn_play.text = "开始"
}
videoView.setOnPreparedListener {
videoView.start()
}
} else {
btn_play.text = "开始"
videoView.stopPlayback()
}
}
}
/*
//https://blog.csdn.net/guolin_blog/article/details/51763825
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus && Build.VERSION.SDK_INT >= 19) {
val decorView = window.decorView
//真正的全屏模式
decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
}
*/
override fun onDestroy() {
super.onDestroy()
videoView?.stopPlayback()
}
}
以上的代码存放在Github:
https://github.com/jp5201314/MediaPlayer.git
有需要的可以在这里下载源码!!!