Category Archives: Plugins

Plugins.nativescript.rocks upgraded

Behind the scenes PNR (http://plugins.nativescript.rocks) has been upgraded to support several cool new features.

At this moment the largest difference is the backend data storage system has been completely changed; and now has a lot of new data available to it.    This system should allow us to do some more pretty cool things in the future...

By using this new data; I also have a bit more accurate plugin list,    In addition the new system has the ability to track both NativeScript 2.x plugins and separately 3.x.  So on the page you can now see a select list that allows you to change "All" (All plugins), "2.x" plugins that should be only 2.x compatible; and then finally only 3.x compatible.  In addition I took the time to actually drop a physical search bar in the title area; as my virtual search bar seemed to confuse a lot of people.

Play around with it, let me know if you run into any issues.

NativeScript 3.0 Sneak Peek and what it entails for Plugin developers.

For those who are not aware, v3.0 of NativeScript is the next major version that will be released.  It has been being worked on for several months now as it has parts of it have been completely rewritten to enhance speed of the framework in a number of areas.    Some parts of it have undergone radical changes in design, and as such will require changes to plugins to make them compatible.

Unfortunately these changes are a breaking change and will mess up the plugins for a while...

Some pre-release information has trickled out and as such the plugin developers needs to be made aware of these changes, so we can start getting a jump on these changes...

The biggest issue is any plugins that deals with any properties, or stylers has been completely changed.   These plugins will HAVE to be changed to support 3.0.   This means your plugin will no longer be NS <= 2.5 compatible, these are BREAKING changes.

 

Plugin Sites and the Package.json

As an aside if your plugin doesn't have any breaking changes and can continue to work fine in all versions of NS; then I am asking you to add a new flag to your package.json file to flag that this plugin is 3.0 compatible but doesn't require 3.0.

Your package JSON NativeScript section should look like this:

"nativescript": {
   "platforms": {
      "android": "2.3.0",
      "ios": "2.3.0"
    },
    "plugin": {
       "nan": "false",
       "core3": "true",
       "pan": "true",
       "wrapper": "ios",
       "category": "visual"
    }
 },

The additional "plugin" structure is being introduced  to try and capture the data that has been missing from the plugin infrastructure.  At this moment each item is totally optional.   However, this will allow the plugin sites to categories and filter the plugins based on criteria's that are important to subsets of the users using the plugin sites.  Please see: http://fluentreports.com/blog/?p=489 for more details on the new "plugin" structure proposal.

 

Back to the breaking Changes

The first resource is that some of the NativeScript team produced a video last week https://youtu.be/bwO3cYPb4zQ which will give a decent overview of the changes.

The developers working on the 3.0 project gave a run down of the changes and how they benefit us and/or what changes we need to be concerned about.

The second resource, which I find to be a bit more valuable is this document that is in the source repo.  https://github.com/nativescript/nativescript/blob/master/Modules30Changes.md

They used this document in the above video; but since they only covered an overview and this documents has all the nitty-gritty details.

For this to be a smooth transition I really strongly encourage you on the "core3" attribute be used if you are not just bumping your platforms to 3.0.0.      I will be automatically filtering out plugins that I believe are only 2.0 for 2.0 mode and 3.0 for 3.0 mode.  So  having things tagged correctly will help the end users have a much more painless transition.

 

NativeScript: Plugins - Let Fix the Data!

Some of you might not be aware but I wrote the plugins.nativescript.rocks.   I also helped write the plugins.nativescript.org site (if something doesn't work on plugins.nativescript.org; please blame my cohorts in crime, Nathan Walker and George Edwards.   I had NOTHING to do with any bugs!  😛  )

Well, with the new upcoming changes in 3.0 and some data that we have been unable to determine I have decided to request that the plugin authors add a little bit more metadata to the package.json file that comes with the plugin.

So lets look at the existing "nativescript" key.

"nativescript": {
   "platforms": {
      "android": "2.3.0",
      "ios": "2.3.0"
    }
 },

This tells nativescript which version of NativeScript runttimes are supported.   This allows the TNS command line to throw and error/warning if you are not using the proper versions.   This is useful information as this tells us what platforms are supported.   However, this fails when people (like me) write dummy wrappers to support the plugin not crashing on the other platform.     On the plugins site it will say this plugin supports both Android and iOS, but in all reality the plugin only really supports iOS, and actually doesn't really do anything on Android.    I would like to have the plugins site actually reflect this reality rather than you downloading a plugin you thing works on Android and it turns out it doesn't.

In addition since Angular was introduced to the eco-system, there are a large number of plugins that actually do NOT work with NAN (NativeScript Angular) code.   And even some that don't work with PAN (Plain Awesome NativeScript) code.  In addition in the future we might get other frameworks supported like VueJS (VAN?), etc.

So I would like to start capturing the data so that we can do these additional cool things.   And so I am proposing the following additional OPTIONAL meta data to be added.

"nativescript": {
   "platforms": {
      "android": "2.3.0",
      "ios": "2.3.0"
    },
    "plugin": {
       "nan": "false",
       "pan": "true",
       "core3": "true",
       "wrapper": "ios",
       "category": "visual"
    }
 },

nan = NativeScript ANgular will be assumed to be false, unless Angular is detected in the Keywords/name/description.
pan = Plain Awesome NativeScript Will be assumed to be true.
core3 = Supports NS Core Modules 3. Will be assumed FALSE if platforms.ios/.android < 3
Will be assumed TRUE if platforms.ios/andorid >= 3.
wrapper = Using a dummy wrapper Will default to false, use "ios" or "android" to signify platform which is using a wrapper.
category This is the category to put the plugin in.   Valid categories currently are: "Interface", "Processing", "Templates", "Developer", "Utilities"

I am up for other category suggestions.   But at this point these are the primary categories that I use on plugins.nativescript.rocks.

Please note each key is optional; however, your plugin will get extra points for having an category key.  And you will LOSE points if we detect a plugin is using a wrapper and you haven't tagged it, as this is a issue the plugin users really hate seeing faulty data about the plugins support.

I would recommend plugin authors start adding this to any releases of there plugins so that we can capture the data.  This will become critical with the 3.0 release as a large chunk of plugins are not going to be compatible between NS 2 & NS 3.

NativeScript: iOS and xCode 8 the wonderful world of breaking changes

native8xcodeFor those who have upgraded to the all new xCode 8, you may have noticed some of the plugins breaking...     The biggest breaking change in NativeScript and xCode 8 is now things deep down in the ObjC runtime that used to be a function call are now a property.

So, for example let say you needed to access UIScreen.mainScreen.

 

 

In xCode 7 this was

var mainScreen = UIScreen.mainScreen();

in xCode 8 this is now:
var mainScreen = UIScreen.mainScreen;

Notice, it is no longer a FUNCTION call.  It is a PROPERTY.   Now how do you make this compatible so your code can run with both xCode 7 and xCode 8.

If you are developing an app; I recommend you use the helper function that Telerik added to NativeScript which they use throughout the core modules.

var utils = require('utils/utils');
var mainScreen = utils.ios.getter(UIScreen, UIScreen.mainScreen);

If you have your own plugin, then I'm going to recommend you embed my code into your own plugin...  The code is basically the same as Teleriks, but you eliminate the require call.
function iosProperty(theClass, theProperty) {
    if (typeof theProperty === "function") {
        // xCode 7 and below
        return theProperty.call(theClass);
    } else {
        // xCode 8+
        return theProperty;
    }
}

Then you use it the exact same way;
var mainScreen = iosProperty(UIScreen, UIScreen.mainScreen);

Happy NativeScripting, and hopefully you can easily get all your plugins updated shortly to support both xCode 7 & 8!

NativeScript: Patreon Posts & Plugins

For those who are unaware; I've started doing paid content; see my post on "Why Patreon" to see the reasons.   I'm going to attempt to keep this post updated with plugins and posts that are available to those who are my patreon supporters.

Posts:

 

Plugins:

 

NativeScript: Android plugins and Windows path size issues

If your on Linux or OSX you can skip this post; it only applies to us pathetic people that prefer Windows (like me ). I do have Linux and OSX, so maybe I'm not that pathetic; but since I do prefer Windows, maybe I am.

If you don't want to read the reason this occurs but all you want is the fix; then scroll down to the fix!

Well if you see this error: Command [Some Path]\gradlew.bat failed with exit code 1 then you more than likely ran into this error if you see a lot of messages above it with "No Delegate Set" and errors.

Well to understand the issue you need to understand that this is a issue between Windows, Gradle and how NativeScript (A fix might show up by v1.8 of NativeScript) currently does Android plugins. Windows, if it supported larger path sizes; this wouldn't be an issue (which is why it works on Mac/Linux). NativeScript if it handled plugins differently might not run into this issue either. But at the current place we are at; it does so here is the crux of the issue.

1. Windows only supports 255 character path sizes (if they are not UNC or Unicode path's)

2. NativeScript scans all your plugins; any that have a platforms/android folder; it will use the include.gradle file found in that folder.  If there is NOT a include.gradle file; it will create one for you using the plugin name as the information.

3. Gradle combines all the productFlavors (which are inside the include.gradle files) into one long string.

Ok, lets look at a sample include.gradle file (this is also what is also generated for you, if it doesn't exist)

android {
    productFlavors {
        "nativescript-websockets" {
            dimension "nativescript-websockets"
        }
    }
}

So lets pretend your code exists at: C:\nativescript\AwesomeProject\, so there is (32) characters. Now add platforms\android\ (18). Next add build\intermediates\res\merged\ (31) as this is where Gradle does its resource merging. So lets say you are using the Telerik NativeScript UI plugin; and lets grab one of the image names \debug\drawable-xxhdpi\someimage.png which is of course adds another 49 characters. So this means we are using 130 characters already; leaving us with 122 characters left to play with.

So if you have a plugin installed like nativescript-websockets you get 23 characters used just for a single plugin. I bet you can see where this is going. Add on the cool nativescript-telerik-ui plugin and you have another 23 characters used. Add just a couple more plugins, and yes -- you are now well over 255 character limit!

Guess what happens???    Well if you are following the story so far; you get a nice error that gradle quit with error 1.

The Fix:

Now for the good news; here is how you can continue developing!

  1. Go to your app folder and do a tns platform remove android to safely recover, you need to kill your existing android platforms folder.
  2. Go into you node_modules folder, and then you need to repeat this next set of steps for EACH of the plugins you have installed.
    • Enter that plugins platforms\android folder and edit the include.gradle -- if that folder doesn't exist then you are done and can skip this plugin.  If the folder exists but the include.gradle file doesn't exist you can choose to ignore it or create your own.  DO NOT create a platforms\android folder, if it doesn't exist. Only create a include.gradle if the plugin already has a platforms\android folder and it doesn't have a include.gradle.
    • Edit the include.gradle and make the name shorter; this is the formula that I used.   Replace nativescript with "ns", eliminate any dashes, and then use the first letter for each word in the plugin.   So "nativescript-cardview" becomes "nscv",and "nativescript-telerik-ui" becomes "nstu". So the include.gradle changes from above (nativescript-websockets) to:
      android {
          productFlavors {
              "nsws" {
                  dimension "nsws"
              }
          }
      }

      Pretty simple huh?   By shorting the name, you go from 23 character per plugin to 4 characters per plugin.   So you can now easily fit 5 plugins in the same space it used to take for 1 plugin.  Please make sure the total letters are unique -- don't have two plugins with the same name (i.e. "nsws" for nativescript-websockets and nativescript-webserver)  as the same name, make them distinct.  Having duplicate names will probably break Gradle.
  3. Do a nativescript platform add android to re-install the platform after you are all done, and then you should be good to go.

Please note this potential side effect: I have confirmation below that if you are using a plugin that requires additional permissions; this work around will unfortunately not merge the info from the plugins AndroidManifest.xml file.   With all the plugins I had, I never saw this issue; but depending on what you are doing this is something you may run into.   You have two choices to deal with this:

  1. Don't rename that specific plugin inside the include.gradle file.  This way the AndroidManifest.xml file will get merged properly.   You an afford a couple plugins to still have large names.
  2. Copy the information that you need (like permissions) from the plugins AndroidManifest and manually merge it into your master manifest located at App/App_Resources/Android/AndroidManifest.xml

The bug report so you can track this is Android/369 and based on the conversation with the NativeScript devs this should hopefully be fixed in v1.8 (but no promises).

NativeScript: Announcing {N} plugin tracking site

If you are like me occasionally you have to find a plugin and you go and check the npmjs.com site and do a search for NativeScript and then peruse a ton of entries; some relevant and some not so much.

Well, last night as I was finally working on updating my manually done plugin list (http://github.com/nathanaela/nativescript-plugins) ; I realized that the number of plugins was just getting to be too great for me to now be manually tracking them all.

So I set out to create something that could automate everything; I found a site/project called react.parts that was open source.  I quickly downloaded the source and glanced through it and promptly borrowed the data updater component.   I made a huge number of changes to the updater, some was just fixing some bugs and some was that I needed totally different fields for my purpose.    I am happy to announce today it runs on one of my servers every night getting and building the dataset for the all new NativeScript plugin site:

http://plugins.nativescript.rocks

The site as of today, Feb 18, 2016, the site lists 86 different plugins, my old manual list only had 45.   As the authors fill in data in the plugins, the data will automatically be updated and added.

We have a total of 33 different authors making NativeScript plugins!   Not bad for less than a year, and Eddy Verbruggen has the most plugins; at a count of 12 of them!  Wow, way to go Eddy!

For you plugin authors you need to make sure you have in your main package.json, the following items to get listed properly.   Some of these items if missing will be considered a minor issue; others will cause your plugin to NOT show up.  At this time you MUST have a link to the github repo that hosts it, you also must have either "nativescript" or "{N}" in your keywords.

If you want the Windows, iOS or Android icon to show up on your plugin, you need to use one of those key words also in your "keywords" OR you need to make sure you have them in your nativescript.platforms object.

Please make sure you include a version, and a license field; this is very helpful for people to quickly see in the list.  And example of the fields is what I use for my nativescript-zxing plugin.

{
  "name": "nativescript-zxing",
  "version": "1.0.0",
  "description": "A Simple ZXing barcode reader/writer wrapper",
  "main": "zxing.js",
  "nativescript": {
   "platforms": {
      "android": "1.4.0",
        "ios": "1.4.0"
   }
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/nathanaela/nativescript-zxing.git"
  },
  "keywords": [
    "NativeScript", "Barcode", "JavaScript", "Android", "iOS", "ZXing"
  ],
  "author": {
    "name": "Nathanael Anderson",
    "email": "nathan@master-technology.com"
  },
  "bugs": {
    "url": "https://github.com/nathanaela/nativescript-zxing/issues"
  },
  "license": {
    "type": "APACHE",
    "url": "https://github.com/nathanaela/nativescript-zxing/blob/master/LICENSE"
  },
  "homepage": "https://github.com/nathanaela/nativescript-zxing",
  "readmeFilename": "README.md"
}

Please note, it updates the data nightly, so if you submit changes; and you don't see it show up in 24 hours; ping me and I'll check into what is going on...

Creating a plugin using third party code

So, I was minding my own business last week, by reading about everyone's issues in the NativeScript forum.  Well, ok, so I wasn't minding my own business, we can pretend I was...

So, I saw this post about CodeSign error: entitlements are required and tried to help a little. The issue actually ends up being the newest version of XCode has some issues that has been causing problems for people in all sorts of communities.

Well, I told Aaron, I would do a blog post the next day on the plugin.  My how time flies when you are swamped with stuff to do and it also being Christmas week; so it has been a week since I said the next day.   (Sorry, about that Aaron!)

NS-ZXingSo I am going to go with his ZXing plugin that he was trying to turn into a NativeScript plugin to show how to native Android and native iOS libraries and turn them into awesome NativeScript plugins.

If you just want to look at the code or demo the repo is at https://github.com/NathanaelA/nativescript-zxing.  So here is how I go about making a plugin in from a native library.

  1. Find the iOS (ZXingObjC) and Android (ZXing) versions.
  2. Study the documentation to see how to install them & build the platform files.
  3. Study the documentation to see how to call them & build the js wrappers.

foldersFirst thing we need to do is create a new project folder; since this is for ZXing; I created a folder called nativescript-zxing.  In this folder I created a several files.

The LICENSE file
The first file is the LICENSE file; I need to make sure that I give credit where credit is due and outline my license and the library authors licenses.  Most the time I use a MIT license for my stuff; however in this case since both the iOS & Android parts are already under the Apache license, I used the Apache license to keep everything the same.

The package.json
The second file is the package.json file.  This one pretty straight forward, however since I have seen several mistakes in other NativeScript plugins, I am going to cover it.

{
  "name": "nativescript-zxing",
  "version": "1.0.0",
  "description": "A Simple ZXing barcode reader/writer wrapper",
  "main": "zxing.js",
  "nativescript": {
   "platforms": {
      "android": "1.4.0",
        "ios": "1.4.0"
   }
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/nathanaela/nativescript-zxing.git"
  },
  "keywords": [
    "NativeScript", "Barcode", "JavaScript", "Android", "iOS", "ZXing"
  ],
  "author": {
    "name": "Nathanael Anderson",
    "email": "nathan@master-technology.com"
  },
  "bugs": {
    "url": "https://github.com/nathanaela/nativescript-zxing/issues"
  },
  "license": {
    "type": "APACHE",
    "url": "https://github.com/nathanaela/nativescript-zxing/blob/master/LICENSE"
  },
  "homepage": "https://github.com/nathanaela/nativescript-zxing",
  "readmeFilename": "README.md"
}

The important parts are:

  1. You must have the nativescript.platforms key section like I have.  If you are not supporting iOS or Android you can remove one of those sub-keys; but you need to support at least one valid platform.  Please note this version you use is the minimum platform version you support.  DO NOT SET IT TO THE LATEST version unless it absolutely requires the latest version.  Please use 1.x.0 so that it will work on all versions of 1.x -- I don't know how many plugins I've had to manually change this value to work on the latest Android runtime, because the author put the latest iOS runtime in both spots which is later than the Android version, so it throws an error during install.
  2. It is highly recommended you have the main key set so that NativeScript isn't guessing which is your main JavaScript file.  This has causes problems several times so far, so set it.
  3. PLEASE link back to the repository for your plugin; it makes it a lot easier to report any issues, create pull requests and/or see if anything has been fixed, etc...
  4. Please include the license information, it makes is easier to verify that the plugin can be used for my project.

Android Runtime
So, lets start with the Android version; in this case after reading the documentation; I found out the wiki has the information we need to know.  Most the time the readme has enough information, but in this case I had to actually search for it, and finally found the pieces we need to know in the wiki.  The documentation has a nice little section on using a prebuilt Jar or Maven.  Since we are using Gradle for Android, we can use the Maven stuff and eliminate having to package up or compile anything (This is the best option).

However, in some cases if the project is no longer being maintained or you have to create your own fixes you may need to build and distribute the .jar or .aar file with your project like I need with my NativeScript-WebSockets project.  In the event you need to distribute your own JAR files; put them in the platforms/android/libs directory.

In our case, since the project is maintained and on Maven, we can easily just create a include.gradle and then NativeScript will handle the rest.  The include.gradle file needs to be put in the platforms/android folder.  The include.gradle file looks like this:

android { 
    productFlavors {
        "nativescript-zxing" {
            dimension "nativescript-zxing"
        }
    }
}

dependencies {
   compile 'com.google.zxing:android-core:3.2.1'
   compile 'com.google.zxing:core:3.2.1'  
}

In your file; you need to change both places for the plugin name.  And the dependencies is where we link to the our libraries.   Now how do I know what they are named?  Well first of all we used the Maven link from the Wiki documentation, and then went into the core folder to get the latest version.  3.2.1; The project is called com.google.zxing and it is a sub-project called core.  So the compile line is "compile 'com.google.zxing:core:3.2.1'".   The other compile line is an optional dependency that I decided to include on the Android side of the plugin.  I'm not currently using it in the JS code; but in future versions it would be very useful.  So I am including it in the build process. This is ALL that is required to get the Android version of the plugin to be built into your application.

iOS Runtime
The iOS runtime is much simpler as the docs on the site list what we need to know; we don't have to go searching anywhere else.  So what you need to is create a file called Podfile and place it in your platforms/ios folder.  This file contains a single line:

pod 'ZXingObjC', '~&gt; 3.0'

Now the installation says to put a platform :ios '7.0' into your Podfile; however this is NOT recommended since NativeScript is handling the platform information and will actually set it to 8.0 when you are using Podfiles.   So it is better to only add the single pod line.

We are now all done with the runtime side; the platforms/ios/Podfile and platforms/android/include.gradle will automatically download and install all the needed files to link it into your project.  The next part is where the fun begins...

Creating a cross platform wrapper
This where you have to put on your thinking hat.  You need to decide how you want your api to be called and what features you want to expose.  You can even do what NativeScript does in some cases and expose a ios or android property to access the underlying library. In our case the wrapper is going to be very simple; I just want to show you how do it.  All I am going to do is expose how to create a new barcode image.

iOS Wrapper
So first we need to create a zxing.ios.js file (please notice in my package.json I set the main key to "zxing.js").  NativeScript will automatically RENAME the .ios. version of the plugin when it is building your app on the iOS platform and strip out the .ios; so the file will become zxing.js automatically.

This file is a simple constructor that literally does nothing as I am trying to keep this example very simple.

function NativeZXing() {
    if (!this instanceof NativeZXing) { 
        return new NativeZXing();
    }
}

I do typically safe guards I try to add all of my plugins.  It simplifies usage of the plugin you can actually do "var zx = NativeZXing();" forgetting the "new" and it will still work since the constructor function will call new for them.  Some people prefer to throw an error rather than automatically using new.  My policy is in plugins attempt to be as user friendly as possible.

The next step is to create the function that will create a barcode.  So looking at the documentation the way to create a CGImage is this code:

ZXMultiFormatWriter *writer = [ZXMultiFormatWriter writer];
ZXBitMatrix* result = [writer encode:@"A string to encode"
                              format:kBarcodeFormatQRCode
                               width:500
                              height:500
                               error:&amp;error;
  CGImageRef image = [[ZXImage imageWithMatrix:result] cgimage];

So I decided our function will look like this...
NativeZXing.prototype.createBarcode = function(options) {
    var encode="NOTHING", width=100, height=100, format = this.QR_CODE;
    if (options) {
        if (options.encode) { encode = options.encode; }
        if (options.width) { width = options.width; }
        if (options.height) { height = options.height; }
        if (options.format) { format = options.format; }
    }
    var error = new interop.Reference();
    var writer = ZXMultiFormatWriter.writer();
    var result = writer.encodeFormatWidthHeightError(encode, format, width, height, error);
    
    if (result) {
        return UIImage.alloc().initWithCGImage(ZXImage.imageWithMatrix(result).cgimage);
    } else {
        return error.localizedDescription().toString();
    }
};

This first 7 lines are pretty simple; they set the defaults and allows the options dictionary to override the defaults.  These might be better as properties on the object, but for simplicity they are parameters.   The next line might not be so obvious; "var error = new interop.Reference();" In ObjectiveC anytime we need to pass a pointer/reference for marshalling into a runtime function call we need to create a reference.  If you look up above in the example; you will see error being passed as &error.  That  told me I needed to pre-create the reference so I could pass it in and get the result.   In most cases you can just pass null instead of an interop.Reference() if you don't want the results; but in this case I decided to capture the error.

The next line is an easy conversion; the Documentation says *writer = [ZXMultiFormatWriter writer] this converted into NativeScript is simply var writer = ZXMultiFormatWriter.writer();

The following line is a lot more complex to parse and really makes you have to think about how to convert it.  So looking at the [writer encode:@"A string to encode" format:kBarcodeFormatQRCode width:500 height:500 error:&error]. The rule is the first parameter is ignored, lets parse this.  The NativeScript code starts with writer.encode since that is the iOS call.  Skip the first parameter, then the next parameter is "format" so we append a proper cased "Format" to the writer.encode to make it writer.encodeFormat. We proceed through each of the following parameters and appending a proper cased version.  So the call finally ends up being writer.encodeFormatWidthHeightError(... params ...); Once you understand how it isn't too bad to parse.  However, the issue can be if the documentation is wrong and their are other parameters.  You MUST have every parameter accounted for in the function name for the NativeScript to be able to marshall the call into the iOS runtimes.

The next line just checks to see if we got a result; if so we convert it to an image or we return the error.  To convert the result into an image the next line is [[ZXImage imageWithMatrix:result] cgimage]  Again, the calls are not to hard to parse so this one ends up being; var image = ZXImage.imageWithMatix(result).cgimage;

Now in our plugin case I actually converted the CGImage into a UImage since all the NativeScript code seems to use UImage's.  So that the extra UIImage.alloc().initWithCGImage() code that I added.

The last two things I add to the wrapper are any ENUM or FEATURE flags, to keep consistency for your application code.   For example the format of the barcode can be chosen using format parameter.   Would your really want to add to you *application* code like  ZXBarcodeFormat.kBarcodeFormatQRCode; for iOS and com.google.zxing.BarcodeFormat.QR_CODE for android to determine that you are using QR code barcodes?   No, me either.  So I wrap the feature flags into JS feature flags like so:

NativeZXing.QR_CODE = NativeZXing.prototype.QR_CODE = ZXBarcodeFormat.kBarcodeFormatQRCode;

In this case since ZXing appears to only have a barcode types as the feature flags; I attach them directly.   But if ZXing had a lot of different features I would do something like this:
BARCODE = {QR_CODE: ZXBarcodeFormat.kBarcodeFormatQRCode,...};
NativeZXing.BARCODE = NativeZXing.prototype.BARCODE = BARCODE

And finally we next to export the entire module with this code:
module.exports = NativeZXing;

Awesome the code is complete on iOS.  When you createBarcode({encode: "Hi"}); you will get a UImage back on iOS.

Android Wrapper
Just like we did on iOS; we create a file called zxing.android.js.  In this file we have the exact same constructor, it also has the same module export statement.  However the actual code to generate the Image is different.  So here is the Android version.

NativeZXing.prototype.createBarcode = function(options) {
   var encode="NOTHING", width=100, height=100, format = this.QR_CODE;
   if (options) {
        if (options.encode) { encode = options.encode; }
        if (options.width) { width = options.width; }
        if (options.height) { height = options.height; }
        if (options.format) { format = options.format; }
    }
    var hints = null;
    var writer = new com.google.zxing.MultiFormatWriter();
    var result = writer.encode(encode, format, width, height, hints);
    width = result.getWidth();
    height = result.getHeight();
    var pixels = [];
    for (var y=0;y&lt;height;y++) {
        var offset = y*width;
        for (var x=0;x&lt;width;x++) {
            pixels[offset+x] = result.get(x,y) ? 0xFF000000 : 0xFFFFFFFF;  // Black : White
        }
    }
    var bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    return bitmap;
};

As you can see the first 7 lines are the same.  However, the writer line is different.  Typically the documentation will tell where in the namespace the function resides.  In this case I actually looked at the source code to determine where the MultiFormatWriter function was at.  It showed it was using "package com.google.zxing" namespace and is a class called MultiFormatWriter.    So that is converted to var writer = new com.google.zxing.MultiFormatWriter(); The next line is equally simple since we are looking at the source code (Documentation is typically easier, but in this case the source was quicker). So it is called exactly as it is displayed in the source code: var result = writer.encode(encode, format, width, height, hints);

The examples I found on how to use MultiFormatWriter and convert it to an image; showed us basically scanning the result set and generating a simple pixel array. Creating a new Bitmap; and then you pass that array into your new bitmaps' setPixels function.   Converting that code to JS was trivial as basically all you need to do is go to the android documentation and find out the full namespace for the things.  So the code Bitmap.createBitmap becomes android.graphics.Bitmap.createBitmap.  And Bitmap.Config.ARGB_8888 also gets prefixed with android,graphics. to become android,graphics.Bitmap.Config.ARGB_8888.

The last thing we do is add our enum value for the Android side to our QR_CODE source

NativeZXing.QR_CODE = NativeZXing.prototype.QR_CODE = com.google.zxing.BarcodeFormat.QR_CODE;

Again, this keeps it so that in the application you can easily just use ZXing.QR_CODE and never have to worry about the actually underlying platform value.

Creating the readme.mdandroidios
The next thing you need to do is create documentation; people need to understand how use you plugin.  If you can create a demo that is even better.  For example for this sample plugin I created a simple demo that lets you type in anything; and it will give you the QR code for it.  You can use the demo to help implement the plugin if the instructions aren't enough.

Wrapping it up
The final things you need to do is create a repo; and commit your code.   If it is public publish it to npm so that everyone else can use it.   If this is a private plugin; you can do tns plugin add /path/to/plugin to install it.   For example this plugin's repo is: https://github.com/NathanaelA/nativescript-zxing and can be installed via tns plugin add nativescript-zxing.

If you have any ideas on future blog posts; please feel free to comment.