视频组件自定义
This commit is contained in:
@@ -6,7 +6,10 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@@ -16,6 +19,7 @@ import chuangyuan.ycj.videolibrary.listener.VideoInfoListener
|
||||
import chuangyuan.ycj.videolibrary.video.ExoUserPlayer
|
||||
import chuangyuan.ycj.videolibrary.video.VideoPlayerManager
|
||||
import com.google.android.exoplayer2.ui.PlayerView
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.adapter.AlarmLogAdapter
|
||||
import com.example.defenseapplication.bean.DeviceAlarmBean
|
||||
@@ -24,6 +28,8 @@ import com.example.defenseapplication.databinding.AlarmLogActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.launch
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import com.bigkoo.pickerview.builder.TimePickerBuilder
|
||||
@@ -38,23 +44,38 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
private val originalAlarmList = mutableListOf<DeviceAlarmBean>()
|
||||
private lateinit var exoPlayerManager: ExoUserPlayer
|
||||
private var isMuted = false
|
||||
private var isVoiceEnabled = false
|
||||
private var isLightOn = false
|
||||
private var isPlaying = false
|
||||
private var deviceId: String? = null
|
||||
private var isLoading = false
|
||||
private var fromLiveVideo = false
|
||||
private var isFullScreen = false
|
||||
private var isControlsVisible = false
|
||||
private val hideDelay = 5000L // 5秒自动隐藏
|
||||
private val hideHandler = Handler(Looper.getMainLooper())
|
||||
private val hideRunnable = Runnable {
|
||||
hideControls()
|
||||
}
|
||||
private var passedVideoUrl: String? = null
|
||||
private var passedSelectedId: String? = null
|
||||
private var passedCreateTime: String? = null
|
||||
private var totalDuration: Long = 0
|
||||
private val progressHandler = Handler(Looper.getMainLooper())
|
||||
private val progressRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
updateProgress()
|
||||
progressHandler.postDelayed(this, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = AlarmLogActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.transparentStatusBar()
|
||||
.init()
|
||||
|
||||
window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
|
||||
deviceId = intent.getStringExtra("device_id")
|
||||
fromLiveVideo = intent.getBooleanExtra("from_live_video", false)
|
||||
@@ -68,14 +89,14 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
fetchAlarmList()
|
||||
initListener()
|
||||
|
||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (exoPlayerManager.onBackPressed()) {
|
||||
return
|
||||
}
|
||||
finish()
|
||||
}
|
||||
})
|
||||
// onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
// override fun handleOnBackPressed() {
|
||||
// if (exoPlayerManager.onBackPressed()) {
|
||||
// return
|
||||
// }
|
||||
// finish()
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
private fun dpToPx(dp: Int): Int {
|
||||
@@ -97,6 +118,9 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
.addVideoInfoListener(object : VideoInfoListener {
|
||||
override fun onPlayStart(p0: Long) {
|
||||
Log.d("AlarmLogActivity", "视频开始播放")
|
||||
startProgressUpdate()
|
||||
showControls()
|
||||
resetHideTimer()
|
||||
}
|
||||
|
||||
override fun onLoadingChanged() {
|
||||
@@ -108,9 +132,24 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
|
||||
override fun onPlayEnd() {
|
||||
Log.d("AlarmLogActivity", "播放结束")
|
||||
stopProgressUpdate()
|
||||
hideControls()
|
||||
}
|
||||
|
||||
override fun isPlaying(p0: Boolean) {
|
||||
isPlaying = p0
|
||||
if (p0) {
|
||||
startProgressUpdate()
|
||||
// 视频开始播放时,如果控制栏可见,启动自动隐藏计时器
|
||||
if (isControlsVisible) {
|
||||
resetHideTimer()
|
||||
}
|
||||
} else {
|
||||
stopProgressUpdate()
|
||||
// 视频暂停时,取消自动隐藏计时器,保持控制栏显示
|
||||
hideHandler.removeCallbacks(hideRunnable)
|
||||
showControls()
|
||||
}
|
||||
}
|
||||
|
||||
fun onRepeatModeChanged(p0: Int) {
|
||||
@@ -121,25 +160,11 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
exoPlayerManager.startPlayer()
|
||||
|
||||
setupControllerVisibilityListener()
|
||||
updateProgress()
|
||||
}
|
||||
|
||||
private fun setupControllerVisibilityListener() {
|
||||
binding.exoPlayContextId.post {
|
||||
val playerView = findPlayerView(binding.exoPlayContextId)
|
||||
playerView?.setControllerVisibilityListener { visibility ->
|
||||
if (visibility == View.VISIBLE) {
|
||||
binding.ivBack.visibility = View.VISIBLE
|
||||
binding.muteBar.visibility = View.VISIBLE
|
||||
binding.ivDownload.visibility = View.VISIBLE
|
||||
binding.ivDelete.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.ivBack.visibility = View.GONE
|
||||
binding.muteBar.visibility = View.GONE
|
||||
binding.ivDownload.visibility = View.GONE
|
||||
binding.ivDelete.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
// 移除原来的控制器监听器,改为自定义控制逻辑
|
||||
}
|
||||
|
||||
private fun findPlayerView(view: View): PlayerView? {
|
||||
@@ -169,16 +194,19 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
binding.alarmListRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
binding.alarmListRecyclerView.adapter = adapter
|
||||
}
|
||||
|
||||
|
||||
private fun playVideo(videoUrl: String) {
|
||||
exoPlayerManager.onDestroy()
|
||||
|
||||
|
||||
exoPlayerManager = VideoPlayerManager.Builder(VideoPlayerManager.TYPE_PLAY_GESTURE, binding.exoPlayContextId)
|
||||
.setPlayUri(videoUrl)
|
||||
.setPosition(0)
|
||||
.addVideoInfoListener(object : VideoInfoListener {
|
||||
override fun onPlayStart(p0: Long) {
|
||||
Log.d("AlarmLogActivity", "视频开始播放")
|
||||
startProgressUpdate()
|
||||
showControls()
|
||||
resetHideTimer()
|
||||
}
|
||||
|
||||
override fun onLoadingChanged() {
|
||||
@@ -190,25 +218,51 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
|
||||
override fun onPlayEnd() {
|
||||
Log.d("AlarmLogActivity", "播放结束")
|
||||
stopProgressUpdate()
|
||||
hideControls()
|
||||
}
|
||||
|
||||
override fun isPlaying(p0: Boolean) {
|
||||
isPlaying = p0
|
||||
if (p0) {
|
||||
startProgressUpdate()
|
||||
// 视频开始播放时,如果控制栏可见,启动自动隐藏计时器
|
||||
if (isControlsVisible) {
|
||||
resetHideTimer()
|
||||
}
|
||||
} else {
|
||||
stopProgressUpdate()
|
||||
// 视频暂停时,取消自动隐藏计时器,保持控制栏显示
|
||||
hideHandler.removeCallbacks(hideRunnable)
|
||||
showControls()
|
||||
}
|
||||
}
|
||||
|
||||
fun onRepeatModeChanged(p0: Int) {
|
||||
}
|
||||
})
|
||||
.create()
|
||||
|
||||
|
||||
exoPlayerManager.startPlayer()
|
||||
|
||||
// 保持当前的静音状态
|
||||
if (isMuted) {
|
||||
try {
|
||||
val method = exoPlayerManager.javaClass.getMethod("getPlayer")
|
||||
val player = method.invoke(exoPlayerManager) as? SimpleExoPlayer
|
||||
player?.volume = 0f
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchAlarmList() {
|
||||
val currentDeviceId = deviceId ?: return
|
||||
|
||||
|
||||
Log.d("AlarmLogActivity", "=== 开始请求设备告警日志 ===")
|
||||
Log.d("AlarmLogActivity", "请求参数 - deviceId: $currentDeviceId")
|
||||
|
||||
|
||||
isLoading = true
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
@@ -218,16 +272,16 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
pageNum = "1",
|
||||
pageSize = "10"
|
||||
)
|
||||
|
||||
|
||||
Log.d("AlarmLogActivity", "请求完成")
|
||||
Log.d("AlarmLogActivity", "总条数: ${response.total}, 当前页数据条数: ${response.rows.size}")
|
||||
|
||||
|
||||
val newData = response.rows
|
||||
originalAlarmList.clear()
|
||||
originalAlarmList.addAll(newData)
|
||||
filterAlarmListByDate(calendar)
|
||||
Log.d("AlarmLogActivity", "已获取 ${newData.size} 条数据")
|
||||
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("AlarmLogActivity", "请求异常: ${e.message}", e)
|
||||
} finally {
|
||||
@@ -236,11 +290,21 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun showEmptyView() {
|
||||
binding.alarmListRecyclerView.visibility = View.GONE
|
||||
binding.emptyLayout.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun hideEmptyView() {
|
||||
binding.alarmListRecyclerView.visibility = View.VISIBLE
|
||||
binding.emptyLayout.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun filterAlarmListByDate(selectedDate: Calendar) {
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
||||
val selectedDateStr = dateFormat.format(selectedDate.time)
|
||||
|
||||
|
||||
alarmList.clear()
|
||||
originalAlarmList.forEach { item ->
|
||||
val itemDateStr = item.createTime.substring(0, 10)
|
||||
@@ -250,6 +314,12 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
}
|
||||
adapter?.notifyDataSetChanged()
|
||||
Log.d("AlarmLogActivity", "日期筛选完成,筛选后条数: ${alarmList.size}")
|
||||
|
||||
if (alarmList.isEmpty()) {
|
||||
showEmptyView()
|
||||
} else {
|
||||
hideEmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDateDisplay() {
|
||||
@@ -258,8 +328,51 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
binding.tvDate.text = "${month}月${day}日"
|
||||
}
|
||||
|
||||
private fun showControls() {
|
||||
isControlsVisible = true
|
||||
binding.functionBar.visibility = View.VISIBLE
|
||||
binding.muteBar.visibility = View.VISIBLE
|
||||
binding.playBar.visibility = View.VISIBLE
|
||||
binding.progressBar.visibility = View.VISIBLE
|
||||
// 只有在视频播放时才启动自动隐藏计时器
|
||||
if (isPlaying) {
|
||||
resetHideTimer()
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideControls() {
|
||||
isControlsVisible = false
|
||||
binding.functionBar.visibility = View.GONE
|
||||
binding.muteBar.visibility = View.GONE
|
||||
binding.playBar.visibility = View.GONE
|
||||
binding.progressBar.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun toggleControls() {
|
||||
if (isControlsVisible) {
|
||||
hideControls()
|
||||
} else {
|
||||
showControls()
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetHideTimer() {
|
||||
hideHandler.removeCallbacks(hideRunnable)
|
||||
// 只有在视频播放时才启动自动隐藏计时器
|
||||
if (isPlaying) {
|
||||
hideHandler.postDelayed(hideRunnable, hideDelay)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
// 点击视频区域切换控制栏显示/隐藏
|
||||
binding.exoPlayContextId.setOnClickListener {
|
||||
toggleControls()
|
||||
}
|
||||
|
||||
// 控制栏上的按钮点击时重置隐藏计时器
|
||||
binding.ivBack.setOnClickListener {
|
||||
resetHideTimer()
|
||||
finish()
|
||||
}
|
||||
|
||||
@@ -268,26 +381,66 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
binding.ivMute.setOnClickListener {
|
||||
resetHideTimer()
|
||||
toggleMute()
|
||||
}
|
||||
|
||||
binding.ivDownload.setOnClickListener {
|
||||
resetHideTimer()
|
||||
downloadVideo()
|
||||
}
|
||||
|
||||
binding.ivDelete.setOnClickListener {
|
||||
resetHideTimer()
|
||||
deleteVideo()
|
||||
}
|
||||
|
||||
binding.ivFullScreen.setOnClickListener {
|
||||
resetHideTimer()
|
||||
toggleFullScreen()
|
||||
}
|
||||
|
||||
binding.ivPlay.setOnClickListener {
|
||||
resetHideTimer()
|
||||
togglePlay()
|
||||
}
|
||||
|
||||
binding.seekBar.setOnSeekBarChangeListener(object : android.widget.SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: android.widget.SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
resetHideTimer()
|
||||
exoPlayerManager.seekTo(progress.toLong() * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: android.widget.SeekBar?) {
|
||||
resetHideTimer()
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: android.widget.SeekBar?) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun toggleMute() {
|
||||
isMuted = !isMuted
|
||||
if (isMuted) {
|
||||
binding.ivMute.setImageResource(R.drawable.mute)
|
||||
Toast.makeText(this, R.string.sound_off, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
binding.ivMute.setImageResource(R.drawable.voice)
|
||||
Toast.makeText(this, R.string.sound_on, Toast.LENGTH_SHORT).show()
|
||||
try {
|
||||
// 通过反射获取底层的 ExoPlayer 实例
|
||||
val method = exoPlayerManager.javaClass.getMethod("getPlayer")
|
||||
val player = method.invoke(exoPlayerManager) as? SimpleExoPlayer
|
||||
|
||||
if (isMuted) {
|
||||
binding.ivMute.setImageResource(R.drawable.mute)
|
||||
player?.volume = 0f
|
||||
Toast.makeText(this, R.string.sound_off, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
binding.ivMute.setImageResource(R.drawable.un_mute)
|
||||
player?.volume = 1f
|
||||
Toast.makeText(this, R.string.sound_on, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(this, "音量控制失败", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +452,63 @@ class AlarmLogActivity : AppCompatActivity() {
|
||||
Toast.makeText(this, R.string.delete, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
private fun updateProgress() {
|
||||
val currentPosition = exoPlayerManager.getCurrentPosition()
|
||||
totalDuration = exoPlayerManager.getDuration()
|
||||
|
||||
binding.tvCurrentTime.text = formatTime(currentPosition)
|
||||
binding.tvTotalTime.text = formatTime(totalDuration)
|
||||
|
||||
if (totalDuration > 0) {
|
||||
val progress = (currentPosition * 100 / totalDuration).toInt()
|
||||
binding.seekBar.progress = progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatTime(milliseconds: Long): String {
|
||||
val seconds = (milliseconds / 1000).toInt()
|
||||
val hours = seconds / 3600
|
||||
val minutes = (seconds % 3600) / 60
|
||||
val secs = seconds % 60
|
||||
|
||||
return if (hours > 0) {
|
||||
String.format("%02d:%02d:%02d", hours, minutes, secs)
|
||||
} else {
|
||||
String.format("%02d:%02d", minutes, secs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startProgressUpdate() {
|
||||
stopProgressUpdate()
|
||||
progressHandler.post(progressRunnable)
|
||||
}
|
||||
|
||||
private fun stopProgressUpdate() {
|
||||
progressHandler.removeCallbacks(progressRunnable)
|
||||
}
|
||||
|
||||
private fun toggleFullScreen() {
|
||||
isFullScreen = !isFullScreen
|
||||
if (isFullScreen) {
|
||||
binding.ivFullScreen.setImageResource(R.drawable.full_screen)
|
||||
requestedOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
} else {
|
||||
binding.ivFullScreen.setImageResource(R.drawable.full_size)
|
||||
requestedOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
}
|
||||
}
|
||||
|
||||
private fun togglePlay() {
|
||||
isPlaying = !isPlaying
|
||||
if (isPlaying) {
|
||||
binding.ivPlay.setImageResource(R.drawable.zt)
|
||||
exoPlayerManager.startPlayer()
|
||||
} else {
|
||||
binding.ivPlay.setImageResource(R.drawable.start)
|
||||
exoPlayerManager.onPause()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
exoPlayerManager.onResume()
|
||||
|
||||
@@ -83,14 +83,14 @@ class LiveVideoActivity : BaseActivity() {
|
||||
initAlarmRecyclerView()
|
||||
initListener()
|
||||
fetchAlarmList()
|
||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (exoPlayerManager.onBackPressed()) {
|
||||
return
|
||||
}
|
||||
finish()
|
||||
}
|
||||
})
|
||||
// onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
// override fun handleOnBackPressed() {
|
||||
// if (exoPlayerManager.onBackPressed()) {
|
||||
// return
|
||||
// }
|
||||
// finish()
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
private fun initVideoPlayer() {
|
||||
|
||||
@@ -230,8 +230,6 @@ interface ApiService {
|
||||
@Query("deviceId") deviceId: String,
|
||||
@Query("pageNum") pageNum: String="1",
|
||||
@Query("pageSize") pageSize: String="10",
|
||||
@Query("startTime") startTime: String? = null,
|
||||
@Query("endTime") endTime: String? = null
|
||||
): DeviceAlarmResponse
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user