云台控制
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.AlarmLogActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
|
||||
class AlarmLogActivity : AppCompatActivity() {
|
||||
private lateinit var binding: AlarmLogActivityBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = AlarmLogActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(binding.topBar)
|
||||
.init()
|
||||
initListener()
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
binding.btnBack.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,38 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import android.media.MediaRecorder
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.view.SurfaceHolder
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.view.animation.ScaleAnimation
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedDispatcher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.ui.test.isEnabled
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.LiveVideoActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.gyf.immersionbar.ktx.destroyImmersionBar
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
private const val TAG = "LiveVideoActivity"
|
||||
|
||||
class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
private lateinit var binding: LiveVideoActivityBinding
|
||||
|
||||
@@ -28,11 +42,24 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
private var isVoiceEnabled = false
|
||||
private var isLightOn = false
|
||||
private var isRecording = false
|
||||
private var mediaRecorder: MediaRecorder? = null
|
||||
private var micPulseAnimation: ScaleAnimation? = null
|
||||
|
||||
private var videoWidth = 0
|
||||
private var videoHeight = 0
|
||||
|
||||
private val testVideoUrl = "https://vjs.zencdn.net/v/oceans.mp4"
|
||||
|
||||
private val requestPermissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { isGranted ->
|
||||
if (isGranted) {
|
||||
startRecordingMode()
|
||||
} else {
|
||||
Toast.makeText(this, "需要录音权限才能使用控制功能", Toast.LENGTH_SHORT).show()
|
||||
isRecording = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -140,7 +167,8 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
}
|
||||
|
||||
binding.ivMenu.setOnClickListener {
|
||||
Toast.makeText(this, "菜单", Toast.LENGTH_SHORT).show()
|
||||
val intent = Intent(this, SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.ivFullscreen.setOnClickListener {
|
||||
@@ -166,6 +194,12 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
binding.llAlarmLog.setOnClickListener {
|
||||
Toast.makeText(this, "查看告警日志", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// 点击xq箭头跳转到AlarmLogActivity
|
||||
binding.xq.setOnClickListener {
|
||||
val intent = Intent(this, AlarmLogActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun togglePlayPause() {
|
||||
@@ -270,14 +304,124 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
}
|
||||
|
||||
private fun toggleRecording() {
|
||||
isRecording = !isRecording
|
||||
|
||||
if (isRecording) {
|
||||
binding.ivRecord.setImageResource(com.example.defenseapplication.R.drawable.copy_open)
|
||||
Toast.makeText(this, "开始录像", Toast.LENGTH_SHORT).show()
|
||||
if (!isRecording) {
|
||||
if (checkRecordAudioPermission()) {
|
||||
startRecordingMode()
|
||||
} else {
|
||||
requestRecordAudioPermission()
|
||||
}
|
||||
} else {
|
||||
binding.ivRecord.setImageResource(com.example.defenseapplication.R.drawable.copy)
|
||||
Toast.makeText(this, "停止录像", Toast.LENGTH_SHORT).show()
|
||||
stopRecordingMode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRecordAudioPermission(): Boolean {
|
||||
return ContextCompat.checkSelfPermission(
|
||||
this,
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
private fun requestRecordAudioPermission() {
|
||||
requestPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
|
||||
}
|
||||
|
||||
private fun startRecordingMode() {
|
||||
isRecording = true
|
||||
|
||||
binding.ivRecord.setImageResource(com.example.defenseapplication.R.drawable.copy_open)
|
||||
// 隐藏告警日志区域,显示控制台区域
|
||||
binding.llAlarmLog.visibility = View.GONE
|
||||
binding.consoleBar.visibility = View.VISIBLE
|
||||
|
||||
// 麦克风切换成开启状态
|
||||
binding.ivVoice.setImageResource(com.example.defenseapplication.R.drawable.voice_open)
|
||||
isVoiceEnabled = true
|
||||
|
||||
// 启动语音录制
|
||||
startVoiceRecording()
|
||||
|
||||
// 启动麦克风脉冲动画
|
||||
startMicPulseAnimation()
|
||||
|
||||
Toast.makeText(this, "开始控制模式", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
private fun stopRecordingMode() {
|
||||
isRecording = false
|
||||
|
||||
binding.ivRecord.setImageResource(com.example.defenseapplication.R.drawable.copy)
|
||||
// 显示告警日志区域,隐藏控制台区域
|
||||
binding.llAlarmLog.visibility = View.VISIBLE
|
||||
binding.consoleBar.visibility = View.GONE
|
||||
|
||||
// 麦克风切换成关闭状态
|
||||
binding.ivVoice.setImageResource(com.example.defenseapplication.R.drawable.voice)
|
||||
isVoiceEnabled = false
|
||||
|
||||
// 停止语音录制
|
||||
stopVoiceRecording()
|
||||
|
||||
// 停止麦克风脉冲动画
|
||||
stopMicPulseAnimation()
|
||||
|
||||
Toast.makeText(this, "停止控制模式", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
private fun startMicPulseAnimation() {
|
||||
micPulseAnimation = ScaleAnimation(
|
||||
1.0f, 1.3f,
|
||||
1.0f, 1.3f,
|
||||
Animation.RELATIVE_TO_SELF, 0.5f,
|
||||
Animation.RELATIVE_TO_SELF, 0.5f
|
||||
).apply {
|
||||
duration = 500
|
||||
repeatCount = Animation.INFINITE
|
||||
repeatMode = Animation.REVERSE
|
||||
interpolator = LinearInterpolator()
|
||||
}
|
||||
binding.ivVoice.startAnimation(micPulseAnimation)
|
||||
}
|
||||
|
||||
private fun stopMicPulseAnimation() {
|
||||
micPulseAnimation?.let {
|
||||
binding.ivVoice.clearAnimation()
|
||||
micPulseAnimation = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun startVoiceRecording() {
|
||||
mediaRecorder = MediaRecorder().apply {
|
||||
setAudioSource(MediaRecorder.AudioSource.MIC)
|
||||
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
|
||||
val outputDir = getExternalFilesDir(null) ?: filesDir
|
||||
val audioDir = File(outputDir, "audio")
|
||||
if (!audioDir.exists()) {
|
||||
audioDir.mkdirs()
|
||||
}
|
||||
val outputFile = File(audioDir, "voice_record_${System.currentTimeMillis()}.3gp")
|
||||
setOutputFile(outputFile.absolutePath)
|
||||
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
|
||||
|
||||
try {
|
||||
prepare()
|
||||
start()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(this@LiveVideoActivity, "录音启动失败", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopVoiceRecording() {
|
||||
mediaRecorder?.let {
|
||||
try {
|
||||
it.stop()
|
||||
it.release()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
mediaRecorder = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.databinding.SettingsActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: SettingsActivityBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = SettingsActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
// ImmersionBar核心调用,沉浸式
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(binding.topBar)
|
||||
.init()
|
||||
binding.ivBack.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user