taivo / parse-push-plugin

Push notification plugin for Cordova/Phonegap/ionic on Parse platform
118 stars 102 forks source link

Parse.Push Plugin

Parse.Push plugin for Cordova/Phonegap/ionic. Works for both hosted Parse.com and open source parse-server.

Highlights

Works with Parse.com and parse-server

Supports Android and iOs 8, 9, 10

Handles cold start out-of-the-box

Simple Setup

  1. cordova plugin add https://github.com/taivo/parse-push-plugin
  2. Set app id, server URL, and keys as config.xml preference tags.
  3. Done! No fuss with Objective C, AndroidManifest, or Java

Simple API

Notification events

Handle openPN, receivePN, receivePN:customEvt anywhere in your javascript code.


   ParsePushPlugin.on('receivePN', function(pn){
       console.log('yo i got this push notification:' + JSON.stringify(pn));
   });

   //
   // Use custom events to simulate separate communication channels using push notification.
   // Just set an 'event' key in the push payload made from your server. If you set {event: "x"},
   // you'll be able to catch it via "receivePN:x"
   //
   ParsePushPlugin.on('receivePN:chat', function(pn){
       console.log('yo i can also use custom event to keep things like chat modularized');
   });
   ParsePushPlugin.on('receivePN:system-maintenance', function(pn){
       console.log('yo, here is a system maintenance payload');
   });

   //
   // When you open a notification from the system tray, `openPN` is also triggered.
   // You can use it to do things like navigating to a different page or refreshing data.
   ParsePushPlugin.on('openPN', function(pn){
       //you can do things like navigating to a different view here
       console.log('Yo, I get this when the user taps open a notification from the tray');
   });

Multiple notifications

Android: to prevent flooding the notification tray, this plugin retains only the last PN with the same title field. For messages without the title field, the application name is used. A count of unopened PNs is shown.

You can override this feature, however, by adding the following to config.xml:

   <preference name="ParseMultiNotifications" value="true" />

Foreground vs. Background

Android: Mimic the iOS behavior and create a notification in the system tray when app is off or in background. When app is in foreground, PN payloads are forwarded via the receivePN and receivePN:customEvt events.

iOS: Forward the PN payload to javascript in foreground mode. When app inactive or in background, iOS holds PNs in the tray. Only when the user opens these PNs would we have access and forward them to javascript.

Installation

Install Push Certificates on Server:

Add Plugin

cordova plugin add https://github.com/taivo/parse-push-plugin

Create the following tags in config.xml:

You're all set. The plugin takes care of initializing Parse platform using the config.xml preferences mentioned above. It also saves your installation to the database automatically.

To customize push notifications, initialize Parse platform yourself, or use your own MainApplication.java in Android, see the Advanced Configuration section.

Usage

When your app starts, ParsePushPlugin automatically obtains and stores necessary device tokens to your native ParseInstallation. It also registers a javascript callback that will be triggered when a push notification is opened or received.

Receiving push notifications

Anywhere in your code, you can set a listener for notification events using the ParsePushPlugin object.

$ionicPlatform.ready(function(){
   if(window.ParsePushPlugin){
    ParsePushPlugin.on('receivePN', function(pn){
        alert('yo i got this push notification:' + JSON.stringify(pn));
    });

    //
    //you can also listen to your own custom events
    // Note: to push custom event, include 'event' key in your push payload,
      // e.g. {alert: "sup", event:'chat'}
    ParsePushPlugin.on('receivePN:chat', chatEventHandler);
    ParsePushPlugin.on('receivePN:serverMaintenance', serverMaintenanceHandler);

      //
      // When the app is off or in background, push notifications get added
      // to the notification tray. When a user open a notification, you
      // can catch it via openPN
      ParsePushPlugin.on('openPN', function(pn){
        alert('a notification was opened:' + JSON.stringify(pn));
    });
   }
});

Subscriptions and Installation Id

$ionicPlatform.ready(function(){
   if(window.ParsePushPlugin){
      ParsePushPlugin.getInstallationId(function(id) {
         // note that the javascript client has its own installation id,
         // which is different from the device installation id.
          alert("device installationId: " + id);
      }, function(e) {
          alert('error');
      });

      ParsePushPlugin.getSubscriptions(function(subscriptions) {
          alert(subscriptions);
      }, function(e) {
          alert('error');
      });

      ParsePushPlugin.subscribe('SampleChannel', function(msg) {
          alert('OK');
      }, function(e) {
          alert('error');
      });

      ParsePushPlugin.unsubscribe('SampleChannel', function(msg) {
          alert('OK');
      }, function(e) {
          alert('error');
      });
   }
});

Navigate to a specific view when user opens a notification

If your app is already on (or in the background), you can simply perform page switching in javascript. Just add a urlHash field in your PN payload that contains either a url hash, i.e. #myhash, or a url parameter string, i.e. ?param1=a&param2=b. Then catch that field via the openPN event and go from there.

ParsePushPlugin.on('openPN', function(pn){
    if(pn.urlHash){
        window.location.hash = hash;
    }
});

For cold start, you can also let your cordova app finish loading and use javascript to handle page switching. Carry out this type of page switching while the spashscreen is still visible for a better user experience.

Directly launching a non-default url via native code is also possible. Here are some hints on how to do that:

Android: If urlHash starts with "#" or "?", this plugin will pass it along as an extra in the android intent to launch your MainActivity. You can then launch the custom url in MainActivity.onCreate this way:

@Override
public void onCreate(Bundle savedInstanceState)
{
    //
    // your code...
    //

    String urlHash = intent.hasExtra("urlHash") ? intent.getStringExtra("urlHash") : "";
    loadUrl(launchUrl + urlHash);
}

iOS: On cold start via notification, didFinishLaunchingWithOptions and this plugin's didLaunchViaNotification have access to the payload. Those 2 functions are good starting points for launching custom url.

Silent Notifications

For Android, a silent notification can be sent by omitting the title and alert fields in the JSON payload. This means the push notification will not be shown in the system tray, but its JSON payload will still be delivered to your receivePN and receivePN:customEvt handlers.

Advanced Configuration

Android:

The actual code that handles Parse platform initialization is in ParsePushApplication.java.

Android knows to use this class due to the attribute android:name in <application> in 'platforms/android/app/src/main/AndroidManifest.xml'. To preserve your customizations, this plugin sets android:name="github.taivo.parsepushplugin.ParsePushApplication"
if and only if android:name is not already defined. It does this during plugin installation. Similarly, when the plugin is uninstalled, android:name will be removed only if its content matches github.taivo.parsepushplugin.ParsePushApplication exactly.

If you use your own Application class, don't forget to update android:name to point to it.

Optional: Write your own MainApplication and/or initialize Parse yourself: Look at ParsePushApplication.java. The comments contain all the explanations and hints you will need. Mimic the code to write your own customized implementation.

Optional: Customize background color for the push notification icon in Android Lollipop: Go to your platforms/android/res/values folder and create a file named colors.xml. Paste the following content in it and replace the hex color value of the form #AARRGGBB to your liking.

       <?xml version="1.0" encoding="utf-8"?>
      <resources>
         <color name="parse_push_icon_color">#ff112233</color>
      </resources>

You can provide a property ParseNotificationIcon in config.xml to provide a custom android notification icon for Android Lollipop and above like this:

    <preference name="ParseNotificationIcon" value="android_notification_icon" />

The icon has to be in folder resources in project root and with extension .png. The icon is then copied to platforms/android/app/src/main/res/drawable/<PROVIDED-NAME>.png. For details, how to design the icon have a look at https://clevertap.com/blog/fixing-notification-icon-for-android-lollipop-and-above/

iOS:

By default, ParsePushPlugin automatically registers your device for push notification on app startup. This means your app will ask for push notification permission at the very beginning of the first app start. For UX reason, you may want to delay asking the user for that permission until you absolutely need it. To do so, add <preference name="ParseAutoRegistration" value="false" /> to config.xml and manually call ParsePushPlugin.register(successCB, errorCB) in your javascript.

If you want to completely customize your notification settings, use the method didFinishLaunchingWithOptions in AppDelegate+parsepush.m as a guide to modify the same method in your platforms/ios/ProjectName/Classes/AppDelegate.m.

When you initialize Parse from your own platforms/ios/ProjectName/Classes/AppDelegate.m, this plugin will skip it's version of Parse initialization and notification setup, that way it won't override your customization.

Troubleshooting

General:

Android:

iOS:

This plugin takes advantage of the cordova.exec bridge. If calls to cordova.exec only gets triggered after pressing your device's Home button, try inspecting your Content-Security-Policy. Your frame-src must allow gap: because the cordova bridge on iOS works via Iframe.