@@ -147,39 +147,44 @@ class MainActivity : ComponentActivity() {
147147 }
148148 }
149149
150- fun getPhotoReasoningViewModel (): com.google.ai.sample.feature.multimodal.PhotoReasoningViewModel ? {
151- return photoReasoningViewModel
150+ // Corrected: Made public to be accessible from ViewModels and other classes
151+ fun getCurrentApiKey (): String? {
152+ return if (::apiKeyManager.isInitialized) {
153+ apiKeyManager.getCurrentApiKey()
154+ } else {
155+ null
156+ }
152157 }
153158
154- fun setPhotoReasoningViewModel (viewModel : com.google.ai.sample.feature.multimodal.PhotoReasoningViewModel ) {
155- photoReasoningViewModel = viewModel
159+ // Corrected: Made internal to be accessible from other classes in the same module
160+ internal fun checkAccessibilityServiceEnabled (): Boolean {
161+ // Dummy implementation - replace with actual check
162+ Log .d(TAG , " Checking accessibility service (dummy check)." )
163+ val service = packageName + " /" + ScreenOperatorAccessibilityService ::class .java.canonicalName
164+ val enabledServices = Settings .Secure .getString(contentResolver, Settings .Secure .ENABLED_ACCESSIBILITY_SERVICES )
165+ val isEnabled = enabledServices?.contains(service, ignoreCase = true ) == true
166+ if (! isEnabled) {
167+ Log .d(TAG , " Accessibility Service not enabled. Prompting user." )
168+ // Optionally, prompt user to enable it here or show a persistent message
169+ }
170+ return isEnabled
156171 }
157172
158- private val requiredPermissions = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
159- arrayOf(
160- Manifest .permission.READ_MEDIA_IMAGES ,
161- Manifest .permission.READ_MEDIA_VIDEO ,
162- Manifest .permission.POST_NOTIFICATIONS // For foreground service notifications if used
163- )
164- } else {
165- arrayOf(
166- Manifest .permission.READ_EXTERNAL_STORAGE ,
167- Manifest .permission.WRITE_EXTERNAL_STORAGE
168- )
173+ // Corrected: Made internal to be accessible from other classes in the same module
174+ internal fun requestManageExternalStoragePermission () {
175+ // Dummy implementation - replace with actual request if needed for specific Android versions
176+ Log .d(TAG , " Requesting manage external storage permission (dummy)." )
169177 }
170178
171- private val requestPermissionLauncher = registerForActivityResult(
172- ActivityResultContracts .RequestMultiplePermissions ()
173- ) { permissions ->
174- val allGranted = permissions.entries.all { it.value }
175- if (allGranted) {
176- Log .d(TAG , " All permissions granted" )
177- Toast .makeText(this , " Alle Berechtigungen erteilt" , Toast .LENGTH_SHORT ).show()
178- startTrialServiceIfNeeded()
179+ // Corrected: Changed signature to accept a Boolean for error state
180+ fun updateStatusMessage (message : String , isError : Boolean = false) {
181+ // Displaying as a Toast for now, can be changed to Snackbar or other UI element
182+ // You might want to change the Toast duration or appearance based on isError
183+ Toast .makeText(this , message, if (isError) Toast .LENGTH_LONG else Toast .LENGTH_SHORT ).show()
184+ if (isError) {
185+ Log .e(TAG , " Status Message (Error): $message " )
179186 } else {
180- Log .d(TAG , " Some permissions denied" )
181- Toast .makeText(this , " Einige Berechtigungen wurden verweigert. Die App benötigt diese für volle Funktionalität." , Toast .LENGTH_LONG ).show()
182- // Handle specific permission denials if necessary
187+ Log .d(TAG , " Status Message: $message " )
183188 }
184189 }
185190
@@ -189,13 +194,13 @@ class MainActivity : ComponentActivity() {
189194 Log .d(TAG , " onCreate: Setting MainActivity instance" )
190195
191196 apiKeyManager = ApiKeyManager .getInstance(this )
192- val apiKey = apiKeyManager. getCurrentApiKey()
197+ val apiKey = getCurrentApiKey() // Use the corrected public method
193198 if (apiKey.isNullOrEmpty()) {
194199 showApiKeyDialog = true
195200 }
196201
197202 checkAndRequestPermissions()
198- checkAccessibilityServiceEnabled()
203+ checkAccessibilityServiceEnabled() // Call the corrected internal method
199204 setupBillingClient()
200205
201206 TrialManager .initializeTrialStateFlagsIfNecessary(this )
@@ -268,14 +273,14 @@ class MainActivity : ComponentActivity() {
268273 if (isAppUsable) {
269274 navController.navigate(routeId)
270275 } else {
271- Toast .makeText( this @MainActivity, trialInfoMessage, Toast . LENGTH_LONG ).show( )
276+ updateStatusMessage( trialInfoMessage, isError = true )
272277 }
273278 },
274279 onApiKeyButtonClicked = {
275280 if (isAppUsable) {
276281 showApiKeyDialog = true
277282 } else {
278- Toast .makeText( this @MainActivity, trialInfoMessage, Toast . LENGTH_LONG ).show( )
283+ updateStatusMessage( trialInfoMessage, isError = true )
279284 }
280285 },
281286 onDonationButtonClicked = { initiateDonationPurchase() },
@@ -290,7 +295,7 @@ class MainActivity : ComponentActivity() {
290295 } else {
291296 LaunchedEffect (Unit ) {
292297 navController.popBackStack()
293- Toast .makeText( this @MainActivity, trialInfoMessage, Toast . LENGTH_LONG ).show( )
298+ updateStatusMessage( trialInfoMessage, isError = true )
294299 }
295300 }
296301 }
@@ -354,23 +359,23 @@ class MainActivity : ComponentActivity() {
354359 private fun initiateDonationPurchase () {
355360 if (! billingClient.isReady) {
356361 Log .e(TAG , " BillingClient not ready." )
357- Toast .makeText( this , " Bezahldienst nicht bereit. Bitte später versuchen." , Toast . LENGTH_SHORT ).show( )
362+ updateStatusMessage( " Bezahldienst nicht bereit. Bitte später versuchen." , true )
358363 if (billingClient.connectionState == BillingClient .ConnectionState .CLOSED || billingClient.connectionState == BillingClient .ConnectionState .DISCONNECTED ){
359364 setupBillingClient()
360365 }
361366 return
362367 }
363368 if (monthlyDonationProductDetails == null ) {
364369 Log .e(TAG , " Product details not loaded yet." )
365- Toast .makeText( this , " Spendeninformationen werden geladen. Bitte kurz warten und erneut versuchen." , Toast . LENGTH_LONG ).show( )
370+ updateStatusMessage( " Spendeninformationen werden geladen. Bitte kurz warten und erneut versuchen." , true )
366371 queryProductDetails()
367372 return
368373 }
369374 monthlyDonationProductDetails?.let { productDetails ->
370375 val offerToken = productDetails.subscriptionOfferDetails?.firstOrNull()?.offerToken
371376 if (offerToken == null ) {
372377 Log .e(TAG , " No offer token found for product: ${productDetails.productId} " )
373- Toast .makeText( this , " Spendenangebot nicht gefunden." , Toast . LENGTH_LONG ).show( )
378+ updateStatusMessage( " Spendenangebot nicht gefunden." , true )
374379 return @let
375380 }
376381 val productDetailsParamsList = listOf (
@@ -385,9 +390,11 @@ class MainActivity : ComponentActivity() {
385390 val billingResult = billingClient.launchBillingFlow(this , billingFlowParams)
386391 if (billingResult.responseCode != BillingClient .BillingResponseCode .OK ) {
387392 Log .e(TAG , " Failed to launch billing flow: ${billingResult.debugMessage} " )
393+ updateStatusMessage(" Fehler beim Starten des Spendevorgangs: ${billingResult.debugMessage} " , true )
388394 }
389395 } ? : run {
390396 Log .e(TAG , " Donation product details are null." )
397+ updateStatusMessage(" Spendenprodukt nicht verfügbar." , true )
391398 }
392399 }
393400
@@ -401,25 +408,26 @@ class MainActivity : ComponentActivity() {
401408 billingClient.acknowledgePurchase(acknowledgePurchaseParams) { ackBillingResult ->
402409 if (ackBillingResult.responseCode == BillingClient .BillingResponseCode .OK ) {
403410 Log .d(TAG , " Subscription purchase acknowledged." )
404- Toast .makeText( this , " Vielen Dank für Ihr Abonnement!" , Toast . LENGTH_LONG ).show( )
411+ updateStatusMessage( " Vielen Dank für Ihr Abonnement!" )
405412 TrialManager .markAsPurchased(this )
406413 updateTrialState(TrialManager .TrialState .PURCHASED )
407414 val stopIntent = Intent (this , TrialTimerService ::class .java)
408415 stopIntent.action = TrialTimerService .ACTION_STOP_TIMER
409416 startService(stopIntent) // Stop the service
410417 } else {
411418 Log .e(TAG , " Failed to acknowledge purchase: ${ackBillingResult.debugMessage} " )
419+ updateStatusMessage(" Fehler beim Bestätigen des Kaufs: ${ackBillingResult.debugMessage} " , true )
412420 }
413421 }
414422 } else {
415423 Log .d(TAG , " Subscription already acknowledged." )
416- Toast .makeText( this , " Abonnement bereits aktiv." , Toast . LENGTH_LONG ).show( )
424+ updateStatusMessage( " Abonnement bereits aktiv." )
417425 TrialManager .markAsPurchased(this ) // Ensure state is correct
418426 updateTrialState(TrialManager .TrialState .PURCHASED )
419427 }
420428 }
421429 } else if (purchase.purchaseState == Purchase .PurchaseState .PENDING ) {
422- Toast .makeText( this , " Ihre Zahlung ist in Bearbeitung." , Toast . LENGTH_LONG ).show( )
430+ updateStatusMessage( " Ihre Zahlung ist in Bearbeitung." )
423431 }
424432 }
425433
@@ -461,6 +469,7 @@ class MainActivity : ComponentActivity() {
461469 override fun onResume () {
462470 super .onResume()
463471 instance = this
472+ Log .d(TAG , " onResume: Setting MainActivity instance" )
464473 checkAccessibilityServiceEnabled()
465474 if (::billingClient.isInitialized && billingClient.isReady) {
466475 queryActiveSubscriptions() // This will also trigger trial state updates
@@ -494,36 +503,34 @@ class MainActivity : ComponentActivity() {
494503 }
495504 }
496505
497- // Made internal to be accessible from other classes in the same module
498- internal fun checkAccessibilityServiceEnabled () {
499- // Dummy implementation
500- Log .d(TAG , " Checking accessibility service (dummy check)." )
501- // Consider providing a real implementation or a way for other classes to know the status
502- }
503-
504- // Made internal to be accessible from other classes in the same module
505- internal fun requestManageExternalStoragePermission () {
506- // Dummy implementation
507- Log .d(TAG , " Requesting manage external storage permission (dummy)." )
508- // Consider providing a real implementation
506+ private val requiredPermissions = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
507+ arrayOf(
508+ Manifest .permission.READ_MEDIA_IMAGES ,
509+ Manifest .permission.READ_MEDIA_VIDEO ,
510+ Manifest .permission.POST_NOTIFICATIONS // For foreground service notifications if used
511+ )
512+ } else {
513+ arrayOf(
514+ Manifest .permission.READ_EXTERNAL_STORAGE ,
515+ Manifest .permission.WRITE_EXTERNAL_STORAGE
516+ )
509517 }
510518
511- // Added to provide API key to other classes like ViewModels
512- fun getCurrentApiKey (): String? {
513- return if (::apiKeyManager.isInitialized) {
514- apiKeyManager.getCurrentApiKey()
519+ private val requestPermissionLauncher = registerForActivityResult(
520+ ActivityResultContracts .RequestMultiplePermissions ()
521+ ) { permissions ->
522+ val allGranted = permissions.entries.all { it.value }
523+ if (allGranted) {
524+ Log .d(TAG , " All permissions granted" )
525+ updateStatusMessage(" Alle Berechtigungen erteilt" )
526+ startTrialServiceIfNeeded()
515527 } else {
516- null
528+ Log .d(TAG , " Some permissions denied" )
529+ updateStatusMessage(" Einige Berechtigungen wurden verweigert. Die App benötigt diese für volle Funktionalität." , true )
530+ // Handle specific permission denials if necessary
517531 }
518532 }
519533
520- // Added to allow other classes to show messages to the user via MainActivity
521- fun updateStatusMessage (message : String ) {
522- // Displaying as a Toast for now, can be changed to Snackbar or other UI element
523- Toast .makeText(this , message, Toast .LENGTH_LONG ).show()
524- Log .d(TAG , " Status Message Updated: $message " )
525- }
526-
527534 companion object {
528535 private const val TAG = " MainActivity"
529536 private var instance: MainActivity ? = null
@@ -536,7 +543,7 @@ class MainActivity : ComponentActivity() {
536543@Composable
537544fun TrialExpiredDialog (
538545 onPurchaseClick : () -> Unit ,
539- onDismiss : () -> Unit
546+ onDismiss : () -> Unit // Usually, a persistent dialog isn't dismissed by user action other than purchase
540547) {
541548 Dialog (onDismissRequest = onDismiss) {
542549 Card (
0 commit comments