feat:优化视频播放功能,包括下载、播放、暂停和停止视频。

This commit is contained in:
LUX-Timber 2024-04-25 11:14:05 +08:00
parent db59e63779
commit be40211f41
5 changed files with 183 additions and 64 deletions

View File

@ -4,6 +4,17 @@
<value>
<entry key="app">
<State>
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="D:\Android\.android\avd\Pixel_7_API_34.avd" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
@ -15,7 +26,7 @@
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-04-24T08:47:36.516818Z" />
<timeTargetWasSelectedWithDropDown value="2024-04-25T02:40:10.447031700Z" />
</State>
</entry>
</value>

View File

@ -1,9 +1,15 @@
package com.timber.soft.mylivewallpaper.tools
import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.View
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.google.gson.Gson
import com.jakewharton.rxbinding4.view.clicks
import com.timber.soft.mylivewallpaper.data.WallpaperData
@ -14,13 +20,11 @@ import java.util.concurrent.TimeUnit
object AppTools {
private const val DIR_FILE_NAME = "tep"
private const val DIR_DOWNLOAD = "download"
fun View.throttleClicks(time: Long = 1000, block: (View) -> Unit) {
this.clicks().throttleFirst(time, TimeUnit.MILLISECONDS).subscribe { block(this) }
}
fun onMain(operation: () -> Unit) = Handler(Looper.getMainLooper()).post(operation)
fun parseJsonFile(jsonInputStream: InputStream): List<WallpaperData> {
val reader = InputStreamReader(jsonInputStream)
@ -28,39 +32,28 @@ object AppTools {
return Gson().fromJson(jsonString, Array<WallpaperData>::class.java).toMutableList()
}
private fun getDownloadDirectory(): String {
return getDefaultDirectory() + File.separator + DIR_DOWNLOAD
}
private fun getDefaultDirectory(): String {
var dirName = ""
if (MyApplication.appContext.getExternalFilesDir(DIR_FILE_NAME) != null) {//外部存储可用
if (Build.VERSION.SDK_INT >= 29) {
dirName = MyApplication.appContext.getExternalFilesDir(DIR_FILE_NAME)!!.path
} else if (Build.VERSION.SDK_INT < 29) {
dirName = MyApplication.appContext.getExternalFilesDir(DIR_FILE_NAME)!!.absolutePath
fun glideDownload(context: Context, url: String, downloadCall: (File?) -> Unit) {
Glide.with(context).downloadOnly().load(url).addListener(object : RequestListener<File> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<File>?,
isFirstResource: Boolean
): Boolean {
downloadCall.invoke(null)
return false
}
} else {
dirName = MyApplication.appContext.filesDir.absolutePath
}
return dirName
override fun onResourceReady(
resource: File?,
model: Any?,
target: Target<File>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
downloadCall.invoke(resource)
return false
}
}).preload()
}
fun getFileName(url: String): String {
return url.substring(url.lastIndexOf("/") + 1)
}
fun getFilePath(url: String): String {
return getDownloadDirectory() + File.separator + getFileName(url)
}
fun getFile(url: String): File {
return File(getFilePath(url))
}
fun isExist(url: String): Boolean {
return File(getFilePath(url)).exists()
}
}

View File

@ -2,10 +2,13 @@ package com.timber.soft.mylivewallpaper.ui.activity
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.media.MediaPlayer
import android.os.Build
import android.util.Log
import android.view.SurfaceHolder
import android.view.View
import android.widget.Toast
import androidx.core.view.isVisible
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
@ -13,11 +16,12 @@ import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.timber.soft.mylivewallpaper.R
import com.timber.soft.mylivewallpaper.data.AppDatabase
import com.timber.soft.mylivewallpaper.data.WallpaperData
import com.timber.soft.mylivewallpaper.databinding.ActivityDetailsBinding
import com.timber.soft.mylivewallpaper.tools.AppFinalString
import com.timber.soft.mylivewallpaper.tools.AppTools.isExist
import com.timber.soft.mylivewallpaper.tools.AppTools.glideDownload
import com.timber.soft.mylivewallpaper.ui.customerView.DownLoadDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -28,6 +32,9 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
private lateinit var binding: ActivityDetailsBinding
private lateinit var wallpaperData: WallpaperData
private lateinit var downDialog: DownLoadDialog
private var mediaPlayer: MediaPlayer? = null
private lateinit var videoUrl: String
private var isDownload = false
override fun getActivityContentView(): View {
binding = ActivityDetailsBinding.inflate(layoutInflater)
return binding.root
@ -85,6 +92,7 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
binding.detailsCollect.setOnClickListener(this)
binding.detailsSet.setOnClickListener(this)
binding.detailsPlayButton.setOnClickListener(this)
binding.detailsVideoBack.setOnClickListener(this)
binding.detailsCollect.isSelected = wallpaperData.isCollect
}
@ -103,15 +111,32 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
}
binding.detailsPlayButton -> {
if (isExist()) {
if (isDownload) {
binding.detailsPlayButton.isVisible = false
playVideo()
} else {
binding.detailsPlayButton.isVisible = false
binding.detailsProgressbar.isVisible = true
showDownloadDialog()
}
}
binding.detailsVideoBack -> {
stopVideo()
}
}
}
private fun stopVideo() {
try {
mediaPlayer?.stop()
} catch (e: Exception) {
e.printStackTrace()
}
binding.detailsFlPlay.isVisible = false
binding.detailsPlayButton.isVisible = true
}
private fun setCollect() {
if (!binding.detailsCollect.isSelected) {
binding.detailsCollect.isSelected = !binding.detailsCollect.isSelected
@ -138,15 +163,119 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
}
private fun showDownloadDialog() {
Log.e("file_play", "file is null!")
wallpaperData.preview.let {
glideDownload(this, it) { file ->
if (file == null) {
isDownload = false
Toast.makeText(
this@DetailActivity, "Sorry, the download failed.", Toast.LENGTH_SHORT
).show()
binding.detailsProgressbar.isVisible = false
} else {
binding.detailsProgressbar.isVisible = false
file.absolutePath.let { path ->
// mediaPlayer.setDataSource(path)
// mediaPlayer.prepare()
videoUrl = path
isDownload = true
CoroutineScope(Dispatchers.IO).launch {
AppDatabase.dataBase.getWallpaperDao().insertData(wallpaperData.apply {
downloadUrl = path
})
}
playVideo()
}
}
}
}
}
private fun playVideo() {
Log.e("file_play", "file is exist!")
try {
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer()
binding.detailsSurfaceVideo.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
try {
mediaPlayer?.reset()
mediaPlayer?.setDataSource(videoUrl)
mediaPlayer?.setDisplay(holder)
mediaPlayer?.isLooping = true
mediaPlayer?.setVolume(0f, 0f)
mediaPlayer?.setOnPreparedListener {
try {
it.start()
} catch (e: Exception) {
e.printStackTrace()
}
}
mediaPlayer?.prepareAsync()
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun surfaceChanged(
holder: SurfaceHolder,
format: Int,
width: Int,
height: Int
) {
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
}
})
} else {
mediaPlayer?.reset()
mediaPlayer?.setDataSource(videoUrl)
mediaPlayer?.isLooping = true
mediaPlayer?.setVolume(0f, 0f)
mediaPlayer?.prepare()
}
binding.detailsFlPlay.isVisible = true
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun isExist(): Boolean {
return isExist(wallpaperData.preview)
override fun onDestroy() {
super.onDestroy()
mediaPlayer?.stop()
mediaPlayer?.release()
mediaPlayer = null
}
override fun onBackPressed() {
super.onBackPressed()
if (binding.detailsFlPlay.isVisible) {
stopVideo()
return
}
finish()
}
override fun onPause() {
super.onPause()
if (binding.detailsFlPlay.isVisible) {
try {
stopVideo()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun onResume() {
super.onResume()
if (binding.detailsFlPlay.isVisible) {
try {
mediaPlayer?.start()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}

View File

@ -10,23 +10,11 @@ import com.timber.soft.mylivewallpaper.databinding.ViewDownloaddialogBinding
import com.timber.soft.mylivewallpaper.tools.AppTools.throttleClicks
import java.util.concurrent.atomic.AtomicInteger
/**
* TODO : no implement
*/
class DownLoadDialog(
private val context: Context,
private val url: String,
private val title: String = "",
init: DownLoadDialog.() -> Unit
) : Dialog(context, R.style.DownLoadDialog) {
private lateinit var binding: ViewDownloaddialogBinding
var onDownloadSuccess: (() -> Unit)? = null
var onDownloadFailed: (() -> Unit)? = null
private var mCount: AtomicInteger = AtomicInteger(0)
init {
init()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -43,13 +31,10 @@ class DownLoadDialog(
}
private fun startDownload() {
binding.dialogProgressbar.progress = 0f
}
private fun initView() {
if (!TextUtils.isEmpty(title)) {
binding.dialogText.text = title
}
binding.dialogIvClose.throttleClicks {
dismiss()
}

View File

@ -94,14 +94,15 @@
android:visibility="visible" />
<ImageView
android:id="@+id/details_ivClose"
android:id="@+id/details_video_back"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_gravity="end"
android:layout_gravity="start"
android:layout_marginStart="24dp"
android:layout_marginTop="46dp"
android:layout_marginEnd="24dp"
android:src="@drawable/svg_back"
android:visibility="visible" />
android:background="@drawable/shape_circular"
android:padding="12dp"
android:src="@drawable/svg_back" />
</FrameLayout>