Before because of

Since reading the article about Flutter on Solidot, I have become interested in this framework. As for cross-platform APP development, I have also learned about H5+ before. Some colleagues in the company are also engaged in the development of 5+ APP. Google’s products are attractive to me, such as Golang. After watching the tutorial, I decided to use a small object to practice my craft. I chose Autonavi and planned to implement an Autonavi plugin with Flutter.

First of all, I would like to declare that I am a professional handyman and developed as a hobby. I learned Java, DART and FLUTTER for the first time. The purpose of writing this article is to record the mistakes and omissions of learning flutter. Please criticize and correct them.

The working principle of

To write a FLUTTER plugin, you need to understand how it works:

  • Flutter communicates with Native through MethodChannel and is mainly used to execute some control instructions or call native methods synchronously.
  • The Native endpoint transmits the events or messages that occur to flutter via EventChannel, mainly the result of asynchronous invocation or the continuous data stream generated by native.

The location calls of flutter are asynchronous. Location requests are initiated by flutter via invokeMethod() of MethodChannel. The location information is obtained through onLocationChanged() of the AMapLocationListen interface in The Autonavi location SDK after the location is successfully located, and then the location information is sent to Flutter through EventChannel.

The development process

The environment used for this development is macOS El Capitan, Android Studio 3.1.3, and Flutter SDK 0.5.1.

Write Flutter on MAC. FormatException: Bad UTF-8 Encoding 0xb4. I couldn’t afford a Mac Book, so I had an SSD at home, so I installed black Apple. I don’t know how to write iOS code, this targeted plugin only implements the Android version, and I will add the iOS version when I learn it.

  1. Create the Flutter Plugin project

The process of creating a project is skipped.

  1. Native side of plug-in development
  • Open android module

In the project view of AS, select Android and right-click on Flutter->Open Android Module in Android Studio.

  • Introduce autonavi positioning SDK

After opening the Android module, click File->Project Structure, select Modules -> Flutter_AMap_location in the left column, and select the Dependencies page in the right.

Complete the introduction of Autonavi positioning SDK.


    final MethodChannel channel = new MethodChannel(registrar.messenger(), METHOD_CHANNEL_NAME);
    channel.setMethodCallHandler(plugin);

    final EventChannel positionChannel = new EventChannel(registrar.messenger(), STREAM_CHANNEL_NAME );
    positionChannel.setStreamHandler( plugin);
    
Copy the code

Defines a MethodChannel and an EventChannel.

  @Override
  public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else if (call.method.equals("getLocationOnce")) {
      // Set the location scenario to check-in mode
      mapLocationClientOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.SignIn);

      if (null != mapLocationClient) {
        mapLocationClient.setLocationOption(mapLocationClientOption);
        mapLocationClient.stopLocation();
        mapLocationClient.startLocation();
      }
    } else if (call.method.equals("getLocation")) {
      // Set the positioning interval to 5 seconds, 2 seconds by default
      mapLocationClientOption.setInterval(5000);

      // Set the location scene to travel mode
      mapLocationClientOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Transport);

      if (null! = mapLocationClient) { mapLocationClient.setLocationOption(mapLocationClientOption);// After setting the scene mode, it is best to call stop and then start to ensure that the scene mode takes effectmapLocationClient.stopLocation(); mapLocationClient.startLocation(); }}else if (call.method.equals("stopLocation")) {
      // Stop positioning
      mapLocationClient.stopLocation();
    } else{ result.notImplemented(); }}Copy the code

The onMethodCall() method is overridden to receive the instructions for a flutter call. Three commands are defined: getLocationOnce (using Autonavi’s check-in scenario, positioning once only), getLocation (using Autonavi’s travel mode, positioning continuously), and stopLocation (stopping positioning).

  @Override
  public void onListen(Object o, EventSink eventSink) {
    event = eventSink;
  }

  @Override
  public void onCancel(Object o) {
    event = null;
  }
Copy the code

