Last updated at 2020-05-12

1.

  1. IOS and Android updates are completely different.

  2. IOS can only jump to the AppStore, which is easier to implement

  3. Android needs to download apK package. Since there are many Android models, dart is used here to connect to the third-party native Android download library.

  4. Update interface and download update separate processing.

  5. IOS doesn’t have a download schedule, Android does.

Code 2.

2.1 iOS directly use url_launcher to open the AppStore

if (Platform.isIOS) {
  final url = "https://itunes.apple.com/cn/app/id1380512641"; // Replace the number after id with your application ID
  if (await canLaunch(url)) {
    await launch(url, forceSafariVC: false);
  } else {
    throw 'Could not launch $url'; }}Copy the code

2.1 the Android implementation

2.1.1 Add download library to Android /app/build.gradle file
Dependencies {// just copy this line implementation'com. King. App: app - updater: 1.0.8 - androidx'
}
Copy the code
2.1.2 Adding storage permission in Androidmanifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Copy the code
2.1.3 Writing a Plug-in in an Android Project (updateversionPlugin.java)
package com.iwubida.wbd_b2b_app.plugins;

import android.content.Context;
import android.util.Log;

import com.king.app.updater.AppUpdater;
import com.king.app.updater.callback.UpdateCallback;


import java.io.File;
import java.util.HashMap;
import java.util.Map;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;

import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugins.packageinfo.PackageInfoPlugin;
import io.flutter.plugins.pathprovider.PathProviderPlugin;

/** UpdateVersionPlugin */
@SuppressWarnings("unchecked")
public class UpdateVersionPlugin implements EventChannel.StreamHandler.FlutterPlugin {

  private static String TAG = "MY_UPDATE";

  private static String channelName = "plugins.iwubida.com/update_version";

  private Context context;

  private EventChannel eventChannel;

  private AppUpdater update;


    /** Plugin registration. */
    public static void registerWith(Registrar registrar) {
      final UpdateVersionPlugin instance = new UpdateVersionPlugin();
      instance.onAttachedToEngine(registrar.context(), registrar.messenger());
    }

    @Override
    public void onAttachedToEngine(FlutterPlugin.FlutterPluginBinding binding) {
        onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger());
    }

    private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) {
        this.context = applicationContext;
        this.eventChannel = new EventChannel(messenger, channelName);
        this.eventChannel.setStreamHandler(this);
    }

    @Override
    public void onDetachedFromEngine(FlutterPlugin.FlutterPluginBinding binding) {
        context = null;
        eventChannel.setStreamHandler(null);
        eventChannel = null;
    }



    @Override
    public void onListen(Object o, EventChannel.EventSink eventSink) {
        if (o.toString().length() < 5) {
            eventSink.error(TAG, "URL error", o);
            return;
        }
        if(! o.toString().startsWith("http")){
            eventSink.error(TAG, "URL error", o);
            return;
        }

        update = new AppUpdater(context,o.toString()).setUpdateCallback(new UpdateCallback() {

        Map data = new HashMap<String, Object>();

        // Send data to Flutter
        private  void sendData(a) {
            eventSink.success(data);
        }

        @Override
        public void onDownloading(boolean isDownloading) {}@Override
        public void onStart(String url) {
            data.put("start".true);
            data.put("cancel".false);
            data.put("done".false );
            data.put("error".false);
            data.put("percent".1);
            sendData();
        }

        @Override
        public void onProgress(long progress, long total, boolean isChange) {
            int percent = (int)(progress * 1.0 / total * 100);
            if (isChange && percent > 0) {
                data.put("percent", percent); sendData(); }}@Override
        public void onFinish(File file) {
            data.put("done".true);
            sendData();
        }

        @Override
        public void onError(Exception e) {
            data.put("error", e.toString());
            sendData();
        }

        @Override
        public void onCancel(a) {
            data.put("cancel".true); sendData(); }}); update.start(); }@Override
  public void onCancel(Object o) {
    Log.i(TAG, "Cancel download");
    if(update ! =null) { update.stop(); }}}Copy the code
2.1.4 Registering plug-ins in MainActivity
// Register the update component in the onCreate method (old version)
// * Not recommended
UpdateVersionPlugin.registerWith(registrarFor("iwubida.com/update_version"));
Copy the code
New version (Flutter v1.12.13) (problem with Flutter V1.17.0)
// * Not recommended
@Override
  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    // Register the update component
    ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine);
    UpdateVersionPlugin.registerWith(shimPluginRegistry.registrarFor("iwubida.com/update_version"));
  }
Copy the code
// Kotlin - Flutter V1.17.0 - new
// There may be problems with the above two types due to the plugin code changes. I suggest this one.
// Here is the mainactivity.kt code. Java version of the self-written.
 override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    GeneratedPluginRegistrant.registerWith(flutterEngine)
    // Register the update component
    flutterEngine.plugins.add(UpdateVersionPlugin())
}
Copy the code

We need to get the download progress, so we use EventChannel for continuous one-way communication.

2.3 Dart Implementation

static const channelName = 'plugins.iwubida.com/update_version';
  static const stream = const EventChannel(channelName);
  // Schedule subscription
  StreamSubscription downloadSubscription;
  int percent = 0;
  
   // Start downloading
  void _startDownload() {
    if (downloadSubscription == null) { downloadSubscription = stream .receiveBroadcastStream(widget.data.apkUrl) .listen(_updateDownload); }}// Stop listening to progress
  void _stopDownload() {
    if(downloadSubscription ! =null) {
      downloadSubscription.cancel();
      downloadSubscription = null;
      percent = 0; }}// Progress download
  void _updateDownload(data) {
    int progress = data["percent"];
    if(progress ! =null) { setState(() { percent = progress; }); }}Copy the code

2.4 other

There is also the issue of Android permission application. Refer to the code in the project below.

Program source code

Location: lib/widget/update_version. Dart