video: support direct playback
parent
79aecab377
commit
e5745d0c05
|
@ -14,12 +14,15 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.PlaybackException
|
||||||
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.common.util.Util
|
import androidx.media3.common.util.Util
|
||||||
import androidx.media3.datasource.DefaultDataSource
|
import androidx.media3.datasource.DefaultDataSource
|
||||||
import androidx.media3.datasource.DefaultHttpDataSource
|
import androidx.media3.datasource.DefaultHttpDataSource
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.hls.HlsMediaSource
|
import androidx.media3.exoplayer.hls.HlsMediaSource
|
||||||
|
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||||
import gallery.memories.databinding.ActivityMainBinding
|
import gallery.memories.databinding.ActivityMainBinding
|
||||||
|
|
||||||
@UnstableApi class MainActivity : AppCompatActivity() {
|
@UnstableApi class MainActivity : AppCompatActivity() {
|
||||||
|
@ -30,7 +33,7 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
private lateinit var nativex: NativeX
|
private lateinit var nativex: NativeX
|
||||||
|
|
||||||
private var player: ExoPlayer? = null
|
private var player: ExoPlayer? = null
|
||||||
private var playerUri: Uri? = null
|
private var playerUris: Array<Uri>? = null
|
||||||
private var playerUid: String? = null
|
private var playerUid: String? = null
|
||||||
private var playWhenReady = true
|
private var playWhenReady = true
|
||||||
private var mediaItemIndex = 0
|
private var mediaItemIndex = 0
|
||||||
|
@ -72,8 +75,8 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
|
|
||||||
public override fun onResume() {
|
public override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (playerUri != null && (Util.SDK_INT <= 23 || player == null)) {
|
if (playerUris != null && (Util.SDK_INT <= 23 || player == null)) {
|
||||||
initializePlayer(playerUri!!, playerUid!!)
|
initializePlayer(playerUris!!, playerUid!!)
|
||||||
}
|
}
|
||||||
if (mNeedRefresh) {
|
if (mNeedRefresh) {
|
||||||
refreshTimeline(true)
|
refreshTimeline(true)
|
||||||
|
@ -212,7 +215,7 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
requestPermissionLauncher.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE)
|
requestPermissionLauncher.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializePlayer(uri: Uri, uid: String) {
|
fun initializePlayer(uris: Array<Uri>, uid: String) {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
if (playerUid.equals(uid)) return
|
if (playerUid.equals(uid)) return
|
||||||
player?.release()
|
player?.release()
|
||||||
|
@ -220,20 +223,9 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent re-creating
|
// Prevent re-creating
|
||||||
playerUri = uri
|
playerUris = uris
|
||||||
playerUid = uid
|
playerUid = uid
|
||||||
|
|
||||||
// Add cookies from webview to data source
|
|
||||||
val cookies = CookieManager.getInstance().getCookie(uri.toString())
|
|
||||||
val httpDataSourceFactory =
|
|
||||||
DefaultHttpDataSource.Factory()
|
|
||||||
.setDefaultRequestProperties(mapOf("cookie" to cookies))
|
|
||||||
.setAllowCrossProtocolRedirects(true)
|
|
||||||
val dataSourceFactory = DefaultDataSource.Factory(this, httpDataSourceFactory)
|
|
||||||
|
|
||||||
// Create media item from local or remote uri
|
|
||||||
val mediaItem = MediaItem.fromUri(uri)
|
|
||||||
|
|
||||||
// Build exoplayer
|
// Build exoplayer
|
||||||
player = ExoPlayer.Builder(this)
|
player = ExoPlayer.Builder(this)
|
||||||
.build()
|
.build()
|
||||||
|
@ -244,14 +236,44 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
binding.videoView.setShowNextButton(false)
|
binding.videoView.setShowNextButton(false)
|
||||||
binding.videoView.setShowPreviousButton(false)
|
binding.videoView.setShowPreviousButton(false)
|
||||||
|
|
||||||
// Check if HLS source from URI (contains .m3u8 anywhere)
|
for (uri in uris) {
|
||||||
if (uri.toString().contains(".m3u8")) {
|
// Create media item from URI
|
||||||
exoPlayer.addMediaSource(HlsMediaSource.Factory(dataSourceFactory)
|
val mediaItem = MediaItem.fromUri(uri)
|
||||||
.createMediaSource(mediaItem))
|
|
||||||
} else {
|
// Check if remote or local URI
|
||||||
exoPlayer.setMediaItems(listOf(mediaItem), mediaItemIndex, playbackPosition)
|
if (uri.toString().contains("http")) {
|
||||||
|
// Add cookies from webview to data source
|
||||||
|
val cookies = CookieManager.getInstance().getCookie(uri.toString())
|
||||||
|
val httpDataSourceFactory =
|
||||||
|
DefaultHttpDataSource.Factory()
|
||||||
|
.setDefaultRequestProperties(mapOf("cookie" to cookies))
|
||||||
|
.setAllowCrossProtocolRedirects(true)
|
||||||
|
val dataSourceFactory = DefaultDataSource.Factory(this, httpDataSourceFactory)
|
||||||
|
|
||||||
|
// Check if HLS source from URI (contains .m3u8 anywhere)
|
||||||
|
exoPlayer.addMediaSource(
|
||||||
|
if (uri.toString().contains(".m3u8")) {
|
||||||
|
HlsMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(mediaItem)
|
||||||
|
} else {
|
||||||
|
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(mediaItem)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
exoPlayer.setMediaItems(listOf(mediaItem), mediaItemIndex, playbackPosition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Catch errors and fall back to other sources
|
||||||
|
exoPlayer.addListener(object : Player.Listener {
|
||||||
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
|
exoPlayer.seekToNext()
|
||||||
|
exoPlayer.playWhenReady = true
|
||||||
|
exoPlayer.play()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Start the player
|
// Start the player
|
||||||
exoPlayer.playWhenReady = playWhenReady
|
exoPlayer.playWhenReady = playWhenReady
|
||||||
exoPlayer.prepare()
|
exoPlayer.prepare()
|
||||||
|
@ -266,7 +288,7 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
playWhenReady = true
|
playWhenReady = true
|
||||||
mediaItemIndex = 0
|
mediaItemIndex = 0
|
||||||
playbackPosition = 0L
|
playbackPosition = 0L
|
||||||
playerUri = null
|
playerUris = null
|
||||||
playerUid = null
|
playerUid = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import gallery.memories.service.AccountService
|
||||||
import gallery.memories.service.DownloadService
|
import gallery.memories.service.DownloadService
|
||||||
import gallery.memories.service.ImageService
|
import gallery.memories.service.ImageService
|
||||||
import gallery.memories.service.TimelineQuery
|
import gallery.memories.service.TimelineQuery
|
||||||
|
import org.json.JSONArray
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
|
||||||
|
@ -155,16 +156,21 @@ import java.net.URLDecoder
|
||||||
|
|
||||||
// Play with exoplayer
|
// Play with exoplayer
|
||||||
mCtx.runOnUiThread {
|
mCtx.runOnUiThread {
|
||||||
mCtx.initializePlayer(video.uri, fileId)
|
mCtx.initializePlayer(arrayOf(video.uri), fileId)
|
||||||
}
|
}
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun playVideoHls(fileId: String?, url: String?) {
|
fun playVideoRemote(fileId: String?, urlsArray: String?) {
|
||||||
if (fileId == null || url == null) return
|
if (fileId == null || urlsArray == null) return
|
||||||
|
val urls = JSONArray(urlsArray)
|
||||||
|
val list = Array(urls.length()) {
|
||||||
|
Uri.parse(urls.getString(it))
|
||||||
|
}
|
||||||
|
|
||||||
mCtx.runOnUiThread {
|
mCtx.runOnUiThread {
|
||||||
mCtx.initializePlayer(Uri.parse(url), fileId)
|
mCtx.initializePlayer(list, fileId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue