implementation 'com.google.android.exoplayer:exoplayer:2.11.4'
我在此时查到的最新版的是2.11.4的,你们可以通过github获取到当前最新版本,地址:Exoplayer
再写出使用的仓库:
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } //添加这句,使用阿里云镜像
google()
jcenter()
mavenCentral()
maven { url 'https://maven.google.com' }
}
此时进行rebuild你将报错,报错信息为:
Invoke-customs are only supported starting with Android O (--min-api 26)
你需要在让他支持java8,写在buiud.gradle(Module:app)中;
android {
buildTypes {。。。。。。省略不写}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
到这里,前期工作就已经完成了,接下来就是使用了;
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Activity.PlayerActivity"
android:fitsSystemWindows="false">
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="300dp"
app:controller_layout_id="@layout/control_view"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
其中app:controller_layout_id="@layout/control_view"
为我自定义了控制器(播放,暂停等),其中可以将不需要的控件进行删除,需要的控件(播放、暂停)等,你不能改变id;下面是自定义的播放控制器;如果你不需要自定义,将这句代码:app:controller_layout_id="@layout/control_view"
删除即可,会使用默认的控制器;控制器的代码你可以通过全局搜索:exo_playback_control_view.xml
拿到;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#A4000000"
android:layoutDirection="ltr"
android:orientation="vertical"
tools:targetApi="28">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="4dp">
<ImageButton
android:id="@id/exo_prev"
style="@style/ExoMediaButton.Previous" />
<ImageButton
android:id="@id/exo_rew"
style="@style/ExoMediaButton.Rewind" />
<ImageButton
android:id="@id/exo_shuffle"
style="@style/ExoMediaButton" />
<ImageButton
android:id="@id/exo_repeat_toggle"
style="@style/ExoMediaButton" />
<ImageButton
android:id="@id/exo_play"
style="@style/ExoMediaButton.Play" />
<ImageButton
android:id="@id/exo_pause"
style="@style/ExoMediaButton.Pause" />
<ImageButton
android:id="@id/exo_ffwd"
style="@style/ExoMediaButton.FastForward" />
<ImageButton
android:id="@id/exo_next"
style="@style/ExoMediaButton.Next" />
<ImageButton
android:id="@id/exo_vr"
style="@style/ExoMediaButton.VR" />
<TextView
android:id="@+id/fullscreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全屏"
android:textColor="#FFFFFF"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textColor="#FFBEBEBE"
android:textSize="14sp"
android:textStyle="bold" />
<View
android:id="@id/exo_progress_placeholder"
android:layout_width="0dp"
android:layout_height="26dp"
android:layout_weight="1" />
<TextView
android:id="@id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textColor="#FFBEBEBE"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
private fun createMediaSource(intent: Intent): MediaSource? {
//首先你需要获取到Uri,我这里是通过另一个activity的intent传递过来的
var videoUri: Uri = intent.getParcelableExtra("uri")
//接下来你需要分析出你要播放的视频是什么格式的
val type: Int = Util.inferContentType(videoUri)
println("解析出的视频格式为 : $type")
//这里的BassApplication是我自定义的application的名称
var dataSourceFactory: DataSource.Factory =
DefaultHttpDataSourceFactory(Util.getUserAgent(this, "BassApplication"))
//接下来就是根据不同的视频格式,创建不同的MediaSource了
return when (type) {
C.TYPE_DASH ->
DashMediaSource.Factory(dataSourceFactory).createMediaSource(videoUri)
C.TYPE_SS ->
SsMediaSource.Factory(dataSourceFactory).createMediaSource(videoUri)
C.TYPE_HLS ->
HlsMediaSource.Factory(dataSourceFactory).createMediaSource(videoUri)
C.TYPE_OTHER ->
ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(videoUri)
else -> null
}
}
首先,我们需要一个SimpleExoPlayer;
trackSelector,这个将用于打印debug的时候用的,Exoplayer支持你打印一些信息,以方便你调试使用;这里我们先初始化好;
private var player: SimpleExoPlayer? = null
private var trackSelector: DefaultTrackSelector? = null
private var startAutoplay = true
接下来,我们来初始化player;
private fun initPlayer() {
if (player == null) {
trackSelector = DefaultTrackSelector(this)
//初始化Exoplayer
player = SimpleExoPlayer.Builder(this).build()
//监听播放状态以及失败原因
player!!.addListener(PlayerEventListener())
//将错误信息打印出来
player!!.addAnalyticsListener(EventLogger(trackSelector))
//
player!!.setAudioAttributes(
AudioAttributes.DEFAULT, /* handleAudioFocus= */ /* handleAudioFocus= */
true
)
//当他准备好资源后就播放
player!!.playWhenReady = startAutoplay
//这里是将player设置近player_view中
player_view.player = player
//
player_view.setPlaybackPreparer(this)
}
//初始化完成后,我们就将资源设置近player中
createMediaSource(intent)?.let { player!!.prepare(it) }
}
//这里监听到播放时的状态,以及获取到异常情况
private class PlayerEventListener : Player.EventListener {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
println("xxxxx onPlayerStateChanged")
}
override fun onPlayerError(error: ExoPlaybackException) {
if (error.type == ExoPlaybackException.TYPE_SOURCE) {
val cause: IOException = error.sourceException
if (cause is HttpDataSource.HttpDataSourceException) {
val httpError: HttpDataSource.HttpDataSourceException = cause
val dataSpec = httpError.dataSpec
if (httpError is HttpDataSource.InvalidResponseCodeException) {
// Cast to InvalidResponseCodeException and retrieve the response code,
// message and headers.
} else {
// Try calling httpError.getCause() to retrieve the underlying cause,
// although note that it may be null.
}
}
}
println("xxxxxxxxxx 发生播放异常")
}
override fun onTracksChanged(
trackGroups: TrackGroupArray,
trackSelections: TrackSelectionArray
) {
println("xxxxx onTracksChanged")
}
}
@SuppressLint("SourceLockedOrientationActivity")
override fun onStart() {
super.onStart()
//初始化player
initPlayer()
//让player_view准备好
player_view?.onResume()
}
private fun releasePlayer() {
if (player != null) {
player!!.release()
player = null
trackSelector = null
}
}
override fun onDestroy() {
super.onDestroy()
releaseAdsLoader()
releasePlayer()
}