The onListen() and onCancel() methods of the StreamHandler interface are overridden.

  private FlutterAmapLocationPlugin(Activity activity) {
    this.activity = activity;

    mapLocationClientOption = new AMapLocationClientOption();
    mapLocationClient = new AMapLocationClient(activity.getApplicationContext());

    mapLocationListener = new AMapLocationListener() {
      @Override
      public void onLocationChanged(AMapLocation aMapLocation) {
        HashMap<String, Object> loc = new HashMap<>();
        if(aMapLocation ! =null) {
          if (aMapLocation.getErrorCode() == 0) {
            // The location is successful
            loc.put("latitude", aMapLocation.getLatitude());
            loc.put("longitude", aMapLocation.getLongitude());
            loc.put("country", aMapLocation.getCountry());
            loc.put("province", aMapLocation.getProvince());
            loc.put("city", aMapLocation.getCity());
            loc.put("district", aMapLocation.getDistrict());
            loc.put("street", aMapLocation.getStreet());
            loc.put("streetnum", aMapLocation.getStreetNum());
            loc.put("adcode", aMapLocation.getAdCode());
            loc.put("poiname", aMapLocation.getPoiName());
            loc.put("address", aMapLocation.getAddress());
            event.success(loc);
          } else {
            // Failed to locate
            loc.put("errorcode", aMapLocation.getErrorCode());
            loc.put("errorinfo", aMapLocation.getErrorInfo());
            event.error("error"."get location error", loc); }}}}; mapLocationClient.setLocationListener(mapLocationListener); }Copy the code

Since gaud positioning is an asynchronous call, the onLocationChanged() method of AMapLocationListener is called back after successful positioning. This method is copied to get location information from it and then sent back to flutter via EventChannel.

  1. Plugin for flutter side development

This part is relatively simple.

class FlutterAmapLocation {
  static const String METHOD_CHANNEL_NAME = "bg7lgb/amap_location";
  static const String EVENT_CHANNEL_NAME = "bg7lgb/amap_location_stream";
  
  // Create a MethodChannel to call native methods
  static const MethodChannel _channel =
      const MethodChannel(METHOD_CHANNEL_NAME);

  // Create an EventChannel to receive data sent from native
  static const EventChannel _stream =
    const EventChannel(EVENT_CHANNEL_NAME);

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  // A location
  static Future<void> getLocationOnce() async {
    await _channel.invokeMethod("getLocationOnce");
  }

  // continuous positioning
  static Future<void> getLocation() async {
    await _channel.invokeMethod("getLocation");
  }

  // Stop positioning
  static Future<void> stopLocation() async {
    await _channel.invokeMethod("stopLocation");
  }

  // When a stream message is received, two functions that return void are passed in listen
  // And error handling
  // Definition of EventHandler
  // typedef void EventHandler(Object event);
  staticlistenLocation(EventHandler onEvent, EventHandler onError) { _stream.receiveBroadcastStream().listen(onEvent, onError: onError ); }}Copy the code
  1. Example Initializes the program development plug-in
  @override
  void initState() {
    super.initState();
    initPlatformState();

    FlutterAmapLocation.listenLocation(_onLocationEvent, _onLocationError);
  }
  
  // The processing method of received data
  void _onLocationEvent(Object event) {
    Map<String.Object> loc = Map.castFrom(event);

    setState(() {
      _longitude = loc['longitude'];
      _latitude = loc['latitude'];
      _address = loc['address'];
    });
  }

  // An error handler was received
  void _onLocationError(Object event) {
    print(event);
  }
Copy the code

You need to write two functions in the plug-in, one for processing when you receive data and one for processing when you receive errors. Then these two functions as FlutterAmapLocation. ListenLocation parameters ().

At this point, a Gaud targeted Plugin for Flutter is complete and the code has been placed on Github.

  1. Content to be perfected
  • Autonavi location permission, please refer to the SDK help document of Autonavi
  • Autonavi locates apikey Settings
  • IOS implementation of plugins (still to learn:)

6. Reference materials

  • Autonavi locates SDK
  • A Flutter plugin to get location
  • Because Chinese website

From 0 to 1: my Flutter technology practice | the nuggets essay, the campaign is underway