[JAVA] [Flutter] How to use C / C ++ from Dart?

Such a scene

"I want to use the excellent assets of C / C ++ in ** Flutter **.

Conclusion

Flutter / Dart => C / C ++ is tough

There is an issue "Support integrating with C / C ++ in plugin framework" in the Flutter repository. Unfortunately it looks tough ... (as of June 16, 2018) Let's like a lot to get higher priority! !! !!

In addition, Dart => C / C ++ can be go

Let's go through Java and Swift

Run through with "** Flutter / Dart => Java / Swift => C / C ++**"![^ 1] This time, I will take Android / Java as an example. Of course Kotlin is fine too.

Completion demo

Just Hello World 2018-06-04 01.19.10.gif

Implementation

Call Java from Flutter / Dart

** platform channels ** will be used.

Project creation

flutter create -i swift -a java helloworld

Call Java using channel

Copy the following to main.dart

main.dart


import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('helloworld/hello');
  String _greeting = 'Nothing';

  Future<Null> _getGreeting() async {
    String greeting;
    try {
      final String result = await platform.invokeMethod('getGreeting');
      greeting = result;
    } on PlatformException catch (e) {
      greeting = "Failed to get greeting: '${e.message}'.";
    }

    setState(() {
      _greeting = greeting;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Material(
    child: new Center(
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          new RaisedButton(
            child: new Text('Get Greeting'),
            onPressed: _getGreeting,
          ),
          new Text(_greeting),
        ],
      ),
    ),
  );
  }
}

There are three points.

--static const platform = const MethodChannel ('helloworld / hello'); ← ** MethodChannel ** specified --Future <Null> _getGreeting () async {} ← ** Asynchronous ** call --ʻAwait platform.invokeMethod ('getGreeting'); `← ** Specify method name ** and call

Call C / C ++ from Android / Java

Now that Dart => Java is good, let's write Java => C / C ++ Official document is a must read.

Android Studio environment maintenance

Open only the * android directory * of the previous project in Android Studio. Then open Tool> SDK Manager> SDK Tools and install the following.

Add C / C ++

Added cpp directory to main directory. (The name can be anything, but this time it will be cpp) Then add native-lib.c to the cpp directory and copy and paste the following.

native-lib.c


#include <string.h>
#include <jni.h>

jstring
Java_com_example_helloworld_MainActivity_getGreetingFromJNI( JNIEnv* env, jobject thiz ) {
    return (*env)->NewStringUTF(env, "Hello World. I'm Android.");
}

The function name should be "** Java_path to reach the target java file \ _Hoge.java_method name **".

Create CMakeLists.txt

Create CMakeLists.txt in the app directory and copy and paste the following

CMakeLists.txt


# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.

add_library( # Specifies the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.c )

# Specifies a path to native header files.
include_directories(src/main/cpp/include/)

The last line tells you the location of the header file. I don't need to use the header file this time, but I wrote it because it should be used normally.

Edit MainActivity.java

Copy the following.

MainActivity.java


package com.example.helloworld;

import android.os.Bundle;

import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

public class MainActivity extends FlutterActivity {

  private static final String CHANNEL = "helloworld/hello";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);

    new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
            new MethodCallHandler() {
              @Override
              public void onMethodCall(MethodCall call, Result result) {
                if (call.method.equals("getGreeting")) {
                  String greeting = getGreeting();
                  result.success(greeting);
                } else {
                  result.notImplemented();
                }
              }
            });
  }

  private String getGreeting() {
    return getGreetingFromJNI();
  }

  public native String  getGreetingFromJNI();

  static {
      System.loadLibrary("native-lib");
  }
}

3 points

--private static final String CHANNEL = "helloworld / hello"; ← ** Specify the same Channel name ** as before --static {System.loadLibrary ("native-lib");} .so The file is loaded. --public native String getGreetingFromJNI (); ← ** Specify the previously defined C method **

Gradle link

  1. Right-click on the app directory and select "Link C ++ Project with Gradle"
  2. Select CMake for Build System
  3. Specify CMakeLists.txt created earlier in ProjectPath
  4. Click OK

Completion drawing

It should look like this (The com.example.ndktest part is com.example.helloworld this time) スクリーンショット 2018-06-04 1.40.58.png

If cannot resolve symbol appears

Select File> Invalidate Caches / Restart ... to restart

Start-up

If you can get the behavior like [Demo](#Complete demo), it's OK!

in conclusion

It's a hassle to write both java and swift to call C / C ++. I can't wait for the github issue to be resolved ...

[^ 1]: The reason for choosing Java is that the amount of information about NDK is Java> Kotlin.

Recommended Posts

[Flutter] How to use C / C ++ from Dart?
How to use rbenv
How to use letter_opener_web
How to use with_option
How to use java.util.logging
How to use map
How to use Twitter4J
How to use active_hash! !!
How to use hidden_field_tag
[How to use label]
How to use identity
How to use hashes
How to use JUnit 5
How to use Dozer.mapper
How to use Gradle
How to use org.immutables
How to use java.util.stream.Collector
How to use VisualVM
How to use Map
[Java] How to use Map
How to use Chain API
[Java] How to use Map
How to use Priority Queuing
[Rails] How to use enum
How to use java Optional
How to use JUnit (beginner)
How to use Ruby return
[Rails] How to use enum
Use C program from Ruby
How to use @Builder (Lombok)
[Swift] How to use UserDefaults
How to use java class
How to use Swift UIScrollView
How to use Big Decimal
[Java] How to use Optional ②
[Java] How to use removeAll ()
How to use String [] args
[Java] How to use string.format
How to use rails join
How to use Java Map
Ruby: How to use cookies
How to use dependent :: destroy
How to use Eclipse Debug_Shell
How to use Apache POI
[Rails] How to use validation
How to use Java variables
[Beginner] How to use devise Change settings from introduction
[Rails] How to use authenticate_user!
[Rails] How to use "kaminari"
How to use GC Viewer
[Java] How to use Optional ①
How to use Lombok now
How to migrate from JUnit4 to JUnit5
[Creating] How to use JUnit
[Rails] How to use Scope
[Rails 5] How to use gem gon ~ How to pass variables from Rails to JS ~
How to apply C code format from the command line
How to use the link_to method
[Rails] How to use gem "devise"
How to use Lombok in Spring
How to use StringBurrer and Arrays.toString.