Support Flutter Cross-Platform

Dave Parth
Globant
Published in
4 min readAug 4, 2020

--

This post is a continuation of my last post i.e.

Make sure you read or just have a glance at that post as this post is using references of that postcode and problem statements.

What we have covered is a few of the problems that we might face during development time for true Cross-Platform. This time we will cover to support cross-platform if we have plugins that support only one or two techs.

html import tip

We can not be able to run dart:html imported code to Flutter Mobile or desktop. This is the error we will get.

error to run html imported code on flutter mobile

What do we want to do?
1. Import specific packages depending on the platform
2. Run set of function depending on the platform

Enough of the build-up right? Let’s get started.

We have checked this gist in the last post:

if (kIsWeb) {
htmlfile.InputElement uploadInput = htmlfile.FileUploadInputElement();
uploadInput.click();

uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
//was just checking for single file but you can check for multiple one
if (files.length == 1) {
final htmlfile.File file = files[0];
final reader = htmlfile.FileReader();

reader.onLoadEnd.listen((e) {
//to upload file we will be needing file bytes as web does not work exactly like path thing
//and to fetch file name we will be needing file object
//so created custom class to hold both.
pickerCallback([FlutterWebFile(file, reader.result)]);
});
reader.readAsArrayBuffer(file);
}
});
} else {
File file = await FilePicker.getFile();
pickerCallback([file.path]);
}

Note: Suppose file_picker is the plugin that does not support for flutter web and you need your own logic to run when the button is clicked, kind of running javascript or anything and giving result back to Flutter. Now file_picker supports web also.

Let’s start with the steps that we need to do

1. Import specific packages depending on the platform
dart has support for conditional imports like this

import “package_file.dart” if (condition) “other_package_file.dart”;

2. Run set of function depending on the platform

To do this we need to understand the stub structure.
The stub is a piece of code used to stand in for some other programming functionality. here what it means is we are going to say if this is a mobile platform then we will stub this code and else that code.

Stub creation:

To do stub creation we will create abstract class and will import based on circumstances.

import 'platform_file_picker_stub.dart'
if(dart.library.io) 'mobile_file_picker.dart'
if(dart.library.html) 'web_file_picker.dart';

typedef CallBackForFilePicker = Function(List<dynamic> files);

abstract class PlatformFilePicker{

factory PlatformFilePicker() => createPickerObject();

void startWebFilePicker(CallBackForFilePicker pickerCallBack);

String getFileName(dynamic file);

}

here we are importing for stub the stub implementation will be imported based on this imports.

In stub we will just create single function that will just have abstract method for stubbing implementation.

import 'platform_file_picker.dart';

PlatformFilePicker createPickerObject() => throw UnsupportedError(
'Cannot create a client without dart:html or dart:io',
);

Now what dart will do is will try to import implementation based on condition if library is having dart:io then it will import mobile version else it will import web version implementation.

///mobile_file_picker.dart
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'platform_file_picker.dart';

PlatformFilePicker createPickerObject() => IOFilePicker();

class IOFilePicker implements PlatformFilePicker{
@override
String getFileName(file) {
return file.path.substring(file.lastIndexOf(Platform.pathSeparator) + 1);
}

@override
void startWebFilePicker(pickerCallBack) async {
File file = await FilePicker.getFile();
pickerCallBack([file.path]);
}
}
///web_file_picker.dartimport 'dart:html' as htmlfile;
import 'platform_file_picker.dart';

PlatformFilePicker createPickerObject() => WebFilePicker();

class WebFilePicker implements PlatformFilePicker{
@override
String getFileName(file) {
return file.file.name;
}

@override
void startWebFilePicker(pickerCallBack) {
htmlfile.InputElement uploadInput = htmlfile.FileUploadInputElement();
uploadInput.click();

uploadInput.onChange.listen((e){
final files = uploadInput.files;
//just checking for single file here you can for multiple files
if(files.length == 1){
final htmlfile.File file = files[0];
final reader = htmlfile.FileReader();

reader.onLoadEnd.listen((event) {
pickerCallBack([FlutterWebFile(file, reader.result)]);
});
reader.readAsArrayBuffer(file);
}
});
}

}

Finally able to install on iOS and flutter web.

Here’s the GitHub code:

Hope you liked it.

Do you know you can press the clap👏 button 50 times? The higher you go, the more it motivates me to write more stuff!

Hello, I am Parth Dave. A noob developer and noob photographer. You can find me on Linkedin or stalk me on GitHub or maybe follow me on Twitter?

Have a nice fluttery day!

--

--

Dave Parth
Globant
Writer for

Developer, Photographer. Flutter and Automation enthusiast.