Add local video playback
parent
ce3ee760d0
commit
403e4404a7
|
@ -13,8 +13,6 @@ android {
|
|||
targetSdk 33
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -32,16 +30,18 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
def mediaVersion = "1.0.1"
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.core:core-ktx:1.10.1'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.9.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.5.3'
|
||||
implementation 'androidx.navigation:navigation-ui:2.5.3'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.6'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
implementation "androidx.media3:media3-exoplayer:$mediaVersion"
|
||||
implementation "androidx.media3:media3-ui:$mediaVersion"
|
||||
implementation "androidx.media3:media3-exoplayer-dash:$mediaVersion"
|
||||
}
|
|
@ -1,21 +1,36 @@
|
|||
package gallery.memories
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.common.util.Util
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import gallery.memories.databinding.ActivityMainBinding
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
@UnstableApi class MainActivity : AppCompatActivity() {
|
||||
private val binding by lazy(LazyThreadSafetyMode.NONE) {
|
||||
ActivityMainBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private lateinit var mNativeX: NativeX
|
||||
|
||||
private var player: ExoPlayer? = null
|
||||
private var playerUri: Uri? = null
|
||||
private var playerUid: String? = null
|
||||
private var playWhenReady = true
|
||||
private var mediaItemIndex = 0
|
||||
private var playbackPosition = 0L
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
// Initialize services
|
||||
|
@ -25,8 +40,35 @@ class MainActivity : AppCompatActivity() {
|
|||
initializeWebView()
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mNativeX.destroy()
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
if (playerUri != null && (Util.SDK_INT <= 23 || player == null)) {
|
||||
initializePlayer(playerUri!!, playerUid!!)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
if (Util.SDK_INT <= 23) {
|
||||
releasePlayer()
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onStop() {
|
||||
super.onStop()
|
||||
if (Util.SDK_INT > 23) {
|
||||
releasePlayer()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled", "ClickableViewAccessibility")
|
||||
private fun initializeWebView() {
|
||||
// Intercept local APIs
|
||||
binding.webview.webViewClient = object : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
||||
view.loadUrl(request.url.toString())
|
||||
|
@ -39,6 +81,15 @@ class MainActivity : AppCompatActivity() {
|
|||
} else null
|
||||
}
|
||||
}
|
||||
|
||||
// Pass through touch events
|
||||
binding.webview.setOnTouchListener { _, event ->
|
||||
if (player != null) {
|
||||
binding.videoView.dispatchTouchEvent(event)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
val webSettings = binding.webview.settings
|
||||
webSettings.javaScriptEnabled = true
|
||||
webSettings.javaScriptCanOpenWindowsAutomatically = true
|
||||
|
@ -49,11 +100,52 @@ class MainActivity : AppCompatActivity() {
|
|||
binding.webview.clearCache(true)
|
||||
binding.webview.addJavascriptInterface(mNativeX, "nativex")
|
||||
binding.webview.loadUrl("http://10.0.2.2:8035/index.php/apps/memories/")
|
||||
binding.webview.setBackgroundColor(0x00000000)
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mNativeX.destroy()
|
||||
fun initializePlayer(uri: Uri, uid: String) {
|
||||
if (player != null) {
|
||||
if (playerUid.equals(uid)) return
|
||||
player?.release()
|
||||
player = null
|
||||
}
|
||||
|
||||
playerUri = uri
|
||||
playerUid = uid
|
||||
|
||||
player = ExoPlayer.Builder(this)
|
||||
.build()
|
||||
.also { exoPlayer ->
|
||||
binding.videoView.player = exoPlayer
|
||||
binding.videoView.visibility = View.VISIBLE
|
||||
val mediaItem = MediaItem.fromUri(uri)
|
||||
exoPlayer.setMediaItems(listOf(mediaItem), mediaItemIndex, playbackPosition)
|
||||
exoPlayer.playWhenReady = playWhenReady
|
||||
exoPlayer.prepare()
|
||||
}
|
||||
}
|
||||
|
||||
fun destroyPlayer(uid: String) {
|
||||
if (playerUid.equals(uid)) {
|
||||
releasePlayer()
|
||||
|
||||
// Reset vars
|
||||
playWhenReady = true
|
||||
mediaItemIndex = 0
|
||||
playbackPosition = 0L
|
||||
playerUri = null
|
||||
playerUid = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun releasePlayer() {
|
||||
player?.let { exoPlayer ->
|
||||
playbackPosition = exoPlayer.currentPosition
|
||||
mediaItemIndex = exoPlayer.currentMediaItemIndex
|
||||
playWhenReady = exoPlayer.playWhenReady
|
||||
exoPlayer.release()
|
||||
}
|
||||
player = null
|
||||
binding.videoView.visibility = View.GONE
|
||||
}
|
||||
}
|
|
@ -9,14 +9,15 @@ import android.view.WindowInsetsController
|
|||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebResourceResponse
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import gallery.memories.mapper.SystemImage
|
||||
import gallery.memories.service.DownloadService
|
||||
import gallery.memories.service.ImageService
|
||||
import gallery.memories.service.TimelineQuery
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.net.URLDecoder
|
||||
|
||||
class NativeX(private val mActivity: AppCompatActivity) {
|
||||
@UnstableApi class NativeX(private val mActivity: MainActivity) {
|
||||
val TAG = "NativeX"
|
||||
|
||||
private val mImageService: ImageService = ImageService(mActivity)
|
||||
|
@ -99,6 +100,31 @@ class NativeX(private val mActivity: AppCompatActivity) {
|
|||
mDlService!!.queue(url, filename)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun playVideoLocal(fileId: String?) {
|
||||
if (fileId == null) return;
|
||||
|
||||
Thread {
|
||||
// Get URI of local video
|
||||
val videos = SystemImage.getByIds(mActivity, arrayListOf(fileId.toLong()))
|
||||
if (videos.isEmpty()) return@Thread
|
||||
val video = videos[0]
|
||||
|
||||
// Play with exoplayer
|
||||
mActivity.runOnUiThread {
|
||||
mActivity.initializePlayer(video.uri, fileId)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun destroyVideo(fileId: String?) {
|
||||
if (fileId == null) return;
|
||||
mActivity.runOnUiThread {
|
||||
mActivity.destroyPlayer(fileId)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun routerGet(path: String): WebResourceResponse {
|
||||
val parts = path.split("/").toTypedArray()
|
||||
|
|
|
@ -6,10 +6,18 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/video_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
Loading…
Reference in New Issue