diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/SystemStatusFragment.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/SystemStatusFragment.kt index 2a9bd991..8f2b85c2 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/SystemStatusFragment.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/SystemStatusFragment.kt @@ -184,7 +184,7 @@ class SystemStatusFragment : Fragment() { cameraManager = requireContext().getSystemService(Context.CAMERA_SERVICE) as android.hardware.camera2.CameraManager binding.btnQuickFlash.setOnClickListener { - toggleFlashlight() + toggleFlashlight() } binding.btnQuickFlash.setOnLongClickListener { toggleFlashlight(120) @@ -256,66 +256,71 @@ class SystemStatusFragment : Fragment() { private fun allPermissionsGranted() = androidx.core.content.ContextCompat.checkSelfPermission( requireContext(), CAMERA_PERMISSION) == android.content.pm.PackageManager.PERMISSION_GRANTED + private var mirrorDialog: android.app.Dialog? = null // 멤버 변수로 선언 + private fun showMirrorDialog() { - val dialog = android.app.Dialog(requireContext(), android.R.style.Theme_Black_NoTitleBar_Fullscreen) + mirrorDialog = android.app.Dialog(requireContext(), android.R.style.Theme_Black_NoTitleBar_Fullscreen) + mirrorDialog?.let { mirrorDialog -> - // 레이아웃 구성을 위한 FrameLayout 생성 - val frameLayout = android.widget.FrameLayout(requireContext()) - val previewView = androidx.camera.view.PreviewView(requireContext()) - // 타이머용 TextView 생성 - val timerText = TextView(requireContext()).apply { - setTextColor(Color.WHITE) - setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) - setBackgroundColor(Color.parseColor("#88000000")) // 반투명 배경 - setPadding(32, 16, 32, 16) - gravity = android.view.Gravity.CENTER - } + // 레이아웃 구성을 위한 FrameLayout 생성 + val frameLayout = android.widget.FrameLayout(requireContext()) + val previewView = androidx.camera.view.PreviewView(requireContext()) - val params = android.widget.FrameLayout.LayoutParams( - android.widget.FrameLayout.LayoutParams.WRAP_CONTENT, - android.widget.FrameLayout.LayoutParams.WRAP_CONTENT - ).apply { - gravity = android.view.Gravity.TOP or android.view.Gravity.CENTER_HORIZONTAL - topMargin = 100 - } - - frameLayout.addView(previewView) - frameLayout.addView(timerText, params) - dialog.setContentView(frameLayout) - - val cameraProviderFuture = androidx.camera.lifecycle.ProcessCameraProvider.getInstance(requireContext()) - - cameraProviderFuture.addListener({ - val cameraProvider = cameraProviderFuture.get() - val preview = androidx.camera.core.Preview.Builder().build() - - // 전면 카메라 선택 - val cameraSelector = androidx.camera.core.CameraSelector.DEFAULT_FRONT_CAMERA - - try { - cameraProvider.unbindAll() - // 이 다이얼로그의 LifecycleOwner를 Fragment로 지정 - cameraProvider.bindToLifecycle(this, cameraSelector, preview) - preview.setSurfaceProvider(previewView.surfaceProvider) - } catch (e: Exception) { - Blog.LOGE("거울 실행 실패: ${e.message}") + // 타이머용 TextView 생성 + val timerText = TextView(requireContext()).apply { + setTextColor(Color.WHITE) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) + setBackgroundColor(Color.parseColor("#88000000")) // 반투명 배경 + setPadding(32, 16, 32, 16) + gravity = android.view.Gravity.CENTER } - }, androidx.core.content.ContextCompat.getMainExecutor(requireContext())) - CoroutineScope(Dispatchers.Main).launch { - for (i in 30 downTo 1) { - if (!dialog.isShowing) break - timerText.text = "거울 모드 종료까지 $i" + "초" - delay(1000L) + + val params = android.widget.FrameLayout.LayoutParams( + android.widget.FrameLayout.LayoutParams.WRAP_CONTENT, + android.widget.FrameLayout.LayoutParams.WRAP_CONTENT + ).apply { + gravity = android.view.Gravity.TOP or android.view.Gravity.CENTER_HORIZONTAL + topMargin = 100 } - if (dialog.isShowing) { - dialog.dismiss() - context?.toast("배터리 절약을 위해 거울을 껐습니다.") + + frameLayout.addView(previewView) + frameLayout.addView(timerText, params) + mirrorDialog?.setContentView(frameLayout) + + val cameraProviderFuture = androidx.camera.lifecycle.ProcessCameraProvider.getInstance(requireContext()) + + cameraProviderFuture.addListener({ + val cameraProvider = cameraProviderFuture.get() + val preview = androidx.camera.core.Preview.Builder().build() + + // 전면 카메라 선택 + val cameraSelector = androidx.camera.core.CameraSelector.DEFAULT_FRONT_CAMERA + + try { + cameraProvider.unbindAll() + // 이 다이얼로그의 LifecycleOwner를 Fragment로 지정 + cameraProvider.bindToLifecycle(this, cameraSelector, preview) + preview.setSurfaceProvider(previewView.surfaceProvider) + } catch (e: Exception) { + Blog.LOGE("거울 실행 실패: ${e.message}") + } + }, androidx.core.content.ContextCompat.getMainExecutor(requireContext())) + CoroutineScope(Dispatchers.Main).launch { + for (i in 30 downTo 1) { + if (!mirrorDialog.isShowing) break + timerText.text = "거울 모드 종료까지 $i" + "초" + delay(1000L) + } + if (mirrorDialog.isShowing == true) { + mirrorDialog.dismiss() + context?.toast("배터리 절약을 위해 거울을 껐습니다.") + } } + // 화면 터치 시 종료 + previewView.setOnClickListener { mirrorDialog?.dismiss() } + mirrorDialog?.show() } - // 화면 터치 시 종료 - previewView.setOnClickListener { dialog.dismiss() } - dialog.show() } private fun updateQuickControlUI() { @@ -337,6 +342,22 @@ class SystemStatusFragment : Fragment() { override fun onHiddenChanged(hidden: Boolean) { super.onHiddenChanged(hidden) if (hidden) { + if (isFlashOn) { + isFlashOn = false + try { + cameraManager.setTorchMode(cameraManager.cameraIdList[0], false) + binding.btnQuickFlash.text = "🔦 조명" + binding.btnQuickFlash.setTextColor(Color.WHITE) + } catch (e: Exception) { e.printStackTrace() } + } + flashTimerJob?.cancel() + + // 2. 거울 다이얼로그 닫기 (카메라 자원 해제) + mirrorDialog?.let { + if (it.isShowing) it.dismiss() + } + mirrorDialog = null + stopMonitoring() } else { resetNetworkCounters() @@ -348,7 +369,7 @@ class SystemStatusFragment : Fragment() { override fun onPause() { super.onPause() - stopMonitoring() + onHiddenChanged(true) } override fun onResume() {