NativeScript iOS Push Notifications & How to Get Your Device Token When Testing & Debugging in Xcode 8

I found all the articles and frameworks and this still took me quite some time to figure out.  As far as I can tell this is easiest to do using Xcode 8.  Some preliminary items you’ve probably already taken care of if you’ve found yourself here:

Ok, you should be ready to get busy.

Adding The Push Plugin Code To Your Project

From what I can tell it’s not so important where this code is added but seems ideal to put it in the main page js file, the first that loads.  You need to use an observable and bind it to your page.  I had an app that was well into version 2 that I wanted to add push notifications to.  It was setup as many examples are from a year or more ago using

exports.loaded = function(args) { 
  main code here that is run when the first page is loaded  
}

All the examples online use a main-page-view.js observable that’s instantiated in the other main js file and it’s all very complex.  What it boils down to is you need to reference the main observable that’s being bound to your page in the var self = xxx line of the push notifications example code.  In its shortest form you would do something like this:

https://gist.github.com/ChrisFlannagan/8ce46cfd02ab32a291bbeb026624f2a7

What’s super import here is the var self = pageData.  We are putting our observable into a variable called “self” that is used in the push notifications code from the readme.

I was just copying the code into my exports.loaded function and kept getting an error like self.set is not a function and was getting really irritated.  So do what I did above or start a fresh project and copy from the sample push plugin repo here.

Getting Your Device Token

In order to test notifications you need to run your app on an actual device.  So plugin your iPhone or iPad and get ready to run your app on it through either Xcode or tns command line.  I always get confused on how to select the right device on command line so I just use Xcode.

You will also need to make sure you have all the example code in place for registering your device.  I’ve built something you can copy here, just make sure that exports.loaded is initiated on the first page load.  The main xml would look like this in the top tag:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="loaded">

I’ll also embed the full javascript sample code at the bottom of this post so you don’t have to click out of here.

Now you need to get your device token from your iphone/ipad which you will need to use in an app like Easy APNs Provider in order to send test notifications to your phone.  I could not find any functionality in the nativescript plugin but on the link I shared earlier the fella shows how to do it in swift.  These lines here:

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    print("DEVICE TOKEN = \(deviceToken)")
}

You can see the long ass function name there.  I found that function in the nativescript plugin files in node_modules.  So you need to temporarily edit (I know, I know) the file and add a console.log to it.  In node_modules/nativescript-push-notifications/push-plugin.ios.js on, at least in the current version, line 41 you will see

var token = result.userInfo.objectForKey('message');

Under that add a console log:

var token = result.userInfo.objectForKey('message');
console.log(token);

Now when you run the app and accept the push notifications alert it will log in your terminal the device token.  DO NOT FORGET to edit that console log out.  Gotta keep them node_modules pure ya know.

Testing It Out

If you did everything right you can use the app I linked to earlier, Easy APNs Provider, and run some tests.  It worked flawlessly for me once I got the code running.  Good luck! Hit me up if you get stuck @ChrisFlanny.  Here’s a full sample code for doing a simple implementation inside an exported function:

https://gist.github.com/ChrisFlannagan/7f352ec635f1e4dc193ed62e4128609c

Use NativeScript Plugin nativescript-background-http To Send And Store Camera Pictures On PHP Server

I searched and searched and asked on slack and asked on the NS FaceBook group and everything I could think of to figure this out.  I finally pieced it together and it’s working.  So do you want to let your app users take a picture with their camera, or use one in their library for something and you need that photo stored on your web server? We let users take before/progress/after pics from using our device.  We want to store these photos so we can see results ourselves and request use from our users for advertisements.  So here’s how you do it.

nativescript-background-http

You need to make sure and import your camera ui and also this plugin.  It’s extremely awesome and works great.  You can get it by running

tns plugin add nativescript-background-http

EDIT: For some reason when I put this on an actual device it wouldn’t save the photos.  When on the actual phone it has a problem with using knownFolders.currentApp() and a custom folder, so I change that line from

fs.knownFolders.currentApp().path + /saved_images;

to

fs.knownFolders.documents().path;

and it worked just fine.

After setting that up use the below code, or whatever parts of it you’d like, to make the NS function and push the upload to your server.  A couple notes though, I use a folder called /saved_images in my /app project directory to store the files before sending.  I’m not sure this is necessary but I wanted to resize to a maximum of 800px wide or height while retaining proportion.  It is extremely important this directory is created if you use this filepath or your script will fail and you won’t know why because error logging here doesn’t do anything.

Also, I store a global configuration variable for my api’s URL, so I use url: config.apiUrl in my request options.

https://gist.github.com/ChrisFlannagan/e9e32428935076419f24aec6a30a7381

Saving The Image In PHP

So the config.apiUrl points directly to my php file (ex:server.com/apifile.php).  In this file you need to access file_get_contents(‘php://input’) to access the streamed data coming in.  This is how you work with forms submitted using content type “application/octet-stream” to get the file data.  With this data you can simply save it however you’d like using file_put_contents.  There’s other security concerns you will need to address that I’m not going over here as they are different all different applications of this process.  But here’s a quick, simple line for saving the image to a /uploads/ directory:

$all_headers = apache_request_headers();
$newimg = file_put_contents('uploads/' . $all_headers['File-Name'], file_get_contents('php://input'));

Now your image has been saved!

Additional User Data Needed

If you are storing this image and attaching it to a user or any other kind of data you can pass these as header fields just as you did the File-Name.  In your JS just under the line:

"File-Name": filename

Add a comma and put the next field you might need such as:

"File-Name": filename,
"Email-Add": email

Enjoy!