feat:优化视频播放功能,包括下载、播放、暂停和停止视频。
This commit is contained in:
parent
db59e63779
commit
be40211f41
13
.idea/deploymentTargetDropDown.xml
generated
13
.idea/deploymentTargetDropDown.xml
generated
@ -4,6 +4,17 @@
|
|||||||
<value>
|
<value>
|
||||||
<entry key="app">
|
<entry key="app">
|
||||||
<State>
|
<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>
|
<targetSelectedWithDropDown>
|
||||||
<Target>
|
<Target>
|
||||||
<type value="QUICK_BOOT_TARGET" />
|
<type value="QUICK_BOOT_TARGET" />
|
||||||
@ -15,7 +26,7 @@
|
|||||||
</deviceKey>
|
</deviceKey>
|
||||||
</Target>
|
</Target>
|
||||||
</targetSelectedWithDropDown>
|
</targetSelectedWithDropDown>
|
||||||
<timeTargetWasSelectedWithDropDown value="2024-04-24T08:47:36.516818Z" />
|
<timeTargetWasSelectedWithDropDown value="2024-04-25T02:40:10.447031700Z" />
|
||||||
</State>
|
</State>
|
||||||
</entry>
|
</entry>
|
||||||
</value>
|
</value>
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
package com.timber.soft.mylivewallpaper.tools
|
package com.timber.soft.mylivewallpaper.tools
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.View
|
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.google.gson.Gson
|
||||||
import com.jakewharton.rxbinding4.view.clicks
|
import com.jakewharton.rxbinding4.view.clicks
|
||||||
import com.timber.soft.mylivewallpaper.data.WallpaperData
|
import com.timber.soft.mylivewallpaper.data.WallpaperData
|
||||||
@ -14,13 +20,11 @@ import java.util.concurrent.TimeUnit
|
|||||||
|
|
||||||
object AppTools {
|
object AppTools {
|
||||||
|
|
||||||
private const val DIR_FILE_NAME = "tep"
|
|
||||||
private const val DIR_DOWNLOAD = "download"
|
|
||||||
|
|
||||||
fun View.throttleClicks(time: Long = 1000, block: (View) -> Unit) {
|
fun View.throttleClicks(time: Long = 1000, block: (View) -> Unit) {
|
||||||
this.clicks().throttleFirst(time, TimeUnit.MILLISECONDS).subscribe { block(this) }
|
this.clicks().throttleFirst(time, TimeUnit.MILLISECONDS).subscribe { block(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun onMain(operation: () -> Unit) = Handler(Looper.getMainLooper()).post(operation)
|
fun onMain(operation: () -> Unit) = Handler(Looper.getMainLooper()).post(operation)
|
||||||
fun parseJsonFile(jsonInputStream: InputStream): List<WallpaperData> {
|
fun parseJsonFile(jsonInputStream: InputStream): List<WallpaperData> {
|
||||||
val reader = InputStreamReader(jsonInputStream)
|
val reader = InputStreamReader(jsonInputStream)
|
||||||
@ -28,39 +32,28 @@ object AppTools {
|
|||||||
return Gson().fromJson(jsonString, Array<WallpaperData>::class.java).toMutableList()
|
return Gson().fromJson(jsonString, Array<WallpaperData>::class.java).toMutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDownloadDirectory(): String {
|
fun glideDownload(context: Context, url: String, downloadCall: (File?) -> Unit) {
|
||||||
return getDefaultDirectory() + File.separator + DIR_DOWNLOAD
|
Glide.with(context).downloadOnly().load(url).addListener(object : RequestListener<File> {
|
||||||
}
|
override fun onLoadFailed(
|
||||||
|
e: GlideException?,
|
||||||
private fun getDefaultDirectory(): String {
|
model: Any?,
|
||||||
var dirName = ""
|
target: Target<File>?,
|
||||||
if (MyApplication.appContext.getExternalFilesDir(DIR_FILE_NAME) != null) {//外部存储可用
|
isFirstResource: Boolean
|
||||||
if (Build.VERSION.SDK_INT >= 29) {
|
): Boolean {
|
||||||
dirName = MyApplication.appContext.getExternalFilesDir(DIR_FILE_NAME)!!.path
|
downloadCall.invoke(null)
|
||||||
} else if (Build.VERSION.SDK_INT < 29) {
|
return false
|
||||||
dirName = MyApplication.appContext.getExternalFilesDir(DIR_FILE_NAME)!!.absolutePath
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
dirName = MyApplication.appContext.filesDir.absolutePath
|
override fun onResourceReady(
|
||||||
}
|
resource: File?,
|
||||||
return dirName
|
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2,10 +2,13 @@ package com.timber.soft.mylivewallpaper.ui.activity
|
|||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.media.MediaPlayer
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.SurfaceHolder
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.DataSource
|
import com.bumptech.glide.load.DataSource
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
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.load.resource.drawable.DrawableTransitionOptions
|
||||||
import com.bumptech.glide.request.RequestListener
|
import com.bumptech.glide.request.RequestListener
|
||||||
import com.bumptech.glide.request.target.Target
|
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.AppDatabase
|
||||||
import com.timber.soft.mylivewallpaper.data.WallpaperData
|
import com.timber.soft.mylivewallpaper.data.WallpaperData
|
||||||
import com.timber.soft.mylivewallpaper.databinding.ActivityDetailsBinding
|
import com.timber.soft.mylivewallpaper.databinding.ActivityDetailsBinding
|
||||||
import com.timber.soft.mylivewallpaper.tools.AppFinalString
|
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 com.timber.soft.mylivewallpaper.ui.customerView.DownLoadDialog
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -28,6 +32,9 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
|
|||||||
private lateinit var binding: ActivityDetailsBinding
|
private lateinit var binding: ActivityDetailsBinding
|
||||||
private lateinit var wallpaperData: WallpaperData
|
private lateinit var wallpaperData: WallpaperData
|
||||||
private lateinit var downDialog: DownLoadDialog
|
private lateinit var downDialog: DownLoadDialog
|
||||||
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
|
private lateinit var videoUrl: String
|
||||||
|
private var isDownload = false
|
||||||
override fun getActivityContentView(): View {
|
override fun getActivityContentView(): View {
|
||||||
binding = ActivityDetailsBinding.inflate(layoutInflater)
|
binding = ActivityDetailsBinding.inflate(layoutInflater)
|
||||||
return binding.root
|
return binding.root
|
||||||
@ -85,6 +92,7 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
|
|||||||
binding.detailsCollect.setOnClickListener(this)
|
binding.detailsCollect.setOnClickListener(this)
|
||||||
binding.detailsSet.setOnClickListener(this)
|
binding.detailsSet.setOnClickListener(this)
|
||||||
binding.detailsPlayButton.setOnClickListener(this)
|
binding.detailsPlayButton.setOnClickListener(this)
|
||||||
|
binding.detailsVideoBack.setOnClickListener(this)
|
||||||
binding.detailsCollect.isSelected = wallpaperData.isCollect
|
binding.detailsCollect.isSelected = wallpaperData.isCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,15 +111,32 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.detailsPlayButton -> {
|
binding.detailsPlayButton -> {
|
||||||
if (isExist()) {
|
if (isDownload) {
|
||||||
|
binding.detailsPlayButton.isVisible = false
|
||||||
playVideo()
|
playVideo()
|
||||||
} else {
|
} else {
|
||||||
|
binding.detailsPlayButton.isVisible = false
|
||||||
|
binding.detailsProgressbar.isVisible = true
|
||||||
showDownloadDialog()
|
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() {
|
private fun setCollect() {
|
||||||
if (!binding.detailsCollect.isSelected) {
|
if (!binding.detailsCollect.isSelected) {
|
||||||
binding.detailsCollect.isSelected = !binding.detailsCollect.isSelected
|
binding.detailsCollect.isSelected = !binding.detailsCollect.isSelected
|
||||||
@ -138,15 +163,119 @@ class DetailActivity : BaseActivity(), View.OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showDownloadDialog() {
|
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() {
|
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 {
|
override fun onDestroy() {
|
||||||
return isExist(wallpaperData.preview)
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -10,23 +10,11 @@ import com.timber.soft.mylivewallpaper.databinding.ViewDownloaddialogBinding
|
|||||||
import com.timber.soft.mylivewallpaper.tools.AppTools.throttleClicks
|
import com.timber.soft.mylivewallpaper.tools.AppTools.throttleClicks
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO : no implement
|
|
||||||
*/
|
|
||||||
class DownLoadDialog(
|
class DownLoadDialog(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val url: String,
|
private val url: String,
|
||||||
private val title: String = "",
|
|
||||||
init: DownLoadDialog.() -> Unit
|
|
||||||
) : Dialog(context, R.style.DownLoadDialog) {
|
) : Dialog(context, R.style.DownLoadDialog) {
|
||||||
private lateinit var binding: ViewDownloaddialogBinding
|
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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -43,13 +31,10 @@ class DownLoadDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startDownload() {
|
private fun startDownload() {
|
||||||
binding.dialogProgressbar.progress = 0f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
if (!TextUtils.isEmpty(title)) {
|
|
||||||
binding.dialogText.text = title
|
|
||||||
}
|
|
||||||
binding.dialogIvClose.throttleClicks {
|
binding.dialogIvClose.throttleClicks {
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -94,14 +94,15 @@
|
|||||||
android:visibility="visible" />
|
android:visibility="visible" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/details_ivClose"
|
android:id="@+id/details_video_back"
|
||||||
android:layout_width="54dp"
|
android:layout_width="54dp"
|
||||||
android:layout_height="54dp"
|
android:layout_height="54dp"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="start"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
android:layout_marginTop="46dp"
|
android:layout_marginTop="46dp"
|
||||||
android:layout_marginEnd="24dp"
|
android:background="@drawable/shape_circular"
|
||||||
android:src="@drawable/svg_back"
|
android:padding="12dp"
|
||||||
android:visibility="visible" />
|
android:src="@drawable/svg_back" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user