We will be the first to tell you there's been some misunderstandings about NativeScript for several years.
🚨 Spoiler alert 🚨
It's not a technology solely dedicated to deliver native views on iOS and Android devices. It's certainly one of it's capabilities but it's only a side effect of what the technology is designed to do.
☀️ I can see clearly now ☀️
NativeScript === Direct platform API access from JavaScript.
That's applicable to many rewarding development experiences spanning several shapes and sizes.
https://capacitor.nativescript.org/
There's no question that developing for the browser is not only an enjoyable experience but has broad delivery vehicles that make developing for the web a love with broad reaching impact. From the rich plugin ecosystems, the economies of scale in resources for development, to the ever expanding support for more hardware api's directly from the browser.
The Ionic team is well known for providing excellent ui component framework kits as well as supporting an ecosystem in Capacitor that empowers web developers to access platform features with ease.
We 100% support Capacitor and are committed to helping strengthen the Capacitor community.
A Capacitor plugin with a notify
method to give the Capacitor ecosystem all the capabilities of NativeScript.
It provides a convenient native
object giving you quick direct access to your platform when you need it.
A distinct and isolated segment of code where you can write your own native platform API code and optionally expand your own native helpers for anything you could possibly dream up.
Let's outline a few examples and practical cases using the Capacitor Community Proposals starting with a few simple cases working our way to more sophisticated.
Screen Brightness: https://github.com/capacitor-community/proposals/issues/77
With this plugin, Solution 77: https://capacitor.nativescript.org/solution-77.html
native.setScreenBrightness = (value: number) => {
if (native.isAndroid) {
const context = native.androidCapacitorActivity;
if (android.os.Build.VERSION.SDK_INT < 23) {
const attr = context.getWindow().getAttributes();
attr.screenBrightness = value;
context.getWindow().setAttributes(attr);
} else {
if (!android.provider.Settings.System.canWrite(context)) {
const intent = new android.content.Intent(
android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS
);
intent.setData(
android.net.Uri.parse("package:" + context.getPackageName())
);
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
if (android.provider.Settings.System.canWrite(context)) {
android.provider.Settings.System.putInt(
context.getContentResolver(),
android.provider.Settings.System.SCREEN_BRIGHTNESS,
value * 100
);
}
}
} else {
UIScreen.mainScreen.brightness = value;
}
};
Usage in your Ionic web codebase:
import { native } from '@nativescript/capacitor';
native.setScreenBrightness(.8);
Power Mode: https://github.com/capacitor-community/proposals/issues/79
With this plugin, Solution 79: https://capacitor.nativescript.org/solution-79.html
import {
androidBroadcastReceiverRegister,
androidBroadcastReceiverUnRegister,
} from "@nativescript/capacitor/bridge";
let isListening = false;
let clientCallback: (isEnabled: boolean) => void;
let observer;
native.togglePowerModeListener = (callback?: (isEnabled: boolean) => void) => {
clientCallback = callback;
if (native.isAndroid) {
const action = "android.os.action.POWER_SAVE_MODE_CHANGED";
if (!isListening) {
isListening = true;
androidBroadcastReceiverRegister(action, (context, intent) => {
const manager: android.os.PowerManager = native.androidCapacitorActivity.getSystemService(
android.content.Context.POWER_SERVICE
);
if (manager && clientCallback) {
clientCallback(manager.isPowerSaveMode());
}
});
} else {
isListening = false;
androidBroadcastReceiverUnRegister(action);
}
} else {
if (!isListening) {
isListening = true;
observer = NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(
NSProcessInfoPowerStateDidChangeNotification,
null,
null,
(n: NSNotification) => {
if (clientCallback) {
clientCallback(NSProcessInfo.processInfo.lowPowerModeEnabled);
}
}
);
} else {
isListening = false;
NSNotificationCenter.defaultCenter.removeObserver(observer);
}
}
};
Usage in your Ionic web codebase:
import { native } from '@nativescript/capacitor';
native.togglePowerModeListener((isEnabled: boolean) => {
console.log("Power Mode changed:", isEnabled);
});
This example shows how you can also do Native UI Blending, for example using a pure native modal implementation if desired.
native.openNativeModalView = () => {
if (native.isAndroid) {
androidCreateDialog(() => {
const activity = native.androidCapacitorActivity;
const layout = new android.widget.LinearLayout(activity);
layout.setGravity(android.view.Gravity.CENTER);
layout.setOrientation(android.widget.LinearLayout.VERTICAL);
const btn = new android.widget.Button(activity);
btn.setText('Ionic');
layout.addView(btn);
const btn1 = new android.widget.Button(activity);
btn1.setText('Capacitor');
layout.addView(btn1);
return layout;
});
} else {
const vc = UIViewController.alloc().init();
vc.view.backgroundColor = UIColor.blueColor;
const label = UILabel.alloc().initWithFrame(
CGRectMake(0, 30, UIScreen.mainScreen.bounds.size.width, 50),
);
label.text = `Well this is fun.`;
label.textColor = UIColor.orangeColor;
label.textAlignment = NSTextAlignment.Center;
label.font = UIFont.systemFontOfSize(35);
vc.view.addSubview(label);
iosRootViewController().presentModalViewControllerAnimated(vc, true);
}
};
Usage in your Ionic web codebase:
import { native } from '@nativescript/capacitor';
native.openNativeModalView();
Managing dependencies is one of the joys and pains of software scalability and maintenance.
You can fork the plugin if it's open source, make modifications (contribute a pull request!) and reintegrate into your project. That takes time as usually there are various levels of integration points (ie, you often have to build it separately which could introduce other delays if problems arise there) and then also back in your project.
NativeScript has always been designed to solve these cases efficiently giving you another option to mitigate roadblocks and issues to product development.
Last but not least, it's an immense amount of fun having your platform at your fingertips without leaving the comfort of your primary IDE.
NativeScript was designed with a metadata generator. This is a fundamental piece to it's design which means anything the platform says is a public api, is callable, and available to develop with, is mapped into TypeScript constructs. Meaning the same strong type checking you gain in Xcode or Android Studio, you now have in your TypeScript codebase.
This metadata generator is run anytime you build your project for the platform target. Thus if a platform update occurs (a new Xcode, a new iOS, a new Android version, etc.) you are going to see the same build errors. This time instead of opening a plugin that access those features to resolve and integrate back in, you can often handle right in front of you without further delay.
NativeScript is a map of the platform target to your TypeScript codebase in quite literal terms.
For the first 10 developers whom create helpful solutions to any of the listed Capacitor Community proposals here with this plugin, we will send you:
2 sweet bottle openers
2 sweet socks
annnndddd...