From ae5559e01aea65e31e597d5718e15cd2ee9d2752 Mon Sep 17 00:00:00 2001 From: maxinyu Date: Thu, 7 May 2026 14:22:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=91=E5=8F=B0=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 10 +- .../liveVideo/AlarmLogActivity.kt | 29 ++ .../liveVideo/LiveVideoActivity.kt | 160 ++++++- .../liveVideo/SettingsActivity.kt | 25 ++ app/src/main/res/drawable/back_white.png | Bin 0 -> 484 bytes app/src/main/res/drawable/console.png | Bin 0 -> 5905 bytes app/src/main/res/drawable/delete.png | Bin 0 -> 518 bytes app/src/main/res/drawable/download.png | Bin 0 -> 1564 bytes app/src/main/res/drawable/expand.png | Bin 0 -> 361 bytes app/src/main/res/drawable/mute.png | Bin 0 -> 735 bytes app/src/main/res/drawable/start.png | Bin 0 -> 390 bytes .../main/res/layout/alarm_log_activity.xml | 364 ++++++++++++++++ .../main/res/layout/live_video_activity.xml | 31 +- app/src/main/res/layout/settings_activity.xml | 390 ++++++++++++++++++ app/src/main/res/values/colors.xml | 1 + 15 files changed, 999 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/example/defenseapplication/liveVideo/AlarmLogActivity.kt create mode 100644 app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt create mode 100644 app/src/main/res/drawable/back_white.png create mode 100644 app/src/main/res/drawable/console.png create mode 100644 app/src/main/res/drawable/delete.png create mode 100644 app/src/main/res/drawable/download.png create mode 100644 app/src/main/res/drawable/expand.png create mode 100644 app/src/main/res/drawable/mute.png create mode 100644 app/src/main/res/drawable/start.png create mode 100644 app/src/main/res/layout/alarm_log_activity.xml create mode 100644 app/src/main/res/layout/settings_activity.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a119749..3cde424 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,8 @@ + + @@ -23,6 +25,12 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.DefenseApplication"> + + @@ -52,7 +60,7 @@ android:exported="false" /> + android:exported="false" /> diff --git a/app/src/main/java/com/example/defenseapplication/liveVideo/AlarmLogActivity.kt b/app/src/main/java/com/example/defenseapplication/liveVideo/AlarmLogActivity.kt new file mode 100644 index 0000000..dacd45e --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/liveVideo/AlarmLogActivity.kt @@ -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() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt b/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt index b4eb20d..4ceb1af 100644 --- a/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt @@ -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 } } diff --git a/app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt b/app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt new file mode 100644 index 0000000..57d06ec --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt @@ -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() + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/back_white.png b/app/src/main/res/drawable/back_white.png new file mode 100644 index 0000000000000000000000000000000000000000..39089f293aee71df6a7833ca6604f9b9f2f8d27c GIT binary patch literal 484 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/delete.png b/app/src/main/res/drawable/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..668b0a1194668f0b08cca95687f7b389caa0c3bc GIT binary patch literal 518 zcmV+h0{Q)kP)`&TXc9Zg(@XV0xePecw6XnfK1AbEhcw!=K+X$Ye5|kc2dZ>79iHl!qOJ z^B1t8k`0GY2N!T2!Xxv8umDau4d`rz3RsNC1ya50 zFlgulsWPXhms}60`Iv7&bqf22DWWvYVCTYOH9a+8*AK`iz*DY4KQogBV4UyR22Z{L zXM6&y%x=IZ?3sF<`~woI1$h!Kl?(DaxKvV5s;c0wqO*jc1f1O zYKLSE0&*FYn66S2i%qn($}$GqM;g6vyui2M!t-6gV(6EGjBAYG6=k^dKX{Cn*^S85tQB2^rPESx`}dl7UfCjx;DR z5;Q0(DtZGUBcq}sqc;!=3UUw>ynesiJ?HJS&%XDbk9(g8KGy&3z1LoQ?e#xrf1Z0@ z=Pds_M<9EFv$L~TfhWKb@H6-g`~%E?O8Pul4Hjf=Mv=CD0|c}ld_gcLz_Va2SOzWx z25bIC@;kxD;9KnP0oGA$CyfaZz+!NK?hk=gpsHMo;hW%V+OHsOC5;Hs@pbh2CD;s_ z$`v%6#@7R+jiojLI=qG6914p`Q!<0{Ab0^h4Sd?iNmH^A+j5ul@`^kQ)5 zlg6Tc<;29q#o%u6IM@a51=nJH36Rif(pYxmdwr~|Qm#yZ4xDsvQ91QRIUWmAQs<*4=C0TELSFgm;1o=Ae1clPeSFOJS2Xi{$_9#gyN9g9V)8i zD-q!7FT$BiBuOrRlA9!;Ur1{SZT_ag1`yAUDf+6lGF2i#M|T2AkmRzHKzy3HqE3dk zl9-~6DM>DSA>k^QD+Xn%64)L&nI?eOBVFwxK74!oqK0mI#~|?$xIC&W6^9bQiDNS! z`*Eiw$2AnsVH>{%RGl@QPUkrN-%i?Bh7zD9=IyH9+6FVf}3KYgMbhQbM$CO_k z`8D_-LtRK9-d$7d!?t71^YopM@uG5!VdcV-_Z<>&nanH5IH^g_m^?<$@sjTS8ugrn z1mg95ElY0i3{a`fvl#`|;Fqa&oWsDuReW9=9t$;HdXt2kT%7WI(2(B}=BWbnHH zECF``Ki7DSaR`O(b})P-5$fhPGAcdRx@i>*C~N~BuKpnHf=;|_6gCv<8VSB$qTye_ zgQF{-mwt)`IZS*$;DXXZ_y#O{x#)K`w_f;UylnWIEjI?i-%4XAYP-_0SH6lm&+Sw<7koJHyu@tBix13W z`~~PYfxaKfu+60}fy_cj;4QGHhnGn!InR6yO7S%VUI9L^4@n0;@z~c;0&#<|%p_b2 z4gi0^a6*RFr95`afj@v~??>X2OaF*b zwgj9X@aT$5VLuX{s|-Fo%e#++<*t*u|Jo8TsIX5-xPpW_^S&ubn9tw}C$e&*v@L=A z>D67DB$w2%kXUX&=6A4;30pW>qN^>f2oQibrrYSX(x(>e6x&SE_InF$(Taeb6NqcM zM~f;XTp~Bpru80T-=Z}Eoe+>;DkSm$uBx&OgZIh1`<81PYDPl9zI!CxNlQmw>K*G_ zuo-Fa_?1j(^T&|VWh69cnjhI4$O3?b<69Enp>ws_hHek}vB<~? z7$pIFrn!>zBGCGm9DVk~SP1m%Y#jRk00030|EXvQz5oCK21!IgR09Auy18)9>C+eh O0000A-^>|~`tjmESjF!^j~h z{8v?V0e@T9^&i~1NPsj=ZA53#2_Z?6{J~yAFF1Y6vbL~ukpLL|3dj^0cL<8MLWnC) z-}Ag3{3Ve9j8-5=j6HB&ch6W=B|x@BCUO!XMAtOU!&6Hn1f5TXC3ZAT`=viqX##X@ zTH+`6FtTlXlNIxp0G0PoxI`p=u^7{=V3$M!Fj|D*U!1XrVO=qEYXJ;o5Oi)kjNw43xHpsA?nzX1RM|NlOx(?tLP00v1!K~w_(|G< zOGp+`6vyvaQArUIK@en6&?+Jbq3A&oQ7vjw5cD8uRYXPwQPDdJ+7v+#uys+J+C*(b z6h(Y3bmI#*A}GE<@PRu1{)f5aeBX?ZZ{bQgzjMw#=iYPfcjwMn z!gZ}uumh|(b|q_$Vq?i{K=vz?!Fm{k_fSf4UzDM{Ed>K`jGT5}j{k=yTd*dn1|(OJ zxd2rx+6jB%E{qd%`ubAzPOH& zp~)}P&K-`d%WAMLN{&RfFNw}lXRbM)NoMW*B=JMwWh;*6_h3ylFejmU@wJN*cBi~<)OBK6$D&_r51+i` zv=mf>i3*tG6*poGzY0!4C0qmjD&3a&fzo^haea>_uwJy0kikzdNj0#jb62ryv>z*3 zi@HZqe*qY}jZ&cZ1Y`0AUB)Kk8<=W95yc)eQO}?cdjxd-E@A7)@4-s8NkKQ5P`DgE z+8|OY7P-zpP@TDsMaA`oRxsf_+=A^;LlbS_DZV5=Zw>OvX+To9C0V?gm}6HVXlDl) zcfl(-3;Jb$v2#j(1AQfRi?nkqo?J;2eG>G~M4xVb_|6g2jZ03;@$(yK@h%pniu+aM zCPCk+dLNt5<}_eoKMc*cpwL`SgF+WCX8sHS00960F7Va#00006Nklct2LCP*sq%Kl8BVorYoTPlsBGT7$Es( zb&OZRr7+GgLsACmwfPm$9}?GAVpt&gV6`O(!KLt>Aq=(zCD_wifgacrgkVJDpJ5m! z*fHDUN3fzP1u=@}tkQT99B8V-C&e8Qd$#iE3dYp@Qd)owvodZ4;yN<4MJb-Kx{i}z zdu|Yazrp-PaSOzrt@}6$5>(XTpVBO>nLR}+ps){ln0jipyd)J^e)m1zTyO*c0RR8j kInfpX000I_L_t&o0Alx3F;|X19smFU07*qoM6N<$f~gX!)c^nh literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/alarm_log_activity.xml b/app/src/main/res/layout/alarm_log_activity.xml new file mode 100644 index 0000000..2c05859 --- /dev/null +++ b/app/src/main/res/layout/alarm_log_activity.xml @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>--> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/live_video_activity.xml b/app/src/main/res/layout/live_video_activity.xml index 298ff10..63960b2 100644 --- a/app/src/main/res/layout/live_video_activity.xml +++ b/app/src/main/res/layout/live_video_activity.xml @@ -187,6 +187,25 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml new file mode 100644 index 0000000..c23ce63 --- /dev/null +++ b/app/src/main/res/layout/settings_activity.xml @@ -0,0 +1,390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 65904ee..92102b5 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -13,5 +13,6 @@ #99000000 #E7E7E7 #F9F9F9 + #03A9F4 \ No newline at end of file