hooperdev
hooperdev

Reputation: 951

How do I call Dart code from Android service?

I have a background service in Android that I call in my Flutter Dart code using

  var methodChannel = MethodChannel("org.companyname.app.backgroundlocation");
    methodChannel.invokeMethod("startBackgroundService", {
      "encKey" : encryptionKey
    });

I use a flutter library called simple rsa to encrypt location. However, Android doesn't seem to have an equivalent. So, my question is:

Can I call Dart code from my Android code like I do with the Flutter MethodChannel to call Android code?

I have checked this github issue, but there are no actual answers that I can find.

Upvotes: 11

Views: 2956

Answers (2)

T. Johnny
T. Johnny

Reputation: 118

I don't know how effective it is but it works :D

private static final String CHANNEL = "widget.filc.hu/timetable";
// You have to run this on the main thread, i think
public static MethodChannel GetMethodChannel(Context context) {
    FlutterMain.startInitialization(context);
    FlutterMain.ensureInitializationComplete(context, new String[0]);

    FlutterEngine engine = new FlutterEngine(context.getApplicationContext());


    DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint("lib/main.dart", "widget");

    engine.getDartExecutor().executeDartEntrypoint(entrypoint);
    return new MethodChannel(engine.getDartExecutor().getBinaryMessenger(), CHANNEL);
}

The dart side has an init function like this:

void widget() async {
    // get preferences everything what you want....
  
    await app.settings.update();
    // Create methodChannel
    const MethodChannel channel = MethodChannel(CHANNEL);
    channel.setMethodCallHandler(
     (call) async {
      final args = call.arguments;

      print('on Dart ${call.method}!');

      switch (call.method) {
      case 'getTimetable':
        return await _getTimetable();
      case 'getRandom':
        return Random().nextInt(100);
      case 'initialize':
        return "HELLO";
      default:
        throw UnimplementedError("Unknow: " + call.method);
    }
  },
);
}

These links are helped me:

Upvotes: 10

Fahim Muntashir
Fahim Muntashir

Reputation: 41

Follow the steps for enabling a plugin to execute headless Dart code as per https://medium.com/flutter-io/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124. This will involve writing a custom Application class with overrides and a service that have code where a PluginRegistrantCallback will registerWith the plugin registry of a background view (e.g. see here. This typically involves a "foreground" platform channel (for lack of a better description) and a background platform channel being established.
Add code on the Android platform side that will execute Dart code normally (i.e. the "non-headless" way) using the following channel.invokeMethod(...) and handle the call on the Flutter side. In the forked repository linked above, whenever a geofence is registered, the Android side will call channel.invokeMethod("register", null) (see here. This caught in the Flutter to call print the name of the method called, which would be "register" in this case (see here
Run the app and invoke code that execute the logic written in step 2 and notice the Flutter side will catch that a method got called from the platform side. You should method called: register in the debugger output
Now invoke logic that triggers headless execution
Invoke the logic that was done in step 2 again and the Flutter side doesn't get notification a method got called from the platform side i.e. method called: register isn't displayed again

I noticed this whilst incorporating headless execution into my own plugin for notifications. It seems like once a background service calls this method that enables headless Dart code to fire code that relies on other plugin, calling invokeMethod on the foreground platform channel no longer works. Am not sure what the solution is here or perhaps there's an issue with the engine itself

[✓] Flutter (Channel beta, v0.9.4, on Mac OS X 10.14 18A391, locale en-AU) • Flutter version 0.9.4 at /Users/michaelbui/flutter • Framework revision f37c235c32 (5 weeks ago), 2018-09-25 17:45:40 -0400 • Engine revision 74625aed32 • Dart version 2.1.0-dev.5.0.flutter-a2eb050044

[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3) • Android SDK at /Users/michaelbui/Library/Android/sdk • Android NDK location not configured (optional; useful for native profiling support) • Platform android-28, build-tools 27.0.3 • ANDROID_HOME = /Users/michaelbui/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06) • All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 10.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 10.1, Build version 10B61 • ios-deploy 1.9.2 • CocoaPods version 1.5.0

[✓] Android Studio (version 3.2) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin version 27.1.1 • Dart plugin version 173.4700 • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)

[✓] IntelliJ IDEA Community Edition (version 2017.3.5) • IntelliJ at /Applications/IntelliJ IDEA CE.app • Flutter plugin version 23.0.2 • Dart plugin version 173.4700

[✓] VS Code (version 1.28.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 2.20.0

[✓] Connected devices (1 available) • Pixel 2 XL • 711KPXV0530842 • android-arm64 • Android 9 (API 28)

• No issues found! check this out

Upvotes: -1

Related Questions