diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 61a9130..fb7f4a8 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3eac69b..a750660 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -43,7 +43,7 @@
-
+
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..797acea
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 3b78ec8..8b30a6e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,7 +8,7 @@ android {
defaultConfig {
applicationId "com.potyvideo.andexoplayer"
- minSdkVersion 16
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/app/src/main/java/com/potyvideo/andexoplayer/MainActivityKotlin.kt b/app/src/main/java/com/potyvideo/andexoplayer/MainActivityKotlin.kt
index 26bb13a..3c05602 100644
--- a/app/src/main/java/com/potyvideo/andexoplayer/MainActivityKotlin.kt
+++ b/app/src/main/java/com/potyvideo/andexoplayer/MainActivityKotlin.kt
@@ -24,7 +24,7 @@ class MainActivityKotlin : AppCompatActivity(), AndExoPlayerListener, View.OnCli
andExoPlayerView = findViewById(R.id.andExoPlayerView)
- andExoPlayerView.setResizeMode(EnumResizeMode.FIT) // sync with attrs
+ andExoPlayerView.setResizeMode(EnumResizeMode.ZOOM) // sync with attrs
andExoPlayerView.setAndExoPlayerListener(this)
findViewById(R.id.local).setOnClickListener(this)
@@ -33,6 +33,9 @@ class MainActivityKotlin : AppCompatActivity(), AndExoPlayerListener, View.OnCli
findViewById(R.id.stream_dash).setOnClickListener(this)
findViewById(R.id.stream_mkv).setOnClickListener(this)
+ // starter stream
+ loadMP4Stream(PublicValues.TEST_URL_MP4_V3)
+
}
override fun onExoPlayerError(errorMessage: String?) {
@@ -44,7 +47,7 @@ class MainActivityKotlin : AppCompatActivity(), AndExoPlayerListener, View.OnCli
selectLocaleVideo()
}
R.id.stream_mp4 -> {
- loadMP4Stream(PublicValues.TEST_URL_MP4)
+ loadMP4Stream(PublicValues.TEST_URL_MP4_V3)
}
R.id.stream_hls -> {
loadHLSStream(PublicValues.TEST_URL_HLS)
@@ -85,7 +88,10 @@ class MainActivityKotlin : AppCompatActivity(), AndExoPlayerListener, View.OnCli
intent.type = "video/*"
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true)
intent.action = Intent.ACTION_GET_CONTENT
- startActivityForResult(Intent.createChooser(intent, "Select Video"), PublicValues.request_code_select_video)
+ startActivityForResult(
+ Intent.createChooser(intent, "Select Video"),
+ PublicValues.request_code_select_video
+ )
}
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 582c409..8b515ee 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -10,11 +10,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:andexo_aspect_ratio="aspect_16_9"
- app:andexo_full_screen="true"
app:andexo_loop="finite"
app:andexo_play_when_ready="true"
app:andexo_resize_mode="Fit"
- app:andexo_show_controller="true" />
+ app:andexo_show_controller="true"
+ app:andexo_show_full_screen="true" />
+ android:layout_weight="1"
+ app:andexo_show_controller="true"
+ app:andexo_show_full_screen="true" />
{
+ enterFullScreen.visibility = GONE
+ exitFullScreen.visibility = VISIBLE
+ }
+ EnumScreenMode.MINIMISE -> {
+ enterFullScreen.visibility = VISIBLE
+ exitFullScreen.visibility = GONE
+ }
+ else -> {
+ enterFullScreen.visibility = VISIBLE
+ exitFullScreen.visibility = GONE
+ }
+ }
+ }
+
+ protected fun showSystemUI() {
+ playerView.systemUiVisibility = (SYSTEM_UI_FLAG_LOW_PROFILE
+ or SYSTEM_UI_FLAG_IMMERSIVE
+ or SYSTEM_UI_FLAG_FULLSCREEN
+ or SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ or SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ or SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ or SYSTEM_UI_FLAG_HIDE_NAVIGATION)
+ }
+
+ protected fun hideSystemUI() {
+ playerView.systemUiVisibility = (SYSTEM_UI_FLAG_LOW_PROFILE
+ or SYSTEM_UI_FLAG_LAYOUT_STABLE)
+ }
+
}
diff --git a/library/src/main/java/com/potyvideo/library/AndExoPlayerView.kt b/library/src/main/java/com/potyvideo/library/AndExoPlayerView.kt
index 957d0a7..0d16039 100644
--- a/library/src/main/java/com/potyvideo/library/AndExoPlayerView.kt
+++ b/library/src/main/java/com/potyvideo/library/AndExoPlayerView.kt
@@ -1,6 +1,10 @@
package com.potyvideo.library
+import android.app.Activity
import android.content.Context
+import android.content.ContextWrapper
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration
import android.content.res.TypedArray
import android.util.AttributeSet
import android.view.View
@@ -11,19 +15,18 @@ import com.google.android.exoplayer2.source.TrackGroupArray
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.util.MimeTypes
-import com.potyvideo.library.globalEnums.EnumAspectRatio
-import com.potyvideo.library.globalEnums.EnumMute
-import com.potyvideo.library.globalEnums.EnumRepeatMode
-import com.potyvideo.library.globalEnums.EnumResizeMode
+import com.potyvideo.library.globalEnums.*
import com.potyvideo.library.globalInterfaces.AndExoPlayerListener
import com.potyvideo.library.utils.DoubleClick
import com.potyvideo.library.utils.DoubleClickListener
import com.potyvideo.library.utils.PublicFunctions
import com.potyvideo.library.utils.PublicValues
+
class AndExoPlayerView(
- context: Context,
- attributeSet: AttributeSet) : AndExoPlayerRoot(context, attributeSet), Player.EventListener {
+ context: Context,
+ attributeSet: AttributeSet
+) : AndExoPlayerRoot(context, attributeSet), Player.EventListener {
private lateinit var currSource: String
@@ -33,7 +36,6 @@ class AndExoPlayerView(
private var playbackPosition: Long = 0
private var currentWindow: Int = 0
private var currVolume: Float = 0f
- private var showControllers: Boolean = true
override var customClickListener: DoubleClick
get() = DoubleClick(object : DoubleClickListener {
@@ -49,6 +51,12 @@ class AndExoPlayerView(
unMute.id -> {
mutePlayer()
}
+ enterFullScreen.id -> {
+ setScreenMode(EnumScreenMode.FULLSCREEN)
+ }
+ exitFullScreen.id -> {
+ setScreenMode(EnumScreenMode.MINIMISE)
+ }
}
}
@@ -74,29 +82,58 @@ class AndExoPlayerView(
attributeSet.let {
- val typedArray: TypedArray = context.obtainStyledAttributes(it, R.styleable.AndExoPlayerView)
+ val typedArray: TypedArray =
+ context.obtainStyledAttributes(it, R.styleable.AndExoPlayerView)
if (typedArray.hasValue(R.styleable.AndExoPlayerView_andexo_aspect_ratio)) {
- val aspectRatio = typedArray.getInteger(R.styleable.AndExoPlayerView_andexo_aspect_ratio, EnumAspectRatio.ASPECT_16_9.value)
+ val aspectRatio = typedArray.getInteger(
+ R.styleable.AndExoPlayerView_andexo_aspect_ratio,
+ EnumAspectRatio.ASPECT_16_9.value
+ )
setAspectRatio(EnumAspectRatio[aspectRatio])
}
if (typedArray.hasValue(R.styleable.AndExoPlayerView_andexo_resize_mode)) {
- val resizeMode: Int = typedArray.getInteger(R.styleable.AndExoPlayerView_andexo_resize_mode, EnumResizeMode.FILL.value)
+ val resizeMode: Int = typedArray.getInteger(
+ R.styleable.AndExoPlayerView_andexo_resize_mode,
+ EnumResizeMode.FILL.value
+ )
setResizeMode(EnumResizeMode[resizeMode])
}
if (typedArray.hasValue(R.styleable.AndExoPlayerView_andexo_play_when_ready)) {
- setPlayWhenReady(typedArray.getBoolean(R.styleable.AndExoPlayerView_andexo_play_when_ready, false))
+ setPlayWhenReady(
+ typedArray.getBoolean(
+ R.styleable.AndExoPlayerView_andexo_play_when_ready,
+ false
+ )
+ )
}
if (typedArray.hasValue(R.styleable.AndExoPlayerView_andexo_mute)) {
- val muteValue = typedArray.getInteger(R.styleable.AndExoPlayerView_andexo_mute, EnumMute.UNMUTE.value)
+ val muteValue = typedArray.getInteger(
+ R.styleable.AndExoPlayerView_andexo_mute,
+ EnumMute.UNMUTE.value
+ )
setMute(EnumMute[muteValue])
}
if (typedArray.hasValue(R.styleable.AndExoPlayerView_andexo_show_controller)) {
+ setShowControllers(
+ typedArray.getBoolean(
+ R.styleable.AndExoPlayerView_andexo_show_controller,
+ true
+ )
+ )
+ }
+ if (typedArray.hasValue(R.styleable.AndExoPlayerView_andexo_show_full_screen)) {
+ setShowFullScreenButton(
+ typedArray.getBoolean(
+ R.styleable.AndExoPlayerView_andexo_show_full_screen,
+ true
+ )
+ )
}
typedArray.recycle()
@@ -106,7 +143,10 @@ class AndExoPlayerView(
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters) {
}
- override fun onTracksChanged(trackGroups: TrackGroupArray, trackSelections: TrackSelectionArray) {
+ override fun onTracksChanged(
+ trackGroups: TrackGroupArray,
+ trackSelections: TrackSelectionArray
+ ) {
}
override fun onPlayerError(error: ExoPlaybackException) {
@@ -161,54 +201,64 @@ class AndExoPlayerView(
player.prepare()
}
- private fun buildMediaItem(source: String): MediaItem {
+ private fun buildMediaItem(source: String, extraHeaders: HashMap): MediaItem {
return when (PublicFunctions.getMimeType(source)) {
- PublicValues.KEY_MP4 -> buildMediaItemMP4(source)
- PublicValues.KEY_M3U8 -> buildMediaHLS(source)
- PublicValues.KEY_MP3 -> buildMediaItemMP4(source)
+ PublicValues.KEY_MP4 -> buildMediaItemMP4(source, extraHeaders)
+ PublicValues.KEY_M3U8 -> buildMediaHLS(source, extraHeaders)
+ PublicValues.KEY_MP3 -> buildMediaItemMP4(source, extraHeaders)
- else -> buildMediaGlobal(source)
+ else -> buildMediaGlobal(source, extraHeaders)
}
}
- private fun buildMediaItemMP4(source: String): MediaItem {
+ private fun buildMediaItemMP4(
+ source: String,
+ extraHeaders: HashMap
+ ): MediaItem {
return MediaItem.Builder()
- .setUri(source)
- .setMimeType(MimeTypes.APPLICATION_MP4)
- .build()
+ .setUri(source)
+ .setMimeType(MimeTypes.APPLICATION_MP4)
+ .setDrmLicenseRequestHeaders(extraHeaders)
+ .build()
}
- private fun buildMediaHLS(source: String): MediaItem {
+ private fun buildMediaHLS(source: String, extraHeaders: HashMap): MediaItem {
return MediaItem.Builder()
- .setUri(source)
- .setMimeType(MimeTypes.APPLICATION_M3U8)
- .build()
+ .setUri(source)
+ .setMimeType(MimeTypes.APPLICATION_M3U8)
+ .setDrmLicenseRequestHeaders(extraHeaders)
+ .build()
}
- private fun buildMediaDash(source: String): MediaItem {
+ private fun buildMediaDash(source: String, extraHeaders: HashMap): MediaItem {
return MediaItem.Builder()
- .setUri(source)
- .setMimeType(MimeTypes.APPLICATION_MPD)
- .build()
+ .setUri(source)
+ .setMimeType(MimeTypes.APPLICATION_MPD)
+ .setDrmLicenseRequestHeaders(extraHeaders)
+ .build()
}
- private fun buildMediaGlobal(source: String): MediaItem {
+ private fun buildMediaGlobal(source: String, extraHeaders: HashMap): MediaItem {
return MediaItem.Builder()
- .setUri(source)
- .build()
+ .setUri(source)
+ .setDrmLicenseRequestHeaders(extraHeaders)
+ .build()
}
fun setAndExoPlayerListener(andExoPlayerListener: AndExoPlayerListener) {
this.andExoPlayerListener = andExoPlayerListener
}
- fun setSource(source: String) {
+ fun setSource(
+ source: String,
+ extraHeaders: HashMap = hashMapOf()
+ ) {
currSource = source
- val mediaItem = buildMediaItem(source)
+ val mediaItem = buildMediaItem(source, extraHeaders)
playerView.player = player
player.playWhenReady = true
@@ -288,19 +338,28 @@ class AndExoPlayerView(
this.currAspectRatio = aspectRatio
val value = PublicFunctions.getScreenWidth()
when (aspectRatio) {
- EnumAspectRatio.ASPECT_1_1 -> playerView.layoutParams = FrameLayout.LayoutParams(value, value)
- EnumAspectRatio.ASPECT_4_3 -> playerView.layoutParams = FrameLayout.LayoutParams(value, 3 * value / 4)
- EnumAspectRatio.ASPECT_16_9 -> playerView.layoutParams = FrameLayout.LayoutParams(value, 9 * value / 16)
- EnumAspectRatio.ASPECT_MATCH -> playerView.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
+ EnumAspectRatio.ASPECT_1_1 -> playerView.layoutParams =
+ FrameLayout.LayoutParams(value, value)
+ EnumAspectRatio.ASPECT_4_3 -> playerView.layoutParams =
+ FrameLayout.LayoutParams(value, 3 * value / 4)
+ EnumAspectRatio.ASPECT_16_9 -> playerView.layoutParams =
+ FrameLayout.LayoutParams(value, 9 * value / 16)
+ EnumAspectRatio.ASPECT_MATCH -> playerView.layoutParams = FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT
+ )
EnumAspectRatio.ASPECT_MP3 -> {
playerView.controllerShowTimeoutMs = 0
playerView.controllerHideOnTouch = false
- val mp3Height = context.resources.getDimensionPixelSize(R.dimen.player_controller_base_height)
- playerView.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mp3Height)
+ val mp3Height =
+ context.resources.getDimensionPixelSize(R.dimen.player_controller_base_height)
+ playerView.layoutParams =
+ FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mp3Height)
}
EnumAspectRatio.UNDEFINE -> {
val baseHeight = resources.getDimension(R.dimen.player_base_height).toInt()
- playerView.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, baseHeight)
+ playerView.layoutParams =
+ FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, baseHeight)
}
}
}
@@ -334,4 +393,60 @@ class AndExoPlayerView(
player.playbackState
}
+ fun setScreenMode(screenMode: EnumScreenMode = EnumScreenMode.MINIMISE) {
+
+ when (screenMode) {
+ EnumScreenMode.FULLSCREEN -> {
+ getActivity()?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ }
+ EnumScreenMode.MINIMISE -> {
+ getActivity()?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+ }
+ else -> {
+ getActivity()?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+ }
+ }
+
+ currScreenMode = screenMode
+ setShowScreenModeButton(currScreenMode)
+ }
+
+ fun getActivity(): Activity? {
+ var context = context
+ while (context is ContextWrapper) {
+ if (context is Activity) {
+ return context
+ }
+ context = context.baseContext
+ }
+ return null
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ releasePlayer()
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration?) {
+ super.onConfigurationChanged(newConfig)
+ // Checking the orientation of the screen
+ // Checking the orientation of the screen
+ if (newConfig!!.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ // First Hide other objects (list-view or recyclerview), better hide them using Gone.
+ hideSystemUI()
+ val params = playerView.layoutParams as FrameLayout.LayoutParams
+ params.width = ViewGroup.LayoutParams.MATCH_PARENT
+ params.height = ViewGroup.LayoutParams.MATCH_PARENT
+ playerView.layoutParams = params
+ } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
+ // un hide your objects here.
+ showSystemUI()
+ setAspectRatio(currAspectRatio)
+ }
+ }
+
}
\ No newline at end of file
diff --git a/library/src/main/java/com/potyvideo/library/globalEnums/EnumScreenMode.kt b/library/src/main/java/com/potyvideo/library/globalEnums/EnumScreenMode.kt
new file mode 100644
index 0000000..a9b336e
--- /dev/null
+++ b/library/src/main/java/com/potyvideo/library/globalEnums/EnumScreenMode.kt
@@ -0,0 +1,37 @@
+package com.potyvideo.library.globalEnums
+
+enum class EnumScreenMode(var valueStr: String, val value: Int) {
+
+ UNDEFINE("UNDEFINE", -1),
+ FULLSCREEN("fullscreen", 1),
+ MINIMISE("minimise", 2);
+
+ companion object {
+
+ operator fun get(value: String): EnumScreenMode {
+ if (value == null) {
+ return UNDEFINE
+ }
+ val `arr$` = values()
+ for (`val` in `arr$`) {
+ if (`val`.valueStr.equals(value.trim { it <= ' ' }, ignoreCase = true)) {
+ return `val`
+ }
+ }
+ return UNDEFINE
+ }
+
+ operator fun get(value: Int): EnumScreenMode {
+ if (value == null) {
+ return UNDEFINE
+ }
+ val `arr$` = values()
+ for (`val` in `arr$`) {
+ if (`val`.value === value) {
+ return `val`
+ }
+ }
+ return UNDEFINE
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/res/layout/video_player_exo_controllers_kotlin.xml b/library/src/main/res/layout/video_player_exo_controllers_kotlin.xml
index ebab84f..8e84acf 100644
--- a/library/src/main/res/layout/video_player_exo_controllers_kotlin.xml
+++ b/library/src/main/res/layout/video_player_exo_controllers_kotlin.xml
@@ -132,10 +132,8 @@
android:id="@+id/container_audio"
android:layout_width="40dp"
android:layout_height="40dp"
- android:layout_alignParentStart="true"
- android:layout_alignParentLeft="true"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@id/container_setting"
+ app:layout_constraintEnd_toStartOf="@id/container_fullscreen"
app:layout_constraintTop_toTopOf="parent">
+
+
+
+
+
+
+
+
+
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
index dc73b3c..c26d48a 100644
--- a/library/src/main/res/values/attrs.xml
+++ b/library/src/main/res/values/attrs.xml
@@ -6,7 +6,7 @@
-
+