X-SLAYER / flutter_accessibility_service

Flutter plugin for interacting with Accessibility Service in Android.
https://pub.dev/packages/flutter_accessibility_service
MIT License
37 stars 27 forks source link

Constant crashing used with foreground service #25

Open builtbybrayne opened 8 months ago

builtbybrayne commented 8 months ago

Start fine, but there's some sort of lifecycle issues which inevitably cause it to loop-crash.

I've tried a few different approaches to handle the lifecycles, initialisation, and isolate management, but I have been unable to find an incantation that prevents these errors:

These errors have been preventing us from launching our app for many months now and I simply cannot find a way round them. Any help would be gratefully appreciated! Absolutely mission critical.

FYI: our foreground service runner is https://pub.dev/packages/flutter_foreground_task.

Error 1

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'io.flutter.embedding.engine.renderer.FlutterRenderer io.flutter.embedding.engine.a.r()' on a null object reference
       at io.flutter.embedding.android.FlutterView.attachToFlutterEngine(FlutterView.java:48)
       at slayer.accessibility.service.flutter_accessibility_service.AccessibilityListener.onServiceConnected(AccessibilityListener.java:40)
       at android.accessibilityservice.AccessibilityService.dispatchServiceConnected(AccessibilityService.java:858)
       at android.accessibilityservice.AccessibilityService.-$$Nest$mdispatchServiceConnected()
       at android.accessibilityservice.AccessibilityService$2.onServiceConnected(AccessibilityService.java:2734)
       at android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.lambda$init$0(AccessibilityService.java:2900)
       at android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.$r8$lambda$ufMCaNdIS-PlK1AEBiWmKpGSCoc()
       at android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper$$ExternalSyntheticLambda16.run(:8)
       at android.os.Handler.handleCallback(Handler.java:958)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loopOnce(Looper.java:205)
       at android.os.Looper.loop(Looper.java:294)
       at android.app.ActivityThread.main(ActivityThread.java:8248)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

Error 2

Fatal Exception: java.lang.RuntimeException: Unable to start service slayer.accessibility.service.flutter_accessibility_service.AccessibilityListener@585db68 with null: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.getBooleanExtra(java.lang.String, boolean)' on a null object reference
       at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4880)
       at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2314)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:205)
       at android.os.Looper.loop(Looper.java:294)
       at android.app.ActivityThread.main(ActivityThread.java:8248)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.getBooleanExtra(java.lang.String, boolean)' on a null object reference
       at slayer.accessibility.service.flutter_accessibility_service.AccessibilityListener.onStartCommand(AccessibilityListener.java:3)
       at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4862)
       at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2314)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:205)
       at android.os.Looper.loop(Looper.java:294)
       at android.app.ActivityThread.main(ActivityThread.java:8248)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)       

Error 3

Fatal Exception: java.lang.RuntimeException: Unable to destroy activity {ai.mycopilot.beta/ai.mycopilot.beta.MainActivity}: java.lang.IllegalArgumentException: Receiver not registered: f9.e$a@b92a94a
       at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5654)
       at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:5686)
       at android.app.servertransaction.DestroyActivityItem.execute(DestroyActivityItem.java:47)
       at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:180)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:98)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2468)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:205)
       at android.os.Looper.loop(Looper.java:294)
       at android.app.ActivityThread.main(ActivityThread.java:8248)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by java.lang.IllegalArgumentException: Receiver not registered: f9.e$a@b92a94a
       at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:1671)
       at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1872)
       at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:820)
       at slayer.accessibility.service.flutter_accessibility_service.FlutterAccessibilityServicePlugin.onDetachedFromEngine(FlutterAccessibilityServicePlugin.java:15)
       at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.remove(FlutterEngineConnectionRegistry.java:121)
       at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.remove(FlutterEngineConnectionRegistry.java:16)
       at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.removeAll(FlutterEngineConnectionRegistry.java:11)
       at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.destroy(FlutterEngineConnectionRegistry.java:10)
       at io.flutter.embedding.engine.FlutterEngine.destroy(FlutterEngine.java:31)
       at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onDetach(FlutterActivityAndFragmentDelegate.java:100)
       at io.flutter.embedding.android.FlutterActivity.onDestroy(FlutterActivity.java:18)
       at android.app.Activity.performDestroy(Activity.java:8902)
       at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1491)
       at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5641)
       at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:5686)
       at android.app.servertransaction.DestroyActivityItem.execute(DestroyActivityItem.java:47)
       at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:180)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:98)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2468)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:205)
       at android.os.Looper.loop(Looper.java:294)
       at android.app.ActivityThread.main(ActivityThread.java:8248)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

Error 3

Fatal Exception: java.lang.NoSuchMethodError: No interface method anyMatch(Lj$/util/function/Predicate;)Z in class Lj$/util/stream/Stream; or its super classes (declaration of 'j$.util.stream.Stream' appears in /data/app/~~ZLFWe7X3Fq5Nv8kTOjKieQ==/androidx.test.tools.crawler-MQkMpzA8jfAAOwsP0Op8kw==/base.apk!classes2.dex)
       at io.flutter.embedding.android.FlutterView.sendUserSettingsToFlutter(FlutterView.java:51)
       at io.flutter.embedding.android.FlutterView.attachToFlutterEngine(FlutterView.java:263)
       at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onCreateView(FlutterActivityAndFragmentDelegate.java:130)
       at io.flutter.embedding.android.FlutterActivity.createFlutterView(FlutterActivity.java:18)
       at io.flutter.embedding.android.FlutterActivity.onCreate(FlutterActivity.java:31)
       at android.app.Activity.performCreate(Activity.java:8074)
       at android.app.Activity.performCreate(Activity.java:8054)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1341)
       at androidx.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:2)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3688)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3864)
       at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
       at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2253)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:201)
       at android.os.Looper.loop(Looper.java:288)
       at android.app.ActivityThread.main(ActivityThread.java:7870)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
builtbybrayne commented 8 months ago

FWIW, I am aware of https://github.com/X-SLAYER/flutter_accessibility_service/issues/12 and did follow the advice to move all the accessibility requests to the main activity.

However, by definition my foreground service exists only to watch the accessibility event stream - opening our app if certain conditions are met. Hence, the only call I make in the foreground service is invoking FlutterAccessibilityService.accessStream.

builtbybrayne commented 8 months ago

Also, Flutter Doctor output here, for versions etc:

/usr/local/opt/flutter/bin/flutter doctor --verbose
[✓] Flutter (Channel stable, 3.16.8, on macOS 13.5.2 22G91 darwin-arm64, locale en-GB)
    • Flutter version 3.16.8 on channel stable at /usr/local/opt/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 67457e669f (4 weeks ago), 2024-01-16 16:22:29 -0800
    • Engine revision 6e2ea58a5c
    • Dart version 3.2.5
    • DevTools version 2.28.5

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/al/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)
    • All Android licenses accepted.

[✗] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS and macOS development.
      Download at: https://developer.apple.com/xcode/
      Or install Xcode via the App Store.
      Once installed, run:
        sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
        sudo xcodebuild -runFirstLaunch
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)

[✓] IntelliJ IDEA Ultimate Edition (version 2023.3.2)
    • IntelliJ at /Users/al/Applications/IntelliJ IDEA Ultimate.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 13.5.2 22G91 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 121.0.6167.160

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.
Process finished with exit code 0
tabhishekpaul commented 8 months ago

I'm also facing the same issue when i'm calling stream foreground service any fix....?

tabhishekpaul commented 8 months ago

@X-SLAYER any fix...?

X-SLAYER commented 8 months ago

i will try to investigate on this problem

tabhishekpaul commented 8 months ago

i will try to investigate on this problem

tabhishekpaul commented 7 months ago

@X-SLAYER any solution

doshpin commented 2 months ago

I found a workaround that worked for me (tested with flutter_background_service). When your app is loaded, execute the below command in your main thread (after checking for permissions):

  await FlutterAccessibilityService.getSystemActions();

This will resolve the error and prevent the app from crashing when exited.

See extended example:

  @override
  void initState() {
    requestNotificationsPermission();
    super.initState();
  }

  Future<void> requestNotificationsPermission() async {
    hasAccessibilityPermission =
        await FlutterAccessibilityService.isAccessibilityPermissionEnabled();
    if (!hasAccessibilityPermission) {
      hasAccessibilityPermission =
          await FlutterAccessibilityService.requestAccessibilityPermission();
    }
    if (hasAccessibilityPermission) {
      await FlutterAccessibilityService.getSystemActions();
    }
  }