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

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

Related

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

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
}
}

Use Flutter foundation types without Flutter

There are three types that are present on the lib 'package:flutter/foundation.dart' that I need to use in an environment without Flutter. They are: ByteData, ReadBuffer and WriteBuffer. Is it possible to use these classes without having the whole Flutter as dependency?
The reason why I need to use it in an environment without Flutter is because I have a server made using Dart and I need to use these classes to encode/decode my socket messages.
Thanks in advance!
If you want access to classes in package:flutter/foundation.dart you can create a new flutter project as normal and remove runApp() from main() like this:
void main() {
print("This is now a console only program")
//no runApp(new MaterialApp())
}
This code won't start any mobile app and doesn't need an emulator, just a console. I have done some projects only with Dart and you can use all non UI Material Classes, such as File, StringBuffer...
Note: Remember to add the path for dart in the system environment variables, in my case D:\APPS\flutter\bin\cache\dart-sdk\bin, then you can navigate to your flutter project and type dart lib/main.dart in the console to run the code

How to add packages separately for Flutter web and mobile?

I am creating a Flutter project targeting of Android/iOS and Web is there any way to add the supported packages separately for both the Flutter Mobile and Web. For example, I am using the dart:io package in Flutter mobile applications to save the files, but it is not supported in Flutter web, so for web, I am using the dart:js package to download the files in the web application.
For C# we are simply using conditional symbols but Flutter I could not found any solution.
The problem is I could not import both the packages in my main.dart file. Can anyone help me to achieve this
Dart has conditional imports that can be conditioned on the availability of platform libraries.
That means that you can create one library in your package which uses dart:io, and another which uses dart:js, and then import whichever of these is supported.
import "file_loader.dart" // Version which just throws UnsupportedError
if (dart.library.io) "file_loader_io.dart"
if (dart.library.js) "file_loader_js.dart";
// Use imported API.
The important part is that you give these libraries the same API - the same types
with the same members, and the same top-level function - so that no matter which library is imported, the code that uses it is still valid.
When you compile the program, only one of the libraries will be used, so you won't get warnings if the other libraries are incorrect. You should test the code on all the supported platforms, just to be sure.
You should implement code separately, for example, my_ui_web.dart and my_ui_mobile.dart
Then you can import those files using if:
import 'package:my_awesome_app/my_ui_mobile.dart'
if (dart.library.html) 'package:my_awesome_app/my_ui_web.dart'
as myUI;

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'

How do I get the proxy settings of an android/ios device using flutter?

I am trying to build an app using flutter and I would like to know how to retrieve the proxy settings of the device through flutter.
It's probably safe to assume that the HttpClient doesn't pick this up automatically, but you might want to test that.
So, now you need to interact with native code using plugins. There is already a rich library of plugins providing everything from battery level to video player. I can't see proxy in there anywhere, so you need to write your own plugin (which is just one of the standard flutter project types: app, package (just Dart code allowed) and plugin). A plugin is a bit like a package (other projects can depend on it) but includes native code too. It also includes a mini-app so that you can test your plugin code while developing it.
Your plugin will end up being similar to the existing Connectivity plugin, so you may want to copy from there. In your Android method implementation you will replace
NetworkInfo info = manager.getActiveNetworkInfo();
with
ProxyInfo defaultProxy = manager.getDefaultProxy();
You have return two values, the host name and the port, so put these in a Map
Map<String, String> map = new HashMap<String, String>();
map.put("host", defaultProxy.getHost());
map.put("port", Integer.toString(defaultProxy.getPort()));
result.success(map);
Bonus points if you submit your changes to the Connectivity plugin.