Skip to content

Apple Push Notifications

Karambir Singh Nain edited this page Jan 13, 2016 · 2 revisions

To send push notifications to apple devices, we have to send our requests to Apple push notification service(APNs). We are using django-push-notifications package for this. It implements Device models that can send messages through APNS and GCM. It also implements an admin panel and DRF api views. A simple setup will need following:

  1. Install django-push-notifications with pip and add push_notifications to INSTALLED_APPS in settings.
  2. APns provides a set to certificates for authentication that we have to provide to django-push-notifications. We will have an environment variable that will control which APN certificate and gateway to use(sandbox or prod).
  3. Create a directory certs under ROOT_DIR. Put both certificates, sandbox and prod in it and name them apns_sandbox.pem and apns_prod.pem.
  4. Add following code your settings:
CERTS_DIR = ROOT_DIR.path('certs')

# Determines whether to use APNS SANDBOX OR PROD settings
# Should be True for dev and False for qa and prod environment
PUSH_NOTIFICATIONS_DEBUG = env('PUSH_NOTIFICATIONS_DEBUG', default='sandbox')


CERTS_CHOICES = {
    'sandbox': {
        'cert': 'dev.pem',
        'apns_host': 'gateway.sandbox.push.apple.com',
        'apns_feedback': 'feedback.sandbox.push.apple.com'
    },
    'prod': {
        'cert': 'prod.pem',
        'apns_host': 'gateway.push.apple.com',
        'apns_feedback': 'feedback.push.apple.com'
    },
}

PUSH_NOTIFICATIONS_SETTINGS = {
    'APNS_CERTIFICATE': str(CERTS_DIR.path(CERTS_CHOICES[PUSH_NOTIFICATIONS_DEBUG]['cert'])),
    'APNS_HOST': CERTS_CHOICES[PUSH_NOTIFICATIONS_DEBUG]['apns_host'],
    'APNS_FEEDBACK_HOST': CERTS_CHOICES[PUSH_NOTIFICATIONS_DEBUG]['apns_feedback'],
}

Points to Remember

  • We have to give pathname to these certificate files, as underlying python socket library expect a valid filename.
  • These file should not be password protected.

To check if the certs are setup correctly, try sending push notifications via admin to test feedback service, try this management command:

python manage.py prune_devices

You are all set after this. It is advised to use your own view logic as the default api views are somewhat glitch-y. You can use following:

from rest_framework import status
from rest_framework.response import Response

from push_notifications.api.rest_framework import APNSDeviceAuthorizedViewSet as PNAPNSDeviceAuthorizedViewSet
from push_notifications.models import APNSDevice


class APNSDeviceAuthorizedViewSet(PNAPNSDeviceAuthorizedViewSet):
    """
    Register an iOS device for push notifications
    """
    def create(self, request, *args, **kwargs):
        """
        Get or create a device for a user. If the device with the
        `registration_id` exists already and another user registers, assign
        the device to the new user.
        """
        # Default status code to expect
        status_code = status.HTTP_201_CREATED

        existing_device = APNSDevice.objects.filter(
            registration_id=request.data.get('registration_id')
        ).first()

        if existing_device:
            if existing_device.user == request.user:
                status_code = status.HTTP_200_OK
                return Response(
                    self.serializer_class(existing_device).data,
                    status=status_code
                )
            existing_device.delete()

        # Device doesn't exist, create a new one for the user
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status_code, headers=headers)

Api View features:

  • ios app to only send the apns token (registration_id), and backend to add a new entry if the apns device token doesn't already exist
  • ios app makes a post request with both apns device token. Backend to update/add entry based on the apns token (registration_id)
  • device_id is being ignored for now.
  • If another user enters the same apns token (registration_id), delete the existing device, and create a new device assigning it to the new user.
  • POST to api/devices/apns when the device withe the registration_id already exists for that user will return the existing device instead of a 400 per iOS request
Clone this wiki locally