Azure Notification Hub with Cordova app(iOS) - ios

I'm trying to use Notification Hub to push Cordova app(iOS)
Azure side is as below.
Source code on client side is as below.
I'm sure Azure client is correctly connected and registration is successful.
function initPushNotification(){
var push = PushNotification.init({
android: {
senderID: "12345679"
},
ios: {
alert: "true",
badge: "true",
sound: "true"
},
windows: {}
});
var registrationSuccess = function () {
alert('Registered with Azure!');
};
var registrationFailure = function (error) {
alert('Failed registering with Azure: ' + error);
};
push.on('registration', function(data) {
client.push.apns.registerTemplate(handle,
'myTemplate', template, null)
.done(registrationSuccess, registrationFailure);
});
push.on('notification', function(data) {
alert('Push Received: ' + data.message);
});
push.on('error', function(e) {
alert(e.message);
});
But when I execute Test Send from notification hub page, nothing happens.
I tried from simple ruby script to APNS directly and notification comes to iPhone correctly.
Does anyone know how to fix it or any information?
My environment is
MacBook Pro
OS X ElCapitan
Cordova 6.0.0
com.microsoft.azure-mobile-services 1.2.9 "Windows Azure Mobile Services"
phonegap-plugin-push 1.6.2 "PushPlugin"

Most likely the call to client.push.register() is not succeeding for some reason. I'm not using the particular plugin you're using, I'm using azure-mobile-apps-cordova-client combined with phonegap-plugin-push. So far, this combination is working for my purposes.
You can find a more complete example here: Add Push Notifications to your Apache Cordova App.
One thing I would add is that when you call the push.register() API in the azure-mobile-apps-cordova-client plugin, you can give it an error function callback that gets called if the API call fails. It would look like this:
push.register('apns', data.registrationId, null, null, function(err)
{console.log(err);});
Lastly, in Visual Studio, you can also connect to your notification hub and list and manage the registrations. This is useful to determine if the APNS registration is really accepted.

Related

Azure IoT Device: Type error in client.js

I try to get an ARM device connected to Azure IoT Hub. I chose Node.js and got some sample code to get the device connected. I added the required NPM packages such as azure_iot_device, azure_iot_common, azure_iot_http_base.
Within the code, there is one line of code which causes an error.
The line: client.sendEvent(message, printResultFor('send'));
After this, on the debugging console I get the message:
\NodejsWebApp1\node_modules\azure-iot-device\lib\client.js:596
return new Client(new transportCtor(authenticationProvider), null, new blob_upload_1.BlobUploadClient(authenticationProvider));
^
TypeError: transportCtor is not a function
at Function.Client.fromConnectionString
(C:\Users\InterestedGuy\source\repos\NodejsWebApp1\NodejsWebApp1\node_modules\azure-iot-device\lib\client.js:596:27)
at sendmsg (C:\Users\InterestedGuy\source\repos\NodejsWebApp1\NodejsWebApp1\server.js:123:32)
at Server. (C:\Users\InterestedGuy\source\repos\NodejsWebApp1\NodejsWebApp1\server.js:48:9)
at emitTwo (events.js:87:13)
at Server.emit (events.js:172:7)
at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:529:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:88:23)
Press any key to continue...
First guess was that I miss a library so I simply searched the Web where transportCtor should have been defined - but no success.
So the easy question is: where should this function be defined? I would expect the function is part of the Azure IoT SDK but I could not find it. Since the module client.js from azure_iot_device is reporting the error I expect it somewhere within the SDK - but where?
THX for any advice
You should install azure-iot-device-http package to communicate with Azure IoT Hub from any device over HTTP 1.1. You can use this command to get the latest version.
npm install -g azure-iot-device-http#latest
Following code is a tutorial shows how to use this package.
var clientFromConnectionString = require('azure-iot-device-http').clientFromConnectionString;
var Message = require('azure-iot-device').Message;
var connectionString = '[IoT Hub device connection string]';
var client = clientFromConnectionString(connectionString);
var connectCallback = function (err) {
if (err) {
console.error('Could not connect: ' + err);
} else {
console.log('Client connected');
var message = new Message('some data from my device');
client.sendEvent(message, function (err) {
if (err) console.log(err.toString());
});
client.on('message', function (msg) {
console.log(msg);
client.complete(msg, function () {
console.log('completed');
});
});
}
};
client.open(connectCallback);
BTW,for this tutorial you also need to install azure-iot-device package.

Error in Push Notifications while registering for iOS Twilio Voice Client

I am getting the following error while trying to register a user for the Twilio Voice client:
[ERROR VoiceClient] Inside register:deviceToken:completion:, failed to register for Twilio push notifications. Error:Failed to register. Code: 6.
Here is the setup:
Push credentials have been registered with Twilio. A VoIP Push certificate has been registered and those kind of pushes are only in Production mode. Let's say the app ID is "com.bundle.appIDX".
The server side has been setup so that the correct push credentials are fed to the IpMessagingGrant object.
At the client side, the following piece of code is executed:
VoiceClient.sharedInstance().register(withAccessToken: self.accessToken, deviceToken: self.voipToken)
This immediately fails with the error above.
Using version '=2.0.0-beta4' for TwilioVoiceClient, and using version '2.9.1' for twilio-node server side component (https://github.com/twilio/twilio-node/tree/2.9.1).
Tried playing with "Use this credential for sending to a sandbox APN" option and no result.
Tried using both development and provisioning profiles at the client side for the app ID "com.bundle.appIDX".
Is Twilio really supporting VoIP pushes? If yes, what could be wrong with this setup?
Thanks,
Guven.
=======
Edit after Viktor's guidance:
I now manually create the VoiceGrant. I set the value of the key property to 'voice'. Here is what the grant looks like:
{
outgoing_application_sid: 'APXX',
push_credential_sid: 'CRXX',
endpoint_id: 'XX'
}
Still getting the registration error.
I have also tried this format since this is how it looks in 2.11.0 version:
{ outgoing: { application_sid: 'APXX' },
push_credential_sid: 'CRXX',
endpoint_id: 'XX'
}
Any ideas where the problem might be? Attaching the cloud code as well:
var accessToken = new twilio.AccessToken("ACXX", "SKXX", "PPXX", accessTokenOptions);
var voiceGrantConfig = {"outgoingApplicationSid": "APXX",
"endpointId": clientName,
"pushCredentialSid": "CRXX"};
var voiceGrant = new VoiceGrant(voiceGrantConfig);
voiceGrant.key = "voice";
console.log(voiceGrant.toPayload());
accessToken.addGrant(voiceGrant);
var token = accessToken.toJwt();
Edit 2: I have actually upgraded to twilio-node 2.11.0 and still getting the error. Here is the access token right before generating the jwt.
AccessToken {
accountSid: 'ACXX',
keySid: 'SKXX',
secret: 'PPXX',
ttl: 86400,
identity: undefined,
nbf: undefined,
grants:
[ VoiceGrant {
outgoingApplicationSid: 'APXX',
outgoingApplicationParams: undefined,
pushCredentialSid: 'CRXX',
endpointId: 'XX' } ] }
[Edited based on feedback from Guven]
You need a "voice" grant. Otherwise your requests will be denied to the Voice product. You either need to manually add that section to the JSON before signing it or you need to upgrade to the 2.11.0 version. Specifically your token needs to look like this:
{
"sub": "ACxxxx",
"iss": "SKxxxx",
"grants": {
"voice": {
"outgoing": {
"application_sid": "APxxxx"
},
"push_credential_sid": "CRxxxxx"
},
"identity": "voice_test"
},
"jti": "SKxxxxx",
"exp": 1479315711
}
Note, also the "identity" element as well. This is the identifier of your user. Typically its username or an ID of the user record in your system.
Checkout the quickstart app for a code sample for generating the right token (it's in Python but should give you a good idea of how to get started).

React native socket io no events being emitted from client

Trying to use socket.io-client with react-native (ios for now), so far connection / receiving server side events from client seems to be working fine. However I can't seem to emit any events from the client?
Client
var socket = io("http://localhost:3000");
socket.on('connect', function(){
socket.on('ping', function(e) {
console.log('Server emitted ping: ' + e);
socket.emit('pong', 'hi server!');
});
socket.on('disconnect', function(){
console.log("disconnect");
});
});
Server(Node.js)
var io = require('socket.io')(server);
io.on('connection', function (socket) {
console.log('connected...');
socket.on('pong', function (data) {
console.log("Hmm?");
console.log(data);
});
setTimeout(function() {
console.log("Saying hello");
socket.emit('ping', { message: 'Hello from server ' + Date.now() });
}, 1000);
});
So from the server side, I see the logs
connected...
Saying hello
And in the client I see "Server emitted ping...", but the pong event doesn't seem to be doing anything? I tried catching all events on the server through solutions mentioned in StackOverflow, but it looked like no event was coming from the client. Any ideas?
Using latest RN version 0.31.
Also seeing this error when I first run the app in Xcode, could it be the reason?:
[warn][tid:main][RCTEventEmitter.m:52] Sending `websocketFailed` with no listeners registered.
please try:
io.sockets.on('connection', function(socket) {
....
})

in-app purchase Object {message: "Billing is not initialized", code: -3, errorCode: -3}

I am working on ionic meteor using the in-app purchase plugin "cordova-plugin-inapppurchase" (https://github.com/AlexDisler/cordova-plugin-inapppurchase).
When I request 'inAppPurchase.buy(productId)' , I get an error "Object {message: "Billing is not initialized", code: -3, errorCode: -3}"
My code is :
inAppPurchase
.buy('com.myapp.prod1')
.then(function (data) {
console.log(data);
})
.catch(function (err) {
console.log(err);
});
Ionic Information
For ios, it is pretty straight forward, but for android, you need to go to Google playstore, development tool, services and api then copy the base 64 licensing key.
Create a file called manifest.json in the src directory of your ionic project then add the key inside the file in the format below.
{ "play_store_key": "<Base64-encoded public key from the Google Play Store>" }
Add the file to the www folder of the ionic project by adding the path to the angular.json file found in the root folder of the project as shown below.
Sample of angular.json file
call getproducts method before buy or subscribe to initialize the store.
inAppPurchase
.getProducts([
'product.id'
])
.then(function (products) {
$log.debug(products);
})
.catch(function (err) {
$log.error(err);
});
Follow the rest of the instructions here (https://github.com/AlexDisler/cordova-plugin-inapppurchase) and It should work perfectly. Thank you.
got the same error but, I can see that it helps to do:
inAppPurchase
.getProducts([
'product.id'
])
.then(function (products) {
$log.debug(products);
})
.catch(function (err) {
$log.error(err);
});
even through you are fetching your products from, say dbs.
The error (Billing is not initialized) message disappeared after I called the "restore purchases" first.
I now can see the Google Play "BUY" popup screen.

APNS (Apple Push Notification Service) with Node JS

I am looking to create APNS (Apple Push Notification Service), where the server will be sending notifications to the iOS devices.
I am able to make the push notifications work via PHP using the SAME device token and the SAME certificate, however, I would like to send notifications via Node JS instead of PHP.
I have the following valid files/certificates to help me get started:
cert.pem
key.pem
aps_development.cer
cert.p12
key.p12,
ck.pem
I've been looking through several resources/links such as:
https://github.com/argon/node-apn
How to implement APNS notifications through nodejs?
After doing so, I was able to come up with the following sample code, where PASSWORD stands for the password of the key.pem and TOKEN stands for my device's token:
var apn = require("apn");
var path = require('path');
try {
var options = {
cert: path.join(__dirname, 'cert.pem'), // Certificate file path
key: path.join(__dirname, 'key.pem'), // Key file path
passphrase: '<PASSWORD>', // A passphrase for the Key file
ca: path.join(__dirname, 'aps_development.cer'),// String or Buffer of CA data to use for the TLS connection
production:false,
gateway: 'gateway.sandbox.push.apple.com', // gateway address
port: 2195, // gateway port
enhanced: true // enable enhanced format
};
var apnConnection = new apn.Connection(options);
var myDevice = new apn.Device("<TOKEN>");
var note = new apn.Notification();
note.expiry = Math.floor(Date.now() / 1000) + 3600; // Expires 1 hour from now.
note.badge = 3;
note.sound = "ping.aiff";
note.alert = "You have a new message";
note.payload = {'msgFrom': 'Alex'};
note.device = myDevice;
apnConnection.pushNotification(note);
process.stdout.write("******* EXECUTED WITHOUT ERRORS************ :");
} catch (ex) {
process.stdout.write("ERROR :"+ex);
}
I get no errors when executing this code, but The problem is that no notification is received on my iOS device. I have also tried setting the ca:null & debug:true (in options var). But same thing happens.
Again, when I use the ck.pem & device token that I have and use it with PHP, it works, but i'm not able to make it work in Node JS. PLEASE HELP!!
Thank you so much!
You are probably running into the asynchronous nature of NodeJS itself. I use the same node-apn module with great success. But you don't just call it directly like you're used to in PHP - that's a synchronous model that doesn't map from PHP->Node. Your process is exiting before anything can actually happen - the apnConnection.pushNotification(note); is an asynchronous call that just barely gets started before your script returns/exits.
As noted in the node-apn docs you probably want to "listen for" additional events on apnConnection. Here's an excerpt of code that I use to log out various events that are occurring on the connection after it's created:
// We were unable to initialize the APN layer - most likely a cert issue.
connection.on('error', function(error) {
console.error('APNS: Initialization error', error);
});
// A submission action has completed. This just means the message was submitted, not actually delivered.
connection.on('completed', function(a) {
console.log('APNS: Completed sending', a);
});
// A message has been transmitted.
connection.on('transmitted', function(notification, device) {
console.log('APNS: Successfully transmitted message');
});
// There was a problem sending a message.
connection.on('transmissionError', function(errorCode, notification, device) {
var deviceToken = device.toString('hex').toUpperCase();
if (errorCode === 8) {
console.log('APNS: Transmission error -- invalid token', errorCode, deviceToken);
// Do something with deviceToken here - delete it from the database?
} else {
console.error('APNS: Transmission error', errorCode, deviceToken);
}
});
connection.on('connected', function() {
console.log('APNS: Connected');
});
connection.on('timeout', function() {
console.error('APNS: Connection timeout');
});
connection.on('disconnected', function() {
console.error('APNS: Lost connection');
});
connection.on('socketError', console.log);
Equally important, you need to make sure your script STAYS RUNNING while the async requests are being processed. Most of the time, as you build a bigger and bigger service, you're going to end up with some kind of event loop that does this, and frameworks like ActionHero, ExpressJS, Sails, etc. will do this for you.
In the meantime, you can confirm it with this super-crude loop, which just forces the process to stay running until you hit CTRL+C:
setInterval(function() {
console.log('Waiting for events...');
}, 5000);
I will explain it with simple code
First install apn module using this command npm install apn .
Require that module in code
var apn = require('apn');
let service = new apn.Provider({
cert: "apns.pem",
key: "p12Cert.pem",
passphrase:"123456",
production: true //use this when you are using your application in production.For development it doesn't need
});
Here is the main heart of notification
let note = new apn.Notification({
payload:{
"staffid":admins[j]._id,
"schoolid":admins[j].schoolid,
"prgmid":resultt.programid
},
category:"Billing",
alert:"Fee payment is pending for your approval",
sound:"ping.aiff",
topic:"com.xxx.yyy",//this is the bundle name of your application.This key is needed for production
contentAvailable: 1//this key is also needed for production
});
console.log(`Sending: ${note.compile()} to ${ios}`);
services.send(note, ios).then( result => {//ios key is holding array of device ID's to which notification has to be sent
console.log("sent:", result.sent.length);
console.log("failed:", result.failed.length);
console.log(result.failed);
});
services.shutdown();
In Payload you can send data with custom keys.I hope it helps

Resources