Success with Flutter integration! (almost)

Hi guys,

I’m experimenting with MOE and Flutter together in order to have a real common source base for both Android and iOS.

I’ve got most of it working but I’m stuck on a minor(?) problem with the binding.

To give you a bit of background, what I did is the following.

  • In Android Studio I’ve installed both MOE and Flutter plugin.
  • I’ve created a new MOE project with 3 modules, android, common and ios.
  • I’ve added support for CocoaPod to the ios module.
  • I’ve created a new flutter module following
  • I’ve created a binding for the Flutter framework
  • I’ve adapted the Objective-C code from the link above to the binding code in MOE.
  • I’ve disabled the storyboard in xcode and forced the AppDelegate to load the FlutterViewController

And, it works! :slight_smile: It was straightforward and it’s working really well, I’m really happy with this.

The next step is to call native code from Flutter, and here I’m stuck.

I’m following and at some point they call this:

FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
[batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    // TODO

The moeNatJGen gradlew task generated FlutterMethodChannel but not the setMethodCallHandler method.

I looked in the log and there are exactly 5 skipped methods in all the framework, including this one (how lucky! :sob: )

This is the log:

**Skipping:**  setMessageHandler: in FlutterBasicMessageChannel (Objective-C Instance Method) reason:  *unhadled callback at arg([email protected]) type [^(void)(@id, ^(void)(@id))]*
**Skipping:**  userNotificationCenter:willPresentNotification:withCompletionHandler: in FlutterPluginAppLifeCycleDelegate (Objective-C Instance Method) reason:  *bad argument(1) type [object type 'UNNotification' is not processed]*
**Skipping:**  setMethodCallHandler: in FlutterMethodChannel (Objective-C Instance Method) reason:  *unhadled callback at arg([email protected]) type [^(void)(FlutterMethodCall*, ^(void)(@id))]*
**Skipping:**  setMessageHandlerOnChannel:binaryMessageHandler: in FlutterBinaryMessenger (Objective-C Instance Method) reason:  *unhadled callback at arg([email protected]) type [^(void)(NSData*, ^(void)(NSData*))]*
**Skipping:**  userNotificationCenter:willPresentNotification:withCompletionHandler: in FlutterPlugin (Objective-C Instance Method) reason:  *bad argument(1) type [object type 'UNNotification' is not processed]*

I was thinking that maybe I can fix the binding code manually, it’s not the first method I bind myself, but in this particular case I don’t know how to proceed.

The relevant parts from the header file (FlutterChannels.h) are these:

typedef void (^FlutterResult)(id _Nullable result);
typedef void (^FlutterMethodCallHandler)(FlutterMethodCall* call, FlutterResult result);
- (void)setMethodCallHandler:(FlutterMethodCallHandler _Nullable)handler;

Any idea how can I bind the setMethodCallHandler method? I don’t mind about the other methods for now. This is really blocking me on the last step of this project.

Thanks for the help!

1 Like

Flutter is cross-platform so why would you need MOE?

Up until now I always wrote my apps in java, with as much code as possible in a common module.
There are few components that access native functionalities like the camera or the GPS that are kept separated, but this is a minority of the code.
What biggest non-common code is the UI. I don’t like the interface builder of xcode, I prefer to code my layout. It works, I have full control and everything is as I want it, but having to maintain 2 searate UIs is boring and take time.

With Flutter as a module I can migrate the native UI to a Flutter one, one bit at a time. This will reduce the amount of non-shared code to almost 0.

I know I can start from scratch but I don’t want to loose my existing codebase, or handy stuff like retrofit.

I’ve started looking into Flutter only yesterday and I’m amazed I was able to take it so far in only a day. I can say I’ve met my goal.

For my original problem, I still have to find a good solution, but I was able to work around it making a wrapper method in Objective-C.

Of course I’m still interested if someone has a pure NatJ solution.

Going back to the original problem, I’ve tried this but it doesn’t work.

public native void setMethodCallHandler(@ObjCBlock(name = "handle") FlutterMethodCallHandler callback);

public interface FlutterMethodCallHandler {
	void handle(
	        FlutterMethodCall call,
                    @ObjCBlock(name = "call") FlutterResult result

public interface FlutterResult {
	void call(@Mapped(ObjCObjectMapper.class) Object result

It doesn’t give me any error at compile time.

At runtime it doesn’t crash or anything, but if I use the debugger on setMethodCallHandler I see that the parameter is null. In java I’ve confirmed that it isn’t null and it’s valid.

Any idea?

How about doing this?

@ObjCBlock(name = "handle")
@ObjCBlock(name = "call_setMethodCallHandler")

void handle(
void call_setMethodCallHandler(

In my case, the name mismatch affected the behavior.

public interface Aaa {
	void setCcc(@ObjCBlock(name = "call_setBbb") Block_ddd value);

	public interface Block_ddd {
		void call_setBbb(NSDictionary<?, ?> arg0);

If rename call_setBbb to call_setBbb2 then

RuntimeException: Could not find Java method for native callback!

Thank you @ark100 , I’ll give it a shot later, but I don’t think this is it.
Originally I was using a naming convention that I mimiked from a @Generated bind and it beginned with call_ .

The docs about ObjCBlock say that the “name” attribute must match the name in the interface, nothing else, but maybe that’s outdated.

The thing is that I don’t get a RuntimeException, the Object-C method is invoked, but the parameter that get passed seems to be null, while in java it’s not.

Maybe it’s better if I do a proof of concept of the problem, who knows, maybe I discovered a bug or I’m hitting a corner case.

Thank you @ark100, I’ve tested your idea. The call_ prefix doesn’t change the behaviour but the Block_ prefix in the interface name does change a lot of thing.
It doesn’t work yet but I’m doing various experiments. I think that this may be the right direction.

I’ve made a progress I think. This is the code I’m testing now:

public native void setMethodCallHandler(@ObjCBlock(name = "call_A") Block_FlutterMethodCallHandler handler);

public interface Block_FlutterMethodCallHandler {
    void call_A(
            FlutterMethodCall call,
            @ObjCBlock(name = "call_B") Block_FlutterResult result

public interface Block_FlutterResult {
    void call_B(@Mapped(ObjCObjectMapper.class) Object result

If I name the interface FlutterMethodCallHandler instead of Block_FlutterMethodCallHandler then the handler argument is null in ObjC. With the right name the argument get the right value, and this is the first step forward.

Changing the call_* method names doesn’t seems to affect the behaviour in any way.

When the call_A method is invoked from ObjC I get this error:

Terminating app due to uncaught exception 'java.lang.NullPointerException', reason: 'java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String' on a null object reference
at apple.uikit.c.UIKit.UIApplicationMain(Native Method)
at com.example.myapp.Main.main(

The source for ObjCCallbackMapper is here

The problem is with the second argument of call_A. If I use anything that is not a block it works as expected.

In practice if the second argument is not a block the binding code can be automatically generated by NatJ, it’s only when it’s a block that NatJ skip it.


For workarounds or narrow down the problem,
how about via the Objective-C implementation?

At that time, wrapping Blocks is one means.
java --(protocol/class)–> adapter --(blocks)–> Flutter --(blocks)–> adapter --(protocol/class)–> java

(code image)


@interface FlutterResultWrap : NSObject

@protocol Handler<NSObject>
- (void)handle:(FlutterMethodCall*)call result:(FlutterResultWrap*)result;

@interface Adapter : NSObject

@implementation Adapter
- (id)init:(Handler*)cb
{ ... }
- setMethodCallHandlerAdp()
	__weak typeof(self) weakSelf = self;
	[channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResultWrap result) {
		[weakSelf->cb handle:call result: [[FlutterResultWrap alloc] init:result] ];


class A extends NSObject implements Handler {
	void f(){
		adapter = Adapter.alloc().init(this);
	public void handleResult(FlutterMethodCall call, FlutterResultWrap result){

On another note.
If my memory is correct, if _Nullable(or _Nonnull) is included in the definition, auto generation at NatJ was skipped.

Thank you @ark100, quoting from my 2nd comment

The wrapper I was referring to is pretty much what you propose, and it works really well.

The reasons I’m still trying to find a solution that doesn’t involve a wrapper are that I want ti learn more about the internals of NatJ / MOE and that I’d like to see this fixed one day. If I understand it well enough to fix the problem maybe I can send a pull request. Sadly I don’t expect Migeran to work on this any time soon.

Days ago I’ve tested it without _Nullable, NatJ still skip the method with the same reason.

Hi @martinellimarco, I may be in the same situation than you in the next months, with a common module and two separate code bases for the UI that I wish I can migrate to Flutter.
Have you considered writing a piece of blog about your experience? I would be very interested!

1 Like

Hi @t.gallinari, sorry for the late reply but I’ve got a flu.
I don’t have a blog but I’ll be more than happy to help you if you’ll need. Mention me in a message here and I’ll reply as soon as I can.