@nativescript/capacitor/bridge

The bridge is fundamental to NativeScript for Capacitor and also exposes a few utility methods for quick usage.

iosRootViewController

The root view controller of your Capacitor app (or topmost presenting controller if using in context of an existing modal).

  • iosRootViewController()

A helper that you, yourself, could write inside src/nativescript on your own. We provide it as a convenience because it is so handy and often used.

Example usage:

import { iosRootViewController } from "@nativescript/capacitor/bridge";

const vc = UIViewController.alloc().init();
vc.view.backgroundColor = UIColor.blueColor;
iosRootViewController().presentModalViewControllerAnimated(vc, true);

The source of the helper:

export const iosRootViewController = () => {
  if (native.isAndroid) {
    console.log("iosRootViewController is iOS only.");
  } else {
    const app = UIApplication.sharedApplication;
    const win =
      app.keyWindow ||
      (app.windows && app.windows.count > 0 && app.windows.objectAtIndex(0));
    let vc = win.rootViewController;
    while (vc && vc.presentedViewController) {
      vc = vc.presentedViewController;
    }
    return vc;
  }
};

iosAddNotificationObserver (v2+)

Add an iOS Notification observer. This will internally track the observer references however you will also receive the observer reference as the return value in case you need it. See iosRemoveNotificationObserver below for how to remove later.

  • iosAddNotificationObserver: (notificationName: string, onReceiveCallback: (notification: NSNotification) => void) => any;

Learn more in iOS docs.

Example usage:

import { iosAddNotificationObserver } from "@nativescript/capacitor/bridge";

iosAddNotificationObserver('AnyEventName', (notification: NSNotification) => {
  console.log('AnyEventName:', notification.object)
});

The source of the helper:

let iosNotificationObserverClass;
let iosNotificationObservers: Array<any>;

function ensureNotificationObserverClass() {
  if (iosNotificationObserverClass) {
    return;
  }

  @NativeClass
  class NotificationObserver extends NSObject {
    private _onReceiveCallback: (notification: NSNotification) => void;

    public static initWithCallback(onReceiveCallback: (notification: NSNotification) => void): NotificationObserver {
      const observer = <NotificationObserver>super.new();
      observer._onReceiveCallback = onReceiveCallback;

      return observer;
    }

    public onReceive(notification: NSNotification): void {
      this._onReceiveCallback(notification);
    }

    public static ObjCExposedMethods = {
      onReceive: { returns: interop.types.void, params: [NSNotification] },
    };
  }

  iosNotificationObserverClass = NotificationObserver;
}

export const iosAddNotificationObserver = (notificationName: string, onReceiveCallback: (notification: NSNotification) => void) => {
  ensureNotificationObserverClass();
  const observer = iosNotificationObserverClass.initWithCallback(onReceiveCallback);
  NSNotificationCenter.defaultCenter.addObserverSelectorNameObject(observer, 'onReceive', notificationName, null);
  if (!iosNotificationObservers) {
    iosNotificationObservers = [];
  }
  iosNotificationObservers.push(observer);
  return observer;
}

iosRemoveNotificationObserver (v2+)

Remove an iOS Notification observer.

  • iosRemoveNotificationObserver: (observer: any, notificationName: string) => void;

Learn more in iOS docs.

Example usage:

import { iosAddNotificationObserver, iosRemoveNotificationObserver } from "@nativescript/capacitor/bridge";

const observer = iosAddNotificationObserver('AnyEventName', (notification: NSNotification) => {
  console.log('AnyEventName:', notification.object)
});

iosRemoveNotificationObserver(observer, 'AnyEventName');

The source of the helper:

export const iosRemoveNotificationObserver = (observer: any, notificationName: string) => {
  if (iosNotificationObservers) {
    const index = iosNotificationObservers.indexOf(observer);
    if (index >= 0) {
      iosNotificationObservers.splice(index, 1);
      NSNotificationCenter.defaultCenter.removeObserverNameObject(observer, notificationName, null);
    }
  }
}

androidCreateDialog

Create Android fragment dialogs on the fly.

  • androidCreateDialog(view: () => android.view.View, id?: string)

This method is another one that you, yourself, could write inside src/nativescript. It's another handy and convenient utility which can be used often for various native ui blending.

Example usage:

androidCreateDialog(() => {
  const activity = (<any>global).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);

  return layout;
});

The source of the helper:

let DialogImpl;
let DialogFragmentImpl;
if (native.isAndroid) {
  @NativeClass()
  class DialogImplClass extends android.app.Dialog {
    constructor(fragment, context, themeResId) {
      super(context, themeResId);
      return global.__native(this);
    }
  }

  DialogImpl = DialogImplClass;

  @NativeClass()
  class DialogFragmentImplClass extends androidx.fragment.app.DialogFragment {
    view: () => android.view.View;
    id: string;
    constructor(view: () => android.view.View, id?: string) {
      super();
      this.view = view;
      this.id = id;
      return global.__native(this);
    }
    onCreateDialog(savedInstanceState) {
      super.onCreateDialog(savedInstanceState);
      const activity = (<any>global).androidCapacitorActivity;

      const theme = this.getTheme();
      // In fullscreen mode, get the application's theme.
      // theme = activity.getApplicationInfo().theme;
      const dialog = new DialogImpl(this, activity, theme);
      dialog.setCanceledOnTouchOutside(true);
      return dialog;
    }
    onCreateView(inflater: any, container: any, savedInstanceState: any) {
      return this.view();
    }
  }
  DialogFragmentImpl = DialogFragmentImplClass;
}

export const androidCreateDialog = (
  view: () => android.view.View,
  id?: string
) => {
  const df = new DialogFragmentImpl(view, id);
  const fragmentManager = (<any>(
    global
  )).androidCapacitorActivity.getSupportFragmentManager();
  df.show(fragmentManager, id || uniqueId());
};

// general internal utility
const uniqueId = () => {
  return "_" + Math.random().toString(36).substr(2, 9);
};

androidBroadcastReceiverRegister

Register an Android BroadcastReceiver.

  • androidBroadcastReceiverRegister(intentFilter: string, onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void): void

Learn more in Android developer docs as well as the BroadcastReceiver api docs.

Example usage:

const intentFilter = "android.os.action.POWER_SAVE_MODE_CHANGED";
androidBroadcastReceiverRegister(intentFilter, (context, intent) => {
  const manager: android.os.PowerManager = native.androidCapacitorActivity.getSystemService(
    android.content.Context.POWER_SERVICE
  );
  console.log(
    `Power Save Mode is ${manager.isPowerSaveMode() ? "enabled" : "disabled"}`
  );
});

androidBroadcastReceiverUnRegister

Stop receiving broadcasts for the provided intent filter.

  • androidBroadcastReceiverUnRegister(intentFilter: string): void

Example usage:

const intentFilter = "android.os.action.POWER_SAVE_MODE_CHANGED";
androidBroadcastReceiverUnRegister(intentFilter);

Both BroadcastReceiver utilities are also things you could write yourself but we provide as a convenience.

The source of these helpers:

let androidBroadcastReceiverClass;
let androidRegisteredReceivers: {
  [key: string]: android.content.BroadcastReceiver;
};

function ensureBroadCastReceiverClass() {
  if (androidBroadcastReceiverClass) {
    return;
  }

  @NativeClass
  class BroadcastReceiver extends android.content.BroadcastReceiver {
    private _onReceiveCallback: (
      context: android.content.Context,
      intent: android.content.Intent
    ) => void;

    constructor(
      onReceiveCallback: (
        context: android.content.Context,
        intent: android.content.Intent
      ) => void
    ) {
      super();
      this._onReceiveCallback = onReceiveCallback;

      return global.__native(this);
    }

    public onReceive(
      context: android.content.Context,
      intent: android.content.Intent
    ) {
      if (this._onReceiveCallback) {
        this._onReceiveCallback(context, intent);
      }
    }
  }

  androidBroadcastReceiverClass = BroadcastReceiver;
}

export const androidBroadcastReceiverRegister = (
  intentFilter: string,
  onReceiveCallback: (
    context: android.content.Context,
    intent: android.content.Intent
  ) => void
): void => {
  ensureBroadCastReceiverClass();
  const registerFunc = (context: android.content.Context) => {
    const receiver: android.content.BroadcastReceiver = new androidBroadcastReceiverClass(
      onReceiveCallback
    );
    context.registerReceiver(
      receiver,
      new android.content.IntentFilter(intentFilter)
    );
    if (!androidRegisteredReceivers) {
      androidRegisteredReceivers = {};
    }
    androidRegisteredReceivers[intentFilter] = receiver;
  };

  if (global.androidCapacitorActivity) {
    registerFunc(global.androidCapacitorActivity);
  }
};

export const androidBroadcastReceiverUnRegister = (
  intentFilter: string
): void => {
  if (!androidRegisteredReceivers) {
    androidRegisteredReceivers = {};
  }
  const receiver = androidRegisteredReceivers[intentFilter];
  if (receiver) {
    global.androidCapacitorActivity.unregisterReceiver(receiver);
    androidRegisteredReceivers[intentFilter] = undefined;
    delete androidRegisteredReceivers[intentFilter];
  }
};