Starting with NativeScript CLI 1.1.0, you can develop or use plugins in your NativeScript projects.
A NativeScript plugin is any npm package, published or not, that exposes a native API via JavaScript and consists of the following elements.
- A
package.jsonfile which contains the following metadata: name, version, supported runtime versions, dependencies and others. For more information, see the Package.json Specification section. - One or more CommonJS modules that expose a native API via a unified JavaScript API. For more information about Common JS modules, see the CommonJS Wiki.
AndroidManifest.xmlandInfo.plistwhich describe the permissions, features or other configurations required or used by your app for Android and iOS, respectively.- (Optional) Native Android libraries.
- (Optional) Native iOS dynamic libraries.
The plugin must have the directory structure, described in the Directory Structure section.
If the NativeScript framework does not expose a native API that you need, you can develop a plugin which exposes the required functionality. When you develop a plugin, keep in mind the following requirements.
- The plugin must be a valid npm package.
- The plugin must expose a built-in native API or a native API available via custom native libraries.
- The plugin must be written in JavaScript or TypeScript and must comply with the CommonJS specification. If written in TypeScript, make sure to include the compiled
JavaScriptfile in your plugin. - The plugin directory structure must comply with the specification described below.
- The plugin must contain a valid
package.jsonwhich complies with the specification described below. - If the plugin requires any permissions, features or other configuration specifics, it must contain
AndroidManifest.xmlandInfo.plistfile which describe them.
NativeScript plugins which consist of one CommonJS module might have the following directory structure.
my-plugin/
├── index.js
├── package.json
└── platforms/
├── android/
│ └── AndroidManifest.xml
└── ios/
└── Info.plist
NativeScript plugins which consist of multiple CommonJS modules might have the following directory structure.
my-plugin/
├── package.json
├── MyModule1/
│ ├── index1.js
│ └── package.json
├── MyModule2/
│ ├── index2.js
│ └── package.json
└── platforms/
├── android/
│ └── AndroidManifest.xml
└── ios/
└── Info.plist
index.js: This file is the CommonJS module which exposes the native API. You can use platform-specific*.platform.jsfiles. For example:index.ios.jsandindex.android.js. During the plugin installation, the NativeScript CLI will copy the platform resources to thetns_modulessubdirectory in the correct platform destination in theplatformsdirectory of your project.
Alternatively, you can give any name to this CommonJS module. In this case, however, you need to point to this file by setting themainkey in thepackage.jsonfor the plugin. For more information, see Folders as Modules.package.json: This file contains the metadata for your plugin. It sets the supported runtimes, the plugin name and version and any dependencies. Thepackage.jsonspecification is described in detail below.platforms\android\AndroidManifest.xml: This file describes any specific configuration changes required for your plugin to work. For example: required permissions. For more information about the format ofAndroidManifest.xml, see App Manifest.
During the plugin installation, the NativeScript CLI will merge the pluginAndroidManifest.xmlwith theAndroidManifest.xmlfor your project. The NativeScript CLI will not resolve any contradicting or duplicate entries during the merge. After the plugin is installed, you need to manually resolve such issues.platforms\ios\Info.plist: This file describes any specific configuration changes required for your plugin to work. For example: required permissions. For more information about the format ofInfo.plist, see About Information Property List Files.
During the plugin installation, the NativeScript CLI will merge the pluginInfo.plistwith theInfo.plistfor your project. The NativeScript CLI will not resolve any contradicting or duplicate entries during the merge. After the plugin is installed, you need to manually resolve such issues.
NativeScript plugins which contain both native Android and iOS libraries might have the following directory structure.
my-plugin/
├── ...
└── platforms/
├── android/
│ ├── libs/
│ │ └── MyLibrary.jar
│ ├── MyAndroidLibrary/
│ │ ├── ...
│ │ └── project.properties
│ └── AndroidManifest.xml
└── ios/
├── MyiOSLibrary.framework
└── Info.plist
platforms\android\libs: This directory contains any native Android libraries packaged as*.jarpackages. During the plugin installation, the NativeScript CLI will copy these files tolib\Androidin your project and will configure the Android project inplatforms\androidto work with the library.platforms\android\MyAndroidLibrary: This directory contains a native Android library with aproject.propertiesfile. During the plugin installation, the NativeScript CLI will copy these files tolib\Androidin your project and will configure the Android project inplatforms\androidto work with the library.platforms\ios: This directory contains native iOS dynamic libraries (.framework). During the plugin installation, the NativeScript CLI will copy these files tolib\iOSin your project and will configure the Android project inplatforms\iosto work with the library.
Every NativeScript plugin should contain a valid package.json file in its root. This package.json file must meet the following requirements.
- It must comply with the npm specification.
Thepackage.jsonmust contain at leastnameandversionpairs. You will later use the plugin in your code by requiring it by itsname. - It must contain a
nativescriptsection which describes the supported NativeScript runtimes and their versions. This section can be empty. If you want to define supported platforms and runtimes, you can nest aplatformssection. In thisplatformssection, you can nestiosandandroidkey-value pairs. The values in these pairs must be valid runtime versions or ranges of values specified by a valid semver(7) syntax. - If the plugin depends on other npm modules, it must contain a
dependenciessection as described here.
The NativeScript CLI will resolve the dependencies during the plugin installation.
The following is an example of a package.json file for a NativeScript plugin which supports the 1.0.0 version of the iOS runtime and the 1.1.0 version of the Android runtime.
{
"name": "myplugin",
"version": "0.0.1",
"nativescript": {
"platforms": {
"ios": "1.0.0",
"android": "1.1.0"
}
}
}To install a plugin for your project, inside your project, run the following command.
tns plugin add <Plugin>You can specify a plugin by name in the npm registry, local path or URL. The following are valid values for the <Plugin> attribute.
- A
<Name>or<Name>@<Version>for plugins published in the npm registry. - A
<Local Path>to the directory which contains the plugin files and itspackage.jsonfile. - A
<Local Path>to a.tar.gzarchive containing a directory with the plugin and itspackage.jsonfile. - A
<URL>which resolves to a.tar.gzarchive containing a directory with the plugin and itspackage.jsonfile. - A
<git Remote URL>which resolves to a.tar.gzarchive containing a directory with the plugin and itspackage.jsonfile.
The installation of a NativeScript plugin mimics the installation of an npm module.
The NativeScript CLI takes the plugin and installs it to the node_modules directory in the root of your project. During this process, the NativeScript CLI resolves any dependencies described in the plugin package.json file and adds the plugin to the project package.json file in the project root.
If the NativeScript CLI detects any native libraries in the plugin, it copies the library files to the lib/<platform> folder in your project and configures the platform-specific projects in platforms/<platform> to work with the library.
Next, the NativeScript CLI runs a partial prepare operation for the plugin for all platforms configured for the project. During this operation, the CLI copies only the plugin to the tns_modules subdirectories in the platforms\android and platform\ios directories in your project. If your plugin contains platform-specific JS files, the CLI copies them to the respective platform subdirectory and renames them by removing the platform modifier.
TIP: If you have not configured any platforms, when you run
$ tns platform add, the NativeScript CLI will automatically prepare all installed plugins for the selected platform.
Finally, the CLI merges the plugin AndroidManifest.xml and Info.plist files with platforms\android\AndroidManifest.xml and platforms\ios\Info.plist in your project.
IMPORTANT: Currently, the merging of the platform configuration files does not resolve any contradicting or duplicate entries.
The following is an example of a plugin AndroidManifest, project AndroidManifest.xml and the resulting merged file after the plugin installation.
The Plugin Manifest
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="com.example.towntour.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
</manifest>The Project Manifest Located in platforms\android\
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.nativescript.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name="com.tns.NativeScriptApplication"
android:allowBackup="true"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>The Merged Manifest Located in platforms\android\
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android" package="org.nativescript.test" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="com.example.towntour.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--
Some comment here
-->
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme">
<activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.EDIT"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>After the installation is complete, you need to open platforms\android\AndroidManifest.xml and platforms\ios\Info.plist in your project and inspect them for duplicate or contradicting entries. Make sure to preserve the settings required by the plugin. Otherwise, your app might not build or it might not work as expected, when deployed on device.
To use a plugin inside your project, you need to add a require in your app.
var myPlugin = require("myplugin");This will look for a myplugin module with a valid package.json file in the tns_modules directory. Note that you must require the plugin with the value for the name key in the plugin package.json file.
To remove a plugin from your project, inside your project, run the following command.
tns plugin remove <Plugin>You must specify the plugin by the value for the name key in the plugin package.json file.
The removal of a NativeScript plugin mimics the removal of an npm module.
The NativeScript CLI removes any plugin files from the node_modules directory in the root of your project and removes any native Android libraries which have been added during the plugin installation. During this process, the NativeScript CLI removes any dependencies described in the plugin package.json file and removes the plugin from the project package.json file in the project root.
IMPORTANT: This operation does not remove files from the
platforms\androidandplatforms\iosdirectories and native iOS libraries, and does not unmerge theAndroidManifest.xmlandInfo.plistfiles.
After the plugin removal is complete, make sure to remove any leftover native library files from the <lib> directory in the root of the project.Update the platform-specific projects in platforms\<platform> to remove any dependencies on the removed native libraries.
Next, you need to run the following command.
tns prepare <Platform>Make sure to run the command for all platforms configured for the project. During this operation, the NativeScript CLI will remove any leftover plugin files from your platforms\android and platforms\ios directories.
TIP: Instead of
$ tns prepareyou can run$ tns build,$ tns run,$ tns deployor$ tns emulate. All these commands run$ tns prepare.
Next, open your platforms\android\AndroidManifest.xml and platforms\ios\Info.plist files and remove any leftover entries from the plugin AndroidManifest.xml and Info.plist files.
Finally, make sure to update your code not to use the uninstalled plugin.