音视频播放IjkMediaPlayer
2021-11-10 本文已影响0人
码农_小斌哥
1.引入依赖:implementation "com.gitee.nurApplication:NurVideoPlayer:2.1.6"
2.视频播放activity:
import android.util.Log
import android.view.KeyEvent
import android.view.View
import cn.lecent.prisonroom.basemodule.BaseAppActivity
import cn.lecent.prisonroom.broadcastmodule.databinding.ActivityTalkbackVideoBinding
import com.blankj.utilcode.util.SPUtils
import com.bumptech.glide.Glide
import com.nurmemet.nur.nurvideoplayer.listener.OnControlClickListener
/**
*
* 音视频播放器
*/
class TalkbackVideoActivity : BaseAppActivity(), OnControlClickListener {
private lateinit var binding: ActivityTalkbackVideoBinding
private val ID_SCREEN_VIEW = 1010
override fun getRootView(): View {
binding = ActivityTalkbackVideoBinding.inflate(layoutInflater)
return binding.root
}
override fun initData() {
super.initData()
// binding.llLayout.setOnClickListener { finish() }
val imgVideoUrl = intent.getStringExtra("imgVideoUrl")
val url = intent.getStringExtra("url")
val videoName = intent.getStringExtra("videoName")
Log.e("TAG", "player: $url")
var videoUrl: String? = null
url?.let {
videoUrl = if (it.startsWith("http") || it.startsWith("https")) {
it
} else {
SPUtils.getInstance().getString("baseUrl", null) + it
}
}
if (!imgVideoUrl.isNullOrEmpty()) {
val url = SPUtils.getInstance().getString("baseUrl", null) + imgVideoUrl
Glide.with(this).load(url).into(binding.videoView.thumbImageView)
}
binding.videoView.run {
setUp(this@TalkbackVideoActivity, videoUrl,videoName)
start()
findViewById<View>(ID_SCREEN_VIEW).visibility = View.INVISIBLE
setOnControlClickListener(this@TalkbackVideoActivity)
}
}
override fun onBackPressed() {
if (binding.videoView.isFullScreen) {
binding.videoView.setChangeScreen(false)
} else super.onBackPressed()
}
override fun onPause() {
super.onPause()
binding.videoView.pause()
}
override fun onResume() {
super.onResume()
binding.videoView.start()
}
override fun onDestroy() {
super.onDestroy()
binding.videoView.stopPlay()
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
val b: Boolean = binding.videoView.onKeyDown(keyCode)
return b || super.onKeyDown(keyCode, event)
}
override fun onBackBtnClick() {
finish()
}
override fun onVolumeControlClick() {
}
override fun onScreenControlClick() {
}
}
3.activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".ui.TalkbackVideoActivity">
<androidx.cardview.widget.CardView
android:id="@+id/cv_open"
android:layout_width="@dimen/dp_283"
android:layout_height="@dimen/dp_200"
android:layout_centerHorizontal="true"
app:cardCornerRadius="@dimen/dp_7"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<!--视频-->
<RelativeLayout
android:id="@+id/main_video_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.nurmemet.nur.nurvideoplayer.NurVideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--播放器下面的UI写在这里-->
</com.nurmemet.nur.nurvideoplayer.NurVideoView>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
4.音频播放:
import android.media.AudioManager;
import java.io.IOException;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
/**
* 创建时间:2021/11/10
* 作者:huangyougui
* 描述:音频播放器
*/
public class IjkAudioPlayer {
private IjkMediaPlayer ijkMediaPlayer;
public IjkMediaPlayer getPlayer() {
return ijkMediaPlayer;
}
public void init() {
if (ijkMediaPlayer == null) {
ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"soundtouch",0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"analyzemaxduration",50L);
}
ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
public void setPathAndPrepare(String uri) {
try {
ijkMediaPlayer.setDataSource(uri);
ijkMediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
if (ijkMediaPlayer != null) {
ijkMediaPlayer.start();
}
}
public void pause(){
if (ijkMediaPlayer != null) {
ijkMediaPlayer.pause();
}
}
public void stop(){
if (ijkMediaPlayer != null) {
ijkMediaPlayer.stop();
}
}
/**
* 耗时
*/
public void reset(){
if (ijkMediaPlayer != null) {
ijkMediaPlayer.reset();
}
}
public void release() {
if (ijkMediaPlayer != null) {
ijkMediaPlayer.reset();
ijkMediaPlayer.release();
ijkMediaPlayer = null;
}
}
}
5.后台播放服务:
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.IBinder
import android.text.TextUtils
import android.widget.Toast
import cn.lecent.prisonroom.broadcastmodule.ui.IjkAudioPlayer
import tv.danmaku.ijk.media.player.IMediaPlayer
/**
*创建时间:2021/11/10
*作者:huangyougui
*描述:音频后台播放服务
*/
class AudioPlayerService : Service(), IMediaPlayer.OnErrorListener,
IMediaPlayer.OnPreparedListener {
//ijk播放器
private var ijkAudioPlayer: IjkAudioPlayer? = null
private var isPrepared = false
private var isStop = false
private var isPause = false
//是否播放过音乐、防止多次启动时setPathAndPrepare 异常(无法捕获)
private var isInit = false
//记录播放uri
private var oldUri: String? = ""
override fun onBind(intent: Intent): IBinder? = null
override fun onCreate() {
super.onCreate()
if (ijkAudioPlayer == null) {
ijkAudioPlayer = IjkAudioPlayer()
ijkAudioPlayer?.run{
init()
player.setOnErrorListener(this@AudioPlayerService)
player.setOnPreparedListener(this@AudioPlayerService)
}
}
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (intent?.action != null) {
when (intent.action) {
PLAY -> {
val uri = intent.getStringExtra(PLAY_URI)
val sameUri = oldUri == uri
oldUri = uri
//是否是暂停
if (isPrepared && isPause && sameUri) {
ijkAudioPlayer?.start()
isPause = false
//当停止播放时
} else if (isStop || ijkAudioPlayer!!.player.isPlaying || !sameUri) {
ijkAudioPlayer?.run {
stop()
reset()
setPathAndPrepare(uri)
}
} else {
if (!isInit) {
ijkAudioPlayer?.setPathAndPrepare(uri)
}
}
}
PAUSE -> if (ijkAudioPlayer!!.player.isPlaying) {
ijkAudioPlayer?.pause()
isPause = true
}
CONTINUE_PLAY -> if (!TextUtils.isEmpty(oldUri)) {
if (isPrepared && isPause) {
ijkAudioPlayer?.start()
isPause = false
}
}
STOP -> if (ijkAudioPlayer!!.player.isPlaying) {
ijkAudioPlayer?.stop()
isPrepared = false
isStop = true
}
STOP_PLAY_SERVICE -> stopSelf()
}
}
return START_NOT_STICKY
}
override fun onDestroy() {
super.onDestroy()
ijkAudioPlayer?.stop()
ijkAudioPlayer?.release()
isPrepared = false
}
override fun onError(iMediaPlayer: IMediaPlayer, i: Int, i1: Int): Boolean {
isPrepared = false
isStop = true
Toast.makeText(this, "出错了、请重试!", Toast.LENGTH_SHORT).show()
return false
}
override fun onPrepared(iMediaPlayer: IMediaPlayer) {
isInit = true
isPrepared = true
isStop = false
iMediaPlayer.start()
isPause = false
}
companion object {
private const val PLAY_URI = "play_uri"//音频url
private const val PLAY = "play"//播放
private const val CONTINUE_PLAY = "continue_play"//继续播放
private const val PAUSE = "pause"//暂停
private const val STOP = "stop"//停止
const val STOP_PLAY_SERVICE = "stop_play_service"//终止服务
//启动服务播放
fun startPlay(context: Context, uri: String?) {
context.startService(
Intent(context, AudioPlayerService::class.java).putExtra(PLAY_URI, uri).setAction(
PLAY
)
)
}
//继续播放、若已发生暂停
fun continuePlay(context: Context) {
context.startService(
Intent(context, AudioPlayerService::class.java).setAction(
CONTINUE_PLAY
)
)
}
//暂停播放
fun pausePlay(context: Context) {
context.startService(Intent(context, AudioPlayerService::class.java).setAction(PAUSE))
}
//停止播放
fun stopPlay(context: Context) {
context.startService(Intent(context, AudioPlayerService::class.java).setAction(STOP))
}
}
}