Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using flutter_blue together with android-long-task leads to a PlatformException #2

Closed
ahoelzemann opened this issue May 18, 2021 · 4 comments

Comments

@ahoelzemann
Copy link

ahoelzemann commented May 18, 2021

Hey @easazade ,

I'm trying to use your package to download files from a BLE device in the background. It runs fine so far. However, I receive the following exception when I try to run any function from flutter_blue https://pub.dev/packages/flutter_blue

As soon as I try to run my initialization function for the BLEManager

Future<bool> asyncInit() async {
   flutterBlue = FlutterBlue.instance;
   await flutterBlue.stopScan();
   for (var device in await flutterBlue.connectedDevices) {
     await device.disconnect();
   }
   return true;
 }

I get the following exception:

E/flutter (11319): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: MissingPluginException(No implementation found for method isAvailable on channel plugins.pauldemarco.com/flutter_blue/methods)
E/flutter (11319): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:175:7)
E/flutter (11319):
E/flutter (11319): #.1 FlutterBlue._setLogLevelIfAvailable (package:flutter_blue/src/flutter_blue.dart:78:9)
E/flutter (11319):
E/flutter (11319):

Any idea what's going wrong?

best regards and thanks for the nice plugin!

@2math
Copy link

2math commented May 28, 2021

I have the same issue while testing the plugin on my side with Location plugin.
At the same time I can make network calls and use the http plugin

serviceMain() async {
  WidgetsFlutterBinding.ensureInitialized();

  ServiceClient.setExecutionCallback((initialData) async {
    var serviceData = AppServiceData.fromJson(initialData);

    Log.w('initialData : $serviceData', "tag");

    var body = {
      'userId': "me",
      'password': "123",
    };

    Call call = Call.name(CallMethod.POST, 'v1/login', body: jsonEncode(body), refreshOn401: false);

    var serverData = await BaseNetworkManager().doServerCall(call, (json) {
      return jsonDecode(json);
    }).catchError((e) {
      Log.error("login", error: e);
    });

    Log.i('server data : $serverData', "tag");

    var locationData = await Location().hasPermission().catchError((e){
      Log.error("Location", error: e);
    });

    Log.i("my location $locationData");
  });
}

The crash log when I call Location().hasPermission()

E/MethodChannel#lyokone/location( 5972): Failed to handle method call
E/MethodChannel#lyokone/location( 5972): java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.lyokone.location.FlutterLocation.checkPermissions()' on a null object reference
E/MethodChannel#lyokone/location( 5972): 	at com.lyokone.location.MethodCallHandlerImpl.onHasPermission(MethodCallHandlerImpl.java:123)
E/MethodChannel#lyokone/location( 5972): 	at com.lyokone.location.MethodCallHandlerImpl.onMethodCall(MethodCallHandlerImpl.java:41)
E/MethodChannel#lyokone/location( 5972): 	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/MethodChannel#lyokone/location( 5972): 	at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
E/MethodChannel#lyokone/location( 5972): 	at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:738)
E/MethodChannel#lyokone/location( 5972): 	at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#lyokone/location( 5972): 	at android.os.MessageQueue.next(MessageQueue.java:335)
E/MethodChannel#lyokone/location( 5972): 	at android.os.Looper.loop(Looper.java:183)
E/MethodChannel#lyokone/location( 5972): 	at android.app.ActivityThread.main(ActivityThread.java:7660)
E/MethodChannel#lyokone/location( 5972): 	at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#lyokone/location( 5972): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
E/MethodChannel#lyokone/location( 5972): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

I think such a plugins needs to be registered again for the foreground service, because probably runs in another isolate.
Here is what the guys from flt_worker has to let the devs to register extra plugins in the background isolate
https://github.com/xinthink/flt_worker/blob/4e93edfe02e3d1eba05230233d29d25ead2bd085/android/src/main/java/dev/thinkng/flt_worker/internal/BackgroundWorkerPlugin.java#L100

Then in my activity I can register such a plugins :

public class MainActivity extends FlutterFragmentActivity {
    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);

        // set a callback to register all plugins to a headless engine instance
        FltWorkerPlugin.registerPluginsForWorkers = registry -> {
            io.flutter.plugins.pathprovider.PathProviderPlugin.registerWith(
                    registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));

            io.flutter.plugins.connectivity.ConnectivityPlugin.registerWith(registry.registrarFor("io.flutter.plugins.connectivity.ConnectivityPlugin"));

            io.flutter.plugins.deviceinfo.DeviceInfoPlugin.registerWith(registry.registrarFor("io.flutter.plugins.deviceinfo.DeviceInfoPlugin"));

            com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"));

            io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));

            com.tekartik.sqflite.SqflitePlugin.registerWith(registry.registrarFor("com.tekartik.sqflite.SqflitePlugin"));

            return null;
        };
    }
}

On flutter_workmanager they have even a way that auto register all plugins on android
https://github.com/fluttercommunity/flutter_workmanager/blob/master/android/src/main/kotlin/be/tramckrijte/workmanager/BackgroundWorker.kt#L80

@2math
Copy link

2math commented May 31, 2021

I have tried to manually register location package from the foreground service, but this is not the case. I can see a log message that this plugin is already registered for this FlutterEngine, so my comment above is invalid and you don't need to register any external plugins.
However the problem with location plugin is in the plugin it self, which require an activity to work.

@easazade , probably this is the problem with your plugin too?

@2math
Copy link

2math commented Jun 4, 2021

With https://github.com/Baseflow/flutter-geolocator I can get locations and everything works great. So I confirm the problem is with Location plugin, which apparently needs an activity to work

@easazade
Copy link
Owner

accessing location on background and foreground is different. and I mean natively different and you should use a different library for that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants