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 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 com.quillstudios.pokegoalshelper.ui.FloatingUIActivity 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 private var yoloDetector_tflite: YOLOTFLiteDetector? = null private lateinit var mediaProjectionManager: MediaProjectionManager private val screenCapturePermissionLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> Log.d(TAG, "Screen capture permission result: ${result.resultCode}") if (result.resultCode == Activity.RESULT_OK) { val data = result.data if (data != null) { try { startScreenCaptureService(data) startFloatingUI() isCapturing = true Log.d(TAG, "Screen capture service started successfully") } catch (e: Exception) { Log.e(TAG, "Failed to start screen capture service", e) isCapturing = false } } else { Log.e(TAG, "Screen capture permission granted but no data received") } } else { Log.e(TAG, "Screen capture permission denied with result code: ${result.resultCode}") } } private fun initializeOpenCV() { if (OpenCVLoader.initLocal()) { Log.d(TAG, "OpenCV loaded successfully") // Test OpenCV val testMat = Mat(100, 100, CvType.CV_8UC3) Log.d(TAG, "Mat created: ${testMat.rows()}x${testMat.cols()}") // Initialize ONNX YOLO detector for testing yoloDetector = YOLOOnnxDetector(this) //yoloDetector_tflite = YOLOTFLiteDetector(this) if (yoloDetector!!.initialize()) { Log.d(TAG, "โœ… ONNX YOLO detector initialized successfully") } else { Log.e(TAG, "โŒ ONNX YOLO detector initialization failed") } } else { Log.e(TAG, "OpenCV initialization failed") } } private fun testYOLODetection() { Log.i(TAG, "๐Ÿงช Starting ONNX YOLO test with static image...") 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) { Log.d(TAG, "Notification permission granted, checking overlay permission") requestScreenCapturePermission() // Re-check other permissions } else { Log.e(TAG, "Notification permission denied") } } private val overlayPermissionLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { _ -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Settings.canDrawOverlays(this)) { Log.d(TAG, "Overlay permission granted, proceeding with screen capture") proceedWithScreenCapture() } else { Log.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 } private fun startFloatingUI() { val floatingUIIntent = Intent(this, FloatingUIActivity::class.java).apply { action = FloatingUIActivity.ACTION_SHOW_FAB flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } startActivity(floatingUIIntent) Log.d(TAG, "FloatingUIActivity started") } 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 = {} ) } }