This is a real demenostration of how to use Android Studio with kotlin and wordpress to implement push notification using FirebaseService, onMessageReceived, FirebaseInstanceIdService, onTokenRefresh, sendRegistrationToServer
Folowing up with the previous article is required:
https://ahmadnaser.com/android-wordpress-blog-project-kotlin-volley-retrofit2-gson-okhttp-picasso-ahbottomnavigation/
Then you will be ready to proceed with this step by reserving yours gbeapis
1-reserve your WordPress hosting from greenbackend and get your wordpress greenbackend api license
http://greenbackend.com/developer-hosting
2-ADD the following permissoins and services to the manifest
1 2 3 4 5 6 7 8 |
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<service android:name=".Services.GreenFirebaseService" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <service android:name=".Services.FirebaseInstanceIDService" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> |
3- FirebaseInstanceIDService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package com.ahmadnaser.gbeapiswpblogdemo.Services import android.util.Log import com.google.firebase.iid.FirebaseInstanceId import com.google.firebase.iid.FirebaseInstanceIdService import com.google.firebase.messaging.FirebaseMessaging class FirebaseInstanceIDService : FirebaseInstanceIdService() { val TAG = FirebaseInstanceIDService::class.java.simpleName!! override fun onCreate() { super.onCreate() Log.d(TAG, "onCreate contact firebase instance service"); } override fun onTokenRefresh() { Log.d(TAG, "onTokenRefresh") val refreshedToken = FirebaseInstanceId.getInstance().token // we want to send messages to this application instance and manage this apps subscriptions on the server side // so now send the Instance ID token to the app server refreshedToken?.let { sendRegistrationToServer(it) } } companion object { const val TAG = "GibbyInstanceIdService" } private fun sendRegistrationToServer(refreshedToken: String) { Log.d(TAG, "Refreshed token: $refreshedToken - send this to server?") FirebaseMessaging.getInstance().subscribeToTopic("global") } } |
4- GreenFirebaseService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
package com.ahmadnaser.gbeapiswpblogdemo.Services import android.app.Notification import android.app.Service import android.content.Intent import android.os.IBinder import android.util.Log import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import android.content.Context.NOTIFICATION_SERVICE import android.app.NotificationManager import android.graphics.BitmapFactory import com.ahmadnaser.gbeapiswpblogdemo.R.mipmap.ic_launcher import android.app.PendingIntent import android.content.Context import com.ahmadnaser.gbeapiswpblogdemo.MainActivity import android.media.RingtoneManager import android.support.v4.app.NotificationCompat import android.support.v4.app.TaskStackBuilder import android.text.Html import com.ahmadnaser.gbeapiswpblogdemo.Activities.PostDetailsActivity import com.ahmadnaser.gbeapiswpblogdemo.Fragments.HomeViewModel import com.ahmadnaser.gbeapiswpblogdemo.R class GreenFirebaseService : FirebaseMessagingService() { val TAG = "GreenFirebaseService" override fun onMessageReceived(remoteMessage: RemoteMessage?) { // [START_EXCLUDE] // There are two types of messages data messages and notification messages. Data messages are handled // here in onMessageReceived whether the app is in the foreground or background. Data messages are the type // traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app // is in the foreground. When the app is in the background an automatically generated notification is displayed. // When the user taps on the notification they are returned to the app. Messages containing both notification // and data payloads are treated as notification messages. The Firebase console always sends notification // messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options // [END_EXCLUDE] // TODO(developer): Handle FCM messages here. // Not getting messages here? See why this may be: https://goo.gl/39bRNJ Log.d(TAG, "From: " + remoteMessage!!.from!!) // Check if message contains a data payload. if (remoteMessage.data.size > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.data) } //remoteMessage.getData().containsKey("post_id"); // Check if message contains a notification payload. if (remoteMessage.notification != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.notification!!.body!!) sendNotification(remoteMessage.notification!!.title, remoteMessage.notification!!.body, remoteMessage.data) } if (remoteMessage.notification == null && remoteMessage.data.size > 0) { sendDataNotification(remoteMessage.data) } // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. } // [END receive_message] private fun sendNotification(title: String?, messageBody: String?, data: Map<String, String>) { var intent = Intent(this, MainActivity::class.java) if (data.size > 0 && data.containsKey("post_id")) { intent = Intent(this, PostDetailsActivity::class.java) intent.putExtra(HomeViewModel.POST_ID, data["post_id"]) intent.putExtra(HomeViewModel.POST_NAME, data["post_title"]) intent.putExtra(HomeViewModel.POST_AUTHOR,data["post_date"]) intent.putExtra(HomeViewModel.POST_IMAGE,data["post_image"]) } intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT) val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) val notificationBuilder = NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_home_black_48dp) .setContentTitle(title) .setContentText(messageBody) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager //notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()); } private fun sendDataNotification(data: Map<String, String>) { val stackBuilder = TaskStackBuilder.create(this) val num = System.currentTimeMillis().toInt() if (data.size > 0) { var intent = Intent(this, MainActivity::class.java) if (data.containsKey("post_id")) { intent = Intent(this, PostDetailsActivity::class.java) intent.putExtra(HomeViewModel.POST_ID, data["post_id"]) intent.putExtra(HomeViewModel.POST_NAME, data["post_title"]) intent.putExtra(HomeViewModel.POST_AUTHOR,data["post_date"]) intent.putExtra(HomeViewModel.POST_IMAGE,data["post_image"]) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) stackBuilder.addParentStack(MainActivity::class.java) } else { //if there is splash screen load it intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) stackBuilder.addParentStack(MainActivity::class.java) } stackBuilder.addNextIntentWithParentStack(intent) //PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT); val pendingIntent = stackBuilder.getPendingIntent(num, PendingIntent.FLAG_ONE_SHOT) val title = Html.fromHtml(data["title"]).toString() val messageBody = Html.fromHtml(data["message"]).toString() //Notification Builder val mBuilder = NotificationCompat.Builder( applicationContext).setAutoCancel(true) .setDefaults(Notification.DEFAULT_ALL) .setContentTitle(title) .setSmallIcon(R.drawable.ic_home_black_48dp) .setLargeIcon(BitmapFactory.decodeResource(applicationContext.resources, R.drawable.ic_list_black_48dp)) .setContentText(messageBody) val bigText = NotificationCompat.BigTextStyle() bigText.bigText(messageBody) bigText.setBigContentTitle(title) bigText.setSummaryText(title) mBuilder.setStyle(bigText) mBuilder.setPriority(NotificationCompat.PRIORITY_MAX) mBuilder.setContentIntent(pendingIntent) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(num /* ID of notification */, mBuilder.build()) } } } |