How to ignore package when building flutter project for web? - flutter

I have a project which uses flutter_libserialport library on macOS.
I am modifying it to work on web however this library does not work on web.
I am building a web implementation using navigator.serial in javascript which works fine.
However when I attempt to build the project for web I get the following error
/opt/homebrew/Caskroom/flutter/2.2.3/flutter/.pub-cache/hosted/pub.dartlang.org/libserialport-0.2.0+3/lib/src/config.dart:25:8: Error: Not found: 'dart:ffi'
import 'dart:ffi' as ffi;
This makes sense since FFI is not available on web.
But I don't even need the libserialport library on web any way.
How can I get flutter to ignore it?
I tried this however it doesn't contain information on how to exclude a package.
It also does not contain information on how to ignore it specifically for web. It seems to just ignore it in general.

Maybe you should guard your usages of libserialport with the kIsWeb predicate like following:
if(!kIsWeb){
// libserialport code execution here
}
I searched a lot as well and didn't find a way you can do that, I think this should be handled by the package itself not the package's users like in path_provider for instance.
As a workaround I have created a dummy libserialport's SerialPort class for web only as follows:
dummy_serialport.dart:
class SerialPort {
final String name;
static List<String> availablePorts = ['dummy'];
static SerialPortError? lastError;
SerialPort(this.name);
bool openReadWrite() {
return false;
}
}
class SerialPortError {}
// add more properties and functions as needed
main.dart:
import 'package:libserialport/libserialport.dart'
if (dart.library.html) './dummy_serialport.dart'
if (dart.library.io) 'package:libserialport/libserialport.dart';
....
if (!kIsWeb) {
final name = SerialPort.availablePorts.first;
final port = SerialPort(name);
if (!port.openReadWrite()) {
print(SerialPort.lastError);
exit(-1);
}
}
....
....
It's bad, I know :( but it works! maybe you can contact the package author to get more insight and if opening a PR where the interfaces are separated from the FFI implementation so that importing the classes wouldn't break web or something.

Related

How can I apply dart extension methods in the Flutter Logging library?

I am trying logging library in my flutter project. They have some good record messages (e.g. record.name, record.message, etc.) For my project, I want to extend by using dart extension methods this package to add some more record message (e.g. record.version, record.eventName, etc.). As a beginner in dart, I am not sure completely how to do that?
Here is an example that I tried but failed.
extension CustomLog on LogRecord {
String version(LogRecord version) => "1.0";
String eventName(LogRecord eventName) => "userNameChangedEvent";
}
Please provide me some suggestions/examples how can I extend any package and use it on my own.
Logging does not support extending (with extension) the LogRecord to add custom fields.
You can pass all your custom info as an class object in object param and retrieve it later.
Something like
class CustomLogAttributes {
final String version;
final String eventName;
CustomLogAttributes(this.version, this.eventName);
}
then
log.fine("example log message", object: CustomLogAttributes("1.1.0", "example_event");

Unity google-play-core review issue

I added the google play core package as instructed in the repo, and added the code according to the documentation here
I receive the following error: CS0246: The type or namespace name 'PlayAsyncOperation<,>' could not be found (are you missing a using directive or an assembly reference?)
This error shows at _reviewManager.RequestReviewFlow(); and _reviewManager.LaunchReviewFlow(_playReviewInfo)
Any idea what could be the issue?
My full code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Google.Play.Review;
public class ReviewCodes : MonoBehaviour
{
private ReviewManager _reviewManager;
private PlayReviewInfo _playReviewInfo;
// Start is called before the first frame update
void Start()
{
StartCoroutine(RequestReviews());
}
// Update is called once per frame
void Update()
{
}
IEnumerator RequestReviews()
{
// Create instance of ReviewManager
_reviewManager = new ReviewManager();
var requestFlowOperation = _reviewManager.RequestReviewFlow();
yield return requestFlowOperation;
if (requestFlowOperation.Error != ReviewErrorCode.NoError)
{
// Log error. For example, using requestFlowOperation.Error.ToString().
yield break;
}
_playReviewInfo = requestFlowOperation.GetResult();
var launchFlowOperation = _reviewManager.LaunchReviewFlow(_playReviewInfo);
yield return launchFlowOperation;
_playReviewInfo = null; // Reset the object
if (launchFlowOperation.Error != ReviewErrorCode.NoError)
{
// Log error. For example, using requestFlowOperation.Error.ToString().
yield break;
}
// The flow has finished. The API does not indicate whether the user
// reviewed or not, or even whether the review dialog was shown. Thus, no
// matter the result, we continue our app flow.
}
}
"are you missing a using directive or an assembly reference?"
These are following situation which causes a compiler error:
Check if the name of the type or namespace is correct, as most of the time you can get this error when the compiler cannot find that namespace.
Check if you have added the reference to the assembly that contains the namespace. Ex: Your code can be in "using XYZ;"
but if your project does not reference assembly then you can get a CS0246 error.
Try: using Google.Play.Common;
the order might be your problem. You also not only have to import the Google Core Package. You also have to import the Google Review Plugin. The core plugin overrides assemblies and files which then can't be used by the review assembly.
Step-by-Step solution:
Import google-play-plugins-1.7.0.unitypackage
Import com.google.play.review-1.7.0.unitypackage
Make sure to restart your IDE or reload the code in your IDE after this steps.
In older versions in unity there was an option to download this packages with the help of the unity package manager. Now you have to use the official github repository from Google. See Downloading the plugins or just use the official provided .unitypackages from Google

Flutter - How use conditional compilation for platform (Android, iOS, Web)?

I am creating a mobile app in Flutter. Now I have a problem, for one platform I will use a plugin for another, I need to write my platform code (the implementation of the plugin is not suitable).
I see several solutions:
It would be optimal to create several projects and use conditional compilation and shared files in them. I used this technique in visual studio. but I am now using android studio. there is no project file, only folders.
Also a problem with conditional compilation support. I found this article and conditional compilation is very limited.
create your own plugin and use it fully. but it is more labor intensive.
What do you advise maybe there is a third way?
When working with multiple environments (eg. IO and Web) it might be useful to add stub classes to resolve dependencies at compile time, this way, you can easily integrate multiple platform dependent libraries, without compromising compiling for each of it.
For example, one can have have a plugin structured in the following way:
- my_plugin_io.dart
- my_plugin_web.dart
- my_plugin_stub.dart
- my_plugin.dart
Let's break it down, with a simple example:
my_plugin.dart
This is where you can actually have your plugin's class to be used across multiple projects (ie. environments).
import 'my_plugin_stub.dart'
if (dart.library.io) 'my_plugin_io.dart'
if (dart.library.html) 'my_plugin_web.dart';
class MyPlugin {
void foo() {
var bar = myPluginMethod(); // it will either resolve for the web or io implementation at compile time
}
}
my_plugin_stub.dart
This is what will actually resolve at compile time (stubbing) to the right myPluginMethod() method.
Object myPluginMethod() {
throw UnimplementedError('Unsupported');
}
And then create the platform implementations
my_plugin_web.dart
import 'dart:html' as html;
Object myPluginMethod() {
// Something that use dart:html data for example
}
my_plugin_io.dart
import 'dart:io';
Object myPluginMethod() {
// Something that use dart:io data for example
}
Other official alternatives may pass from creating separated projects that share the same interface. This is just like Flutter team has been doing for their web + io plugins, resulting in a project that can be bundled with multiple projects:
- my_plugin_io
- my_plugin_web
- my_plugin_desktop
- my_plugin_interface
A good article explaining this may be found here.
Just typed it right here in SO, so I'm sorry if I had some typo, but you should easily find it on an editor.
You just need to import:
import 'dart:io';
And then use conditionals based on:
// Platform.isIOS // Returns true on iOS devices
// Platform.isAndroid // Returns true on Android devices
if (Platform.isIOS) {
navigationBar = new BottomNavigationBar(...);
}
if (Platform.isAndroid) {
drawer = new Drawer(...);
}
Add this library (no package needed)
import 'dart:io' show Platform;
Now you can create a function that checks which platform the user is using.
Widget getWidgetBasedOnPlatform() {
if (Platform.isIOS) {
return Container(); //the one for iOS
}
else if (Platform.isAndroid) {
return Container(); //the one for Android
}
}

Google Places API in Flutter

I am working on google places API with Flutter. I am working by referring the example. But I got errors for google places API classes as
Eg:
Undefined class 'GoogleMapsPlaces'.
Try changing the name to the name of an existing class, or creating a class with the name
I imported the flutter_google_places in my dart file as:
import 'package:flutter_google_places/flutter_google_places.dart'; But still I got the error for all classes.
Using flutter_google_places version 0.2.3.
GoogleMapPlaces is available on different library, not in flutter_google_places...
it's available on https://pub.dev/packages/google_maps_webservice
you can find another package for google place google_place
var googlePlace = GooglePlace("Your-Key");
var result = await googlePlace.autocomplete.get("1600 Amphitheatre");
You need to import
import 'package:google_maps_webservice/places.dart'; in your main.dart.

Using Java.util.scanner with GWT

for some reason when I try to use scanner with gwt, i get the following error:
No source code is available for type java.util.Scanner; did you forget to inherit a required module?
I looked around and it seems the "No source code is available for type xxxx" errors are due to not having a Javascript equivalent type for the Java type.
Is scanner not able to be used with GWT?
Here is a snippet of my code:
import java.util.Scanner;
...
public void submit(){
String text = editor.getEditor().getText();
Scanner input = new Scanner(text);
while(input.hasNextLine()){
String line = input.nextLine();
if(line.contains("//")){
cInfo.setDone(false);
cInfo.setCode(text);
return;
}
cInfo.setDone(true);
cInfo.setCode(text);
}
}
}
java.util.Scanner is not part of the GWT JRE Emulation. If you need a detail overview of what is inside the emulation here is the link to the docs:
https://developers.google.com/web-toolkit/doc/latest/RefJreEmulation#Package_java_util
Your code (at least the one in the current version of your question) is probably[*] equivalent to
public void submit() {
String text = editor.getEditor().getText();
if ("".equals(text))
return;
cInfo.setDone(!text.contains("//"));
cInfo.setCode(text);
}
However, I have a feeling that this may not actually be what want to do (or is it?)
If you need to split strings on the client side, I usually recommend the Splitter class in Guava. Most of its methods are GwtCompatible, and (together with CharMatcher, Joiner, ...) it's great to use both on the client and server side of your Java code.
[*] assuming, that setDone and setCode are simple setters without side effects