Back to Blog Home
← all posts

Announcing @nativescript/capacitor Beta

February 17, 2021 — by NativeScript TSC

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.

Oh just take me to the docs!

https://capacitor.nativescript.org/

The Capacitor and Ionic advantage

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.

@nativescript/capacitor - What is it exactly?

  1. A Capacitor plugin with a notify method to give the Capacitor ecosystem all the capabilities of NativeScript.

  2. It provides a convenient native object giving you quick direct access to your platform when you need it.

  3. 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.

Why would you want to do that?

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.

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);
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);
});
  • Native UI Blending

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();

Ever managed several third party dependencies?

Managing dependencies is one of the joys and pains of software scalability and maintenance.

  • What if a plugin your project uses falls out of date and the author doesn't maintain the plugin anymore?
  • What if you're down to the final 5% of product preparations and 1 aspect of a plugin feature is not working quite right?

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.

What about platform language changes, strong type checking and error prevention?

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.

Free SWAG!

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

  • 2 stress balls!
Free Swag!