🎉 New! Web Push Notifications for Chatkit. Learn more in our latest blog post.
Hide
Products
chatkit_full-logo

Extensible API for in-app chat

channels_full-logo

Build scalable realtime features

beams_full-logo

Programmatic push notifications

Developers

Docs

Read the docs to learn how to use our products

Tutorials

Explore our tutorials to build apps with Pusher products

Support

Reach out to our support team for help and advice

Sign in
Sign up

Migrating from GCM to Pusher Beams

  • Neo Ighodaro

June 11th, 2019
This tutorial uses an Android demo app.

Introduction

As most of you are aware, Google deprecated Google Cloud Messaging (GCM) on April 10, 2018, and completely removed support for it on May 29, 2019. And so, it is expected that by now you should have migrated to another messaging service or be on the verge of doing so.

Fortunately, Pusher has a solution called Beams that serves this purpose. In this tutorial, we will see how we can migrate an app built with GCM to Pusher Beams.

Understanding a GCM project

For this post, we will be looking at Google’s sample project using GCM here. Let us gain some understanding of what the major files and classes there do:

  • MyGcmListenerService: this is a service class that helps us detect when there is a new message. This service extends the GcmListenerService class and overrides the onMessageReceived method to give information about the new message.
  • RegistrationIntentService: this service is where we fetch our device token and send to the server. As you know, with messaging services, each device will have a device token that you can send to your server in case you need to send messages to a specific device. This service helps us register the token.
  • MyInstanceIDListenerService: this service is used to tell us then the device token has been updated.
  • MainActivity: this is the main activity of the application where the receiver is registered and unregistered. Using GCM requires Google Play Services, in this class, checks like that are performed.

Having understood what these files do, let us see how we can migrate our app to use Pusher Beams instead.

Creating a Firebase project

Recent GCM apps were created with Firebase and if you fall into this category, you can skip this part. However, if your app was created from the Google developers console, follow along.

Go to your Firebase console, choose the Add a project card, then you select your former project from the dropdown and add Firebase to it like this.

This will create a new project on Firebase with the same name. Now, select the Android icon to add an Android app to your Firebase project. Add your package name and register the app.

Thereafter, you download the google-services.json file. After downloading the file, skip the rest of the guide. Now, open your project and add the google-services.json file to your app directory (GCMSample/app/google-services.json).

Creating a Pusher Beams instance

Before creating a Pusher Beams instance, you need an FCM key. By now, you should have your Firebase project ready. Open the project, select the project settings and select the Cloud messaging tab. There, you will find the server key. Copy it out as you will need soon.

After that, open your Pusher Beams dashboard and create a new instance.

After creating the instance, select the Android quickstart. The first step is to enter your server key which you got from Firebase. After that, cancel the rest of the quickstart.

Updating our dependencies

Open your project build.gradle file and make sure you have this dependency:

    dependencies {
        // other dependencies
        classpath 'com.google.gms:google-services:4.2.0'
    }

Next, open your app build.gradle file, remove this dependency:

    implementation "com.google.android.gms:play-services-gcm:15.0.1"

And add these dependencies:

    implementation 'com.google.firebase:firebase-messaging:17.6.0'
    implementation 'com.pusher:push-notifications-android:1.4.0'

Also, make sure this plugin is applied at the end of the file:

    apply plugin: 'com.google.gms.google-services'

After that, sync your gradle files so that the new dependencies will be downloaded for you.

Rewriting our services

Now, we will delete all the service classes from our project - MyGcmListenerService, MyInstanceIDListenerService and RegistrationIntentService. We will then replace all these services with a single service class.

Create a new class named NotificationsMessagingService and paste this:

    import android.app.NotificationChannel
    import android.app.NotificationManager
    import android.app.PendingIntent
    import android.content.Intent
    import android.os.Build
    import androidx.core.app.NotificationCompat
    import androidx.core.app.NotificationManagerCompat
    import com.google.firebase.messaging.RemoteMessage
    import com.pusher.pushnotifications.fcm.MessagingService

    class NotificationsMessagingService : MessagingService() {

        override fun onNewToken(token: String) {
            super.onNewToken(token)
        }

        override fun onMessageReceived(remoteMessage: RemoteMessage) {
            showNotification(remoteMessage)
        }

    }

This class extends the MessagingService class. And so, we can implement two methods essential to our migration:

  • onNewToken - This is called when the device token is updated.
  • onMessageReceived - This is called when a new message is received.

Implementing the onMessageReceived method is compulsory, while the onNewToken method is not. In the onMessageReceived method, we called another function to display a notification. You can add the function like so:

    private fun showNotification(remoteMessage: RemoteMessage) {

        val notificationId = 10
        val channelId  = "migration"
        lateinit var channel:NotificationChannel
        val intent = Intent(this, MainActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
        val mBuilder = NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(remoteMessage.notification!!.title!!)
            .setContentText(remoteMessage.notification!!.body!!)
            .setContentIntent(pendingIntent)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setAutoCancel(true)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationManager = applicationContext.getSystemService(NotificationManager::class.java)
            val name = getString(R.string.channel_name)
            val description = getString(R.string.channel_description)
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            channel = NotificationChannel("migration-channel", name, importance)
            channel.description = description
            notificationManager!!.createNotificationChannel(channel)
            notificationManager.notify(notificationId, mBuilder.build())

        } else {
            val notificationManager =  NotificationManagerCompat.from(this)
            notificationManager.notify(notificationId, mBuilder.build())
        }

    }

Since devices running Android O and above have a unique way of handling notifications, we have to cater to that in the method. You also need to add these resources in the strings.xml file as we used them in the snippet above:

    <string name="channel_name">beams</string>
    <string name="channel_description">Display notifications with Pusher Beams</string>

After writing our service class, the next thing is to declare it in our AndroidManifest.xml file. Remove the previously declared services and add this new one:

    <service android:name=".NotificationsMessagingService">
        <intent-filter android:priority="1">
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

You should also remove these permissions as you do not need them any longer:

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

Also, remove the receiver from the manifest:

    <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="com.neo.gcmsample" />
        </intent-filter>
    </receiver>

Finishing up

Finally, we need to initialize Pusher Beams and subscribe for specific topics and we will do that in the MainActivity which is the starting activity.

In the class, replace everything with this:

    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import com.pusher.pushnotifications.PushNotifications

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            PushNotifications.start(applicationContext, "PUSHER_INSTANCE_ID")
            PushNotifications.addDeviceInterest("hello")
        }
    }

Replace the PUSHER_INSTANCE_ID placeholder with your own key from your dashboard.

In this final snippet, we initialized Beams and subscribed to the hello topic. You can subscribe to as many topics as you want.

Conclusion

Great! You have successfully migrated your app from using GCM to Pusher Beams. You have nothing to fear as Google is about to remove support for GCM. Feel free to play around with the repository and comment if you encounter any hurdles.

Clone the project repository
  • Android
  • Beams
  • Beams

Products

  • Channels
  • Chatkit
  • Beams

© 2019 Pusher Ltd. All rights reserved.

Pusher Limited is a company registered in England and Wales (No. 07489873) whose registered office is at 160 Old Street, London, EC1V 9BW.