bostrot / flutter_android_pip

Simple Flutter plugin for Android picture in picture mode.
MIT License
14 stars 14 forks source link

Failed to handle method call: Attempt to invoke virtual method 'void android.app.Activity.enterPictureInPictureMode()' on a null object reference #8

Open someq opened 3 years ago

someq commented 3 years ago

I am using flutter_android_pip in my Flutter app to enter PiP mode instead of minimizing the app (when user presses home). It worked fine with code like this:

class _MyWidgetState extends State<MyWidget> with WidgetsBindingObserver {
  ...
  void didChangeAppLifecycleState(AppLifecycleState state) {
     if (state == AppLifecycleState.inactive) {
       _enterPipMode();
     }
     else if (state == AppLifecycleState.resumed) {
       _exitPipMode();
     }
  }
  ...
}

After I have installed Firebase it stopped working with following error:

Failed to handle method call
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Activity.enterPictureInPictureMode()' on a null object reference
    at com.bostrot.flutterandroidpip.FlutterAndroidPipPlugin.onMethodCall(FlutterAndroidPipPlugin.java:26)
    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
    at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
    at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:692)
    at android.os.MessageQueue.nativePollOnce(Native Method)
    at android.os.MessageQueue.next(MessageQueue.java:325)
    at android.os.Looper.loop(Looper.java:142)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Note, it still works if Firebase is not initialized in the code.

Also noted deprecation warning on both plugins:

Note: /.../firebase_core-0.7.0/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: /.../firebase_messaging-8.0.0-dev.15/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: /.../flutter_android_pip-0.0.2/android/src/main/java/com/bostrot/flutterandroidpip/FlutterAndroidPipPlugin.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

Are these plugins incompatible in some way?

someq commented 3 years ago

After digging some code found that PluginRegistry.Registrar which is used to register flutter_android_pip is deprecated (which causes deprecation warning).

Its method activity may return null, if application has no foreground activity (e.g., when it's paused).

Now seems it's an issue with async receiving of native state events in flutter. As I am trying to enter pip mode when app is minified (home button pressed, etc.) it should be called in onPause() callback. But Flutter version of it is called too late to handle the pause. The app is paused, acitivity is no longer visible, thus the error.

It's similar to this case.

Seems Firebase just adds some asynchrounous communication on pause, thats why it does not work with it (firebase takes some time) and works without (firebase does not take any time).

bostrot commented 3 years ago

Interesting. I have to read myself into it but it seems Flutter's Pigeon is the way to go for synchronous messages.

EDIT: pre-release here

someq commented 3 years ago

Indeed Pigeon may work, but right now I made a workaround. It's still asynchronous, but fails less in my case:

Now i can access it from my video screen in flutter:

Downsides of this approach are: