Flutter Windows: how can we add Header and footer in same code while we have code for mobile? - flutter

I have flutter 2.10 SDK but there is no documentation on native web Replacements. please anyone throw light on this issue.

What you need to do is to execute code based on the host platform.
First import the relevant headers
import 'dart:io' show Platform;
Using Platform APIs now you can detect the host platform and execute your codes for target platforms:
void myCode() {
if (Platform.isWindows) {
// do something specific for Windows here
} else {
// do something for other platforms
}
}

Related

Flutter plugin for a file picker that works on mobile and desktop that doesn't require go-flutter?

This seems like an issue that won't last for long, but I'm looking for a final solution for opening up a native file picker on all platforms including Desktop without installing go-flutter.
Currently I'm using file_selector plugin by Flutter.dev and it's working for web and macOS (I have yet to test on windows/linux). When I try to run it on an iOS simulator, I get an error.
MissingPluginException(No implementation found for method openFile on channel plugins.flutter.io/file_selector)
I guess this is because it doesn't support iOS and maybe this plugin is just for desktop and web.
I also saw the file_picker plugin but it requires go-flutter to be installed on the desktop to get that to work. I'd rather have nice hot-reloads/builds directly in Android studio and not need go-flutter commands to run the desktop simulations.
Is there a one stop solution that basically combines these two things? I'm pretty new to Flutter, so maybe I'm missing a really easy way to use one or the other library depending on platform with some kind of conditional? It seems kind of messy to go that route, but it could work for now.
The other answer that I'm looking for is a good solution to using file_picker plugin for desktop in an easier way, such as how to use go-flutter seamlessly.
I ended up using a conditional to detect the Platform and will use file_picker for iOS/Android and then file_selector for web/desktop.
So far it's working well. I'll probably write a quick wrapper to abstract that out of the main code.
It seems like the easiest way to do this currently is to use a package like file_picker_desktop for Windows/Mac/Linux and file_picker on Android/iOS/Web. They seem to have similar APIs, so you can make a wrapper function on your app that calls the correct library.
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show kIsWeb;
if (Platform.isAndroid || Platform.isIOS)) {
// use file_picker plugin
FilePickerResult? result = await FilePicker.platform.pickFiles();
if(result != null) {
File file = File(result.files.single.path);
} else {
// User canceled the picker
}
} else if(kIsWeb) {
// use file_selector plugin
final typeGroup = XTypeGroup(label: 'images', extensions: ['jpg',
'png']);
final file = await openFile(acceptedTypeGroups: [typeGroup]);
} else {
// use file_picker_desktop
try {
final result = await pickFiles(
allowMultiple: false,
);
if (result != null) {
File file = File(result.files.single.path);
} else {
// User canceled the picker
}
} catch (e) {
print(e);
}
}
The current latest version of the file_picker plugin (4.4.0) claims to work on all supported platforms, incl. desktop and Web.
I trie with Flutter 2.10.2 on macOS 12.2.1 and it works well. Also successfully tested on Win10.
final path = await FilePicker.platform.saveFile(
dialogTitle: 'Expor data',
fileName: '_${bloc.lot}_${bloc.serial}.dat',
lockParentWindow: true,
);
Setting lockParentWindow makes the file picker application modale, btw.

How to add conditional imports across Flutter mobile,web and window?

I have flutter application which uses different webview plugin for each platform(mobile, web, window).
Though I am able to import platform base on web and mobile, I am not able to import for windows.
I have tried adding else condition if it is not mobile or web, but it is taking mobile plugin.
This is how I import package for web and mobile (Working).
import 'package:eam_flutter/form/mobileui.dart'
if (dart.library.html) 'package:eam_flutter/form/webui.dart'
as multiPlatform;
This is how I import package for web, mobile and windows (Not Working, it is showing mobile webview exception since it doesn't support desktop).
import 'package:eam_flutter/form/windowui.dart'
if (dart.library.html) 'package:eam_flutter/form/webui.dart'
if (dart.library.io) 'package:eam_flutter/form/mobileui.dart'
as multiPlatform;
How can I specify conditional imports for windows?
For anyone else finding this, note that the accepted answer is not an answer to the question that was asked. The answer to the question that was asked is that you cannot. There is no way to use conditional imports to get different behavior between mobile and desktop; see this comment from the Dart team.
Since there is no conditional import support for window since it comes under dart io.
I have this workaround and found it working.
I end up creating file for each platform with different package import.
import 'package:flutter/foundation.dart' show kIsWeb;
import 'dart:io' as io;
if(kIsWeb){
{
return WebPage(); //your web page with web package import in it
}
else if (!kIsWeb && io.Platform.isWindows) {
return WindowsPage(); //your window page with window package import in it
}
else if(!kIsWeb && io.Platform.isAndroid) {
return AndroidPage(); //your android page with android package import in it
}
//you can add others condition...
Maybe we no longer need conditional import.
Look at the code below:
import 'package:package1/package1.dart';
import 'package:package2/package2.dart';
const keepFunc1 = bool.fromEnvironment('KEEP_FUNC1');
dynamic result2;
void main() {
if (keepFunc1) {
result2 = Calculator1()..addOne(1);
} else {
result2 = Calculator2()..addOne(1);
}
runApp(const MyApp());
}
If KEEP_FUNC1 environment variable is not specified to true. The package1 and the class Caculator1 won't be packaged into apk or ipa.
For more details, see the answer I wrote here.
So we can import all packages and use a const environment value to decide what packages to import. The tree-shaking mechanism is smart enough to remove unused parts.
Check this example
you need to create 2 files one for web & another for os and use condition on import

Server using flutter

As we all know Flutter is great for the front end, as I got into working with flutter I liked the Dart programming language very much I used it on some backend servers as well, Now it got me thinking if I can do this..
I have a aqueduct server
(Aqueduct is a dart package, which is very similar to express on node.js)
import 'dart:async';
import 'dart:io';
import 'package:aqueduct/aqueduct.dart';
import 'package:aqueduct/managed_auth.dart';
Future main() async {
final app = Application<App>()
..options.configurationFilePath = 'config.yaml'
..options.port = 8888;
await app.start(numberOfInstances: 3);
}
class App extends ApplicationChannel {
//server side logic
}
will the server/app be successfully built if I make the above main() as the entry point of the flutter app, successfully making the flutter app running on the android device to act as a server?
Or
how can I make it work if the above code fails?
PS: I have not tried this yet.
for your information: a node.js express server can be (may be) run on android using Node.js ARM
The below code runs a server on the port 4040 inside a flutter app
import 'dart:io';
Future main() async {
// #docregion bind
var server = await HttpServer.bind(
InternetAddress.loopbackIPv4,
4040,
);
// #enddocregion bind
print('Listening on localhost:${server.port}');
// #docregion listen
await for (HttpRequest request in server) {
request.response.write('Hello, world!');
await request.response.close();
}
}
if all your liberies is exiting on the flutter phone compiler your server will run without problem probably but if it is not you can looking for anther libery or try to download the libery source code and put it with your dart files
NOTE : I wanna know why you hadn't try to do an small experiment to see if it's work before posting this qustion

How to access the hardware layer when building a NativeScript plugin?

I'm trying to build a plugin to access the camera and I'm not sure how to access the hardware. When I import android, it says that there is no camera2 of undefined.
import { Common } from './CameraPlugin.common';
import { android } from 'tns-core-modules/application';
export class CameraPlugin extends Common {
constructor() {
super();
}
public takePicture() {
const cameraManager = new android.hardware.camera2.CameraManager();
cameraManager.openCamera();
}
}
NativeScript has native access to the Java/Kotlin (on Android) and ObjC/Swift (on iOS) devices with some minor limitations. (1)(2)
First you don't want/need to import "android" from anything; it is a valid global on all Android devices. So all you have to do is do android. (or java., or whatever namespace you need access too.) The import you did actually just hid the android global and replaced it with a different object which for sure doesn't have it.
One word of caution; unless you have installed the platform typescript typings, your editor will NOT know what android., android.hardware., etc are. When you go to actually run it; NativeScript will know what it is and use it just fine.
If you want your editor to know what it is, you need to install the platform typings:
npm i --save-dev tns-platform-declarations and you can read how to set them up here: https://github.com/NativeScript/NativeScript/tree/master/tns-platform-declarations
NativeScript documentation related to how the engine accesses the native code.
(1) - https://docs.nativescript.org/core-concepts/android-runtime/overview
(2) - https://docs.nativescript.org/core-concepts/ios-runtime/Overview

How can I determine if the current platform is a native app or web in Capacitor?

In Cordova you had immediate access to process.env.CORDOVA_PLATFORM is there something similar in Capacitor?
I'm looking to conditionally load some functions on startup and don’t want to block rendering waiting for async Device.getInfo to come back.
For example I want to determine immediately wether to import a script that make's native keyboard modifications, but I don't want to import this script if we are running on web
try {
const { Keyboard } = Plugins
Keyboard.setAccessoryBarVisible({ isVisible: true })
} catch (error) {
// Keyboard isn't available on web so we need to swallow the error
}
I'm using vue-cli
The answers so far are all correct, if you take a look into the Capacitors source code, there a few ways available, which can be used (but are undocumented for now):
Capacitor.getPlatform(); // -> 'web', 'ios' or 'android'
Capacitor.platform // -> 'web', 'ios' or 'android' (deprecated)
Capacitor.isNative // -> true or false
Be aware, that the method Capacitor.isPluginAvailable('PluginName'); only returns if the plugins is available or not (obviously) but important here, it does not tell you, if the method you want to execute after checking the availability is for your platform available.
The documentation of the Capacitor Plugins is not completed (yet).
Example (code), for the plugin StatusBar:
// Native StatusBar Plugin available
if (Capacitor.isPluginAvailable('StatusBar')) {
// Tint statusbar color
StatusBar.setBackgroundColor({
color: '#FF0000'
});
}
This would result in an error on iOS, since this method is not available there, on Android it works fine so far.
That means, that you need to implement a check of the Plugin and Platform combination by yourself (for now), may this will be improved in the future by Ionic / Capacitor itself.
Something like:
// Native StatusBar available
if (Capacitor.getPlatform() === 'android' && Capacitor.isPluginAvailable('StatusBar')) {
// Tint statusbar color
StatusBar.setBackgroundColor({
color: this.config.module.GYMY_MODAL_STATUSBAR_HEX_STRING
});
}
One more thing, you are not able to check, whether the method exists within this plugin (f. e. for the code above setBackgroundColor) as it is available, but throws an error (Error: not implemented) on a platform, which does not support it.
Hope I could help some of you guys.
Cheers
Unkn0wn0x
There is also the property Capacitor.isNative which you could use to determine whether the WebApp is running in Capacitor or in the Web.
https://github.com/ionic-team/capacitor/blob/master/core/src/definitions.ts
Update: In Capacitor V3 you can use Capacitor.isNativePlatform() for this.
https://capacitorjs.com/docs/v3/core-apis/web#isnativeplatform
As of Capacitor 3, you can use the following method to determine if it's running on a native device ("iOS" - "Android") or not ("web").
import { Capacitor } from '#capacitor/core';
if(Capacitor.isNativePlatform()) {
// Platform is mobile
} else {
// Platform is not mobile
}
Official documentation link. https://capacitorjs.com/docs/core-apis/web#isnativeplatform
Found it undocumented: Capacitor.platform
Capacitor.platform could be for example web ios android
Also if you wanted to know if you were running native before loading Capacitor, i.e you wanted to reduce bundle size by not including Capacitor on the web.
window.origin.includes('capacitor://')
You can now use Capacitor.isPluginAvailable('plugin name') to make this check, e.g., :
import { Capacitor, Plugins } from '#capacitor/core';
const { Keyboard } = Plugins;
...
const isAvailable = Capacitor.isPluginAvailable('Keyboard');
if (isAvailable) {
Keyboard.setAccessoryBarVisible({ isVisible: true })
}
You can see all of those on official doc here: https://capacitorjs.com/docs/basics/utilities#getplatform
if (Capacitor.getPlatform() === 'ios') {
// do something
}
if (Capacitor.isNative) {
// do something
}
I would say Device.getInfo() is the only reliable way of checking device's platform in capacitor based project.
Because the implementation of getPlatform(), Capacitor.platform is based on user agent of ui client. That means, if you opened your app on web and select developer tools then select mobile view, in this case it identify your platform as ios or android depending on which one you selected in dev tools instead of 'web'