package com.quillstudios.pokegoalshelper import android.Manifest import android.app.Activity import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.media.projection.MediaProjectionManager import android.net.Uri import android.os.Build import android.os.Bundle import android.provider.Settings import android.util.Log import com.quillstudios.pokegoalshelper.utils.PGHLog import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.quillstudios.pokegoalshelper.ui.theme.PokeGoalsHelperTheme import org.opencv.android.OpenCVLoader import org.opencv.core.Mat import org.opencv.core.CvType class MainActivity : ComponentActivity() { companion object { private const val TAG = "MainActivity" } private var isCapturing by mutableStateOf(false) // private var yoloDetector: YOLOOnnxDetector? = null // Using MLInferenceEngine now // private var yoloDetector_tflite: YOLOTFLiteDetector? = null // Removed - using MLInferenceEngine now private lateinit var mediaProjectionManager: MediaProjectionManager private val screenCapturePermissionLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> PGHLog.d(TAG, "Screen capture permission result: ${result.resultCode}") if (result.resultCode == Activity.RESULT_OK) { val data = result.data if (data != null) { try { startScreenCaptureService(data) // FloatingUI now handled by service overlay isCapturing = true PGHLog.d(TAG, "Screen capture service started successfully") } catch (e: Exception) { PGHLog.e(TAG, "Failed to start screen capture service", e) isCapturing = false } } else { PGHLog.e(TAG, "Screen capture permission granted but no data received") } } else { PGHLog.e(TAG, "Screen capture permission denied with result code: ${result.resultCode}") } } private fun initializeOpenCV() { if (OpenCVLoader.initLocal()) { PGHLog.d(TAG, "OpenCV loaded successfully") // Test OpenCV val testMat = Mat(100, 100, CvType.CV_8UC3) PGHLog.d(TAG, "Mat created: ${testMat.rows()}x${testMat.cols()}") // Initialize ONNX YOLO detector for testing - now using MLInferenceEngine in service // yoloDetector = YOLOOnnxDetector(this) // if (yoloDetector!!.initialize()) { // PGHLog.d(TAG, "โœ… ONNX YOLO detector initialized successfully") // } else { // PGHLog.e(TAG, "โŒ ONNX YOLO detector initialization failed") // } PGHLog.d(TAG, "โœ… Using new MLInferenceEngine architecture in ScreenCaptureService") } else { PGHLog.e(TAG, "OpenCV initialization failed") } } private fun testYOLODetection() { PGHLog.i(TAG, "๐Ÿงช YOLO testing now handled by MLInferenceEngine in ScreenCaptureService") // yoloDetector?.testWithStaticImage() } private fun requestScreenCapturePermission() { // Check notification permission first (Android 13+) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) return } } // Check overlay permission if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(this)) { requestOverlayPermission() return } } proceedWithScreenCapture() } private fun proceedWithScreenCapture() { mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager val captureIntent = mediaProjectionManager.createScreenCaptureIntent() screenCapturePermissionLauncher.launch(captureIntent) } private val notificationPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted -> if (isGranted) { PGHLog.d(TAG, "Notification permission granted, checking overlay permission") requestScreenCapturePermission() // Re-check other permissions } else { PGHLog.e(TAG, "Notification permission denied") } } private val overlayPermissionLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { _ -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Settings.canDrawOverlays(this)) { PGHLog.d(TAG, "Overlay permission granted, proceeding with screen capture") proceedWithScreenCapture() } else { PGHLog.e(TAG, "Overlay permission denied") } } } private fun requestOverlayPermission() { val intent = Intent( Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName") ) overlayPermissionLauncher.launch(intent) } private fun startScreenCaptureService(data: Intent) { val serviceIntent = Intent(this, ScreenCaptureService::class.java).apply { action = ScreenCaptureService.ACTION_START putExtra(ScreenCaptureService.EXTRA_RESULT_DATA, data) } startForegroundService(serviceIntent) } private fun stopScreenCaptureService() { val serviceIntent = Intent(this, ScreenCaptureService::class.java).apply { action = ScreenCaptureService.ACTION_STOP } startService(serviceIntent) isCapturing = false } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { PokeGoalsHelperTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> ScreenCaptureUI( isCapturing = isCapturing, onStartCapture = { requestScreenCapturePermission() }, onStopCapture = { stopScreenCaptureService() }, onTestYOLO = { testYOLODetection() }, modifier = Modifier.padding(innerPadding) ) } } } } override fun onResume() { super.onResume() initializeOpenCV() } } @Composable fun ScreenCaptureUI( isCapturing: Boolean, onStartCapture: () -> Unit, onStopCapture: () -> Unit, onTestYOLO: () -> Unit, modifier: Modifier = Modifier ) { Column( modifier = modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Card( modifier = Modifier.fillMaxWidth(), elevation = CardDefaults.cardElevation(defaultElevation = 8.dp) ) { Column( modifier = Modifier.padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Pokemon Home Analysis", style = MaterialTheme.typography.headlineMedium, modifier = Modifier.padding(bottom = 16.dp) ) Text( text = if (isCapturing) { "Actively monitoring screen for Pokemon data" } else { "Ready to analyze Pokemon Home screens" }, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(bottom = 24.dp) ) if (isCapturing) { Button( onClick = onStopCapture, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.error ), modifier = Modifier.fillMaxWidth() ) { Text("Stop Analysis") } } else { Button( onClick = onStartCapture, modifier = Modifier.fillMaxWidth() ) { Text("Start Pokemon Analysis") } } if (isCapturing) { Spacer(modifier = Modifier.height(16.dp)) Text( text = "๐Ÿ“ฑ Minimize this app and open Pokemon Home", style = MaterialTheme.typography.bodySmall ) } Spacer(modifier = Modifier.height(16.dp)) Button( onClick = onTestYOLO, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.secondary ), modifier = Modifier.fillMaxWidth() ) { Text("๐Ÿงช Test YOLO Detection") } } } Spacer(modifier = Modifier.height(32.dp)) Text( text = "Note: This app will request screen capture permission. A notification will show while analysis is active.", style = MaterialTheme.typography.bodySmall, modifier = Modifier.padding(horizontal = 16.dp) ) } } @Preview(showBackground = true) @Composable fun ScreenCaptureUIPreview() { PokeGoalsHelperTheme { ScreenCaptureUI( isCapturing = false, onStartCapture = {}, onStopCapture = {}, onTestYOLO = {} ) } }