You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
11 KiB

5 months ago
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
5 months ago
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
5 months ago
private lateinit var mediaProjectionManager: MediaProjectionManager
private val screenCapturePermissionLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
PGHLog.d(TAG, "Screen capture permission result: ${result.resultCode}")
5 months ago
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data
if (data != null) {
try {
startScreenCaptureService(data)
// FloatingUI now handled by service overlay
5 months ago
isCapturing = true
PGHLog.d(TAG, "Screen capture service started successfully")
5 months ago
} catch (e: Exception) {
PGHLog.e(TAG, "Failed to start screen capture service", e)
5 months ago
isCapturing = false
}
} else {
PGHLog.e(TAG, "Screen capture permission granted but no data received")
5 months ago
}
} else {
PGHLog.e(TAG, "Screen capture permission denied with result code: ${result.resultCode}")
5 months ago
}
}
private fun initializeOpenCV() {
if (OpenCVLoader.initLocal()) {
PGHLog.d(TAG, "OpenCV loaded successfully")
5 months ago
// Test OpenCV
val testMat = Mat(100, 100, CvType.CV_8UC3)
PGHLog.d(TAG, "Mat created: ${testMat.rows()}x${testMat.cols()}")
5 months ago
// 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")
5 months ago
} else {
PGHLog.e(TAG, "OpenCV initialization failed")
5 months ago
}
}
private fun testYOLODetection() {
PGHLog.i(TAG, "🧪 YOLO testing now handled by MLInferenceEngine in ScreenCaptureService")
// yoloDetector?.testWithStaticImage()
5 months ago
}
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")
5 months ago
requestScreenCapturePermission() // Re-check other permissions
} else {
PGHLog.e(TAG, "Notification permission denied")
5 months ago
}
}
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")
5 months ago
proceedWithScreenCapture()
} else {
PGHLog.e(TAG, "Overlay permission denied")
5 months ago
}
}
}
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 = {}
)
}
}