FCM Integration in Android - Kotlin

                                              

Firebase Cloud Messaging inherits GCM’s core infrastructure but simplifies the client development. It works for all platforms (Android, IOS and Web). Let's see how to integrate FCM in Android with Kotlin.

FCM Messages:

        Two types of FCM messages are there.
  •      Notification messages,  which are handled by the FCM SDK automatically.
  •      Data messages, which are handled by the client app. It can have custom fields, which have to be sent by our server.


1. Configure FCM in Firebase Console



(a) Go to https://console.firebase.google.com/





(b) Then click Add Project, a dialog will be prompted. Enter project name and choose country in it and click on Create Project.





(c) Click on Add Firebase to your Android App, another dialog will be prompted. In that, enter package name (SHA-1 and App Nickname are optional for FCM) and click Register App.


fire4.png


fire5.png
(d) Then download google_services.json file, by clicking download button and follow the instructions on that screen. Now the FCM is configured.


fire6.png


fire7.png


2. Integrate in Application:

               Create new project with Kotlin support and proceed with following.


(a) Make following changes in Project's build.gradle.



buildscript {
  ext.kotlin_version = '1.1.51'
  repositories {
      google()
      jcenter()
  }
  dependencies {
      classpath 'com.android.tools.build:gradle:3.0.0'
      classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
      classpath 'com.google.gms:google-services:3.1.1'
      // NOTE: Do not place your application dependencies here; they belong
      // in the individual module build.gradle files
  }
}


allprojects {
  repositories {
      google()
      jcenter()
  }
}


task clean(type: Delete) {
  delete rootProject.buildDir
}


(b) Make following changes in app's build.gradle.



apply plugin: 'com.android.application'


apply plugin: 'kotlin-android'


apply plugin: 'kotlin-android-extensions'


android {
  compileSdkVersion 26
  defaultConfig {
      applicationId "com.developer.firebasedemo"
      minSdkVersion 15
      targetSdkVersion 26
      versionCode 1
      versionName "1.0"
      testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }
  buildTypes {
      release {
          minifyEnabled false
          proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      }
  }
}


dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar'])
  implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
  implementation 'com.android.support:appcompat-v7:26.1.0'
  implementation 'com.android.support.constraint:constraint-layout:1.0.2'
  testImplementation 'junit:junit:4.12'
  androidTestImplementation 'com.android.support.test:runner:1.0.1'
  androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'


  compile 'com.google.firebase:firebase-messaging:11.4.2'


}


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


(c) Create two services as follows:


FirebaseIDService.kt

        This class handles the token generation and updation on its own.


Token may change on following instances and it will be handled automatically.
  • The app deletes Instance ID
  • The app is restored on a new device
  • The user uninstalls/reinstall the app
  • The user clears app data.


class FirebaseIDService : FirebaseInstanceIdService() {
  internal var dataStorage: DataStorage = DataStorage()


  override fun onTokenRefresh() {
      super.onTokenRefresh()
      // Get updated InstanceID token.
      val refreshedToken = FirebaseInstanceId.getInstance().token
      Log.d("FirebaseIDService", "Refreshed token: " + refreshedToken!!)


      dataStorage.saveFcmToken(applicationContext, refreshedToken)


      // If you want to send messages to this application instance or
      // manage this apps subscriptions on the server side, send the
      // Instance ID token to your app server.
      sendRegistrationToServer(refreshedToken)
  }


  private fun sendRegistrationToServer(refreshedToken: String?) {
      Log.v("Sending to server!!", "Sending==" + refreshedToken!!)
  }
}


FirebaseMessageService.kt


        This class handles the notification received. Both the FCM message types will be handled here.
class FirebaseMessageService : FirebaseMessagingService() {
  private val TAG = "FirebaseMessageService"


  override fun onMessageReceived(remoteMessage: RemoteMessage?) {
      super.onMessageReceived(remoteMessage)


      // Check whether the remoteMessage contains a notification payload.
      if (remoteMessage!!.getNotification() != null) {
          Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()!!)
          sendNotification(remoteMessage.getNotification().getBody())
      }


      //Check whether the remoteMessage contains a data payload.
      if (remoteMessage.getData().size > 0) {
          Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString())
          try {
              val map = remoteMessage.getData()
              handleDataMessage(map)
          } catch (e: Exception) {
              Log.e(TAG, "Exception: " + e.message)
          }


      }
  }


  private fun handleDataMessage(map: Map<String, String>) {
      Log.e(TAG, "push json: " + map.toString())


      try {


          val type = map["type"]
          val id = map["id"]
          val message = map["message"]
          val title = map["title"]


          Log.e(TAG, "type: " + type)
          Log.e(TAG, "message: " + message)
          Log.e(TAG, "id: " + id)


          /** Do the things you would like to do with the data, here **/


      } catch (e: Exception) {
          Log.e(TAG, "Exception: " + e.message)
      }


  }


  private fun sendNotification(messageBody: String?) {
      val channelId: String = getString(R.string.app_name);
      val notificationBuilder: NotificationCompat.Builder =
              NotificationCompat.Builder(this, channelId)
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setContentTitle(getString(R.string.app_name))
                      .setContentText(messageBody)
                      .setAutoCancel(true)


      val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
      notificationManager.notify(2, notificationBuilder.build());
  }
}
(d) Register the created two firebase services in Manifest file.


 <service
          android:name=".FirebaseMessageService">
          <intent-filter>
              <action android:name="com.google.firebase.MESSAGING_EVENT"/>
          </intent-filter>
      </service>
      <service
          android:name=".FirebaseIDService">
          <intent-filter>
              <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
          </intent-filter>
      </service>


(e) Include the following <meta-data> in manifest, to configure the notification to be shown while the app is in background.


 <!-- Set custom default icon. This is used when no icon is set for incoming notification messages. -->
      <meta-data
          android:name="com.google.firebase.messaging.default_notification_icon"
          android:resource="@mipmap/ic_launcher" />
      <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
           notification message. -->
      <meta-data
          android:name="com.google.firebase.messaging.default_notification_color"
          android:resource="@color/colorAccent" />


(f) DataStorage class to store data using SharedPreference

DataStorage.kt



class DataStorage {
  internal lateinit var savedSession: SharedPreferences
  private val KEY: String = ""


  fun saveFcmToken(context: Context, tokenId: String) {
      // TODO Auto-generated method stub
      val editor = context
              .getSharedPreferences(KEY, Activity.MODE_PRIVATE).edit()
      editor.putString("FCM_TOKEN_ID", tokenId)
      editor.commit()


  }


  fun getFcmToken(context: Context): String {
      savedSession = context.getSharedPreferences(KEY, Activity.MODE_PRIVATE)
      return savedSession.getString("FCM_TOKEN_ID", "")


  }
}


3. Run Application



              Now run the application. After that, go to Firebase console and navigate to Notification in Side bar. Then send Notification from there, by choosing any target of your choice. Now the notification has shown up.


Comments

Popular posts from this blog

SOAP Client using ksoap2 in Android - Kotlin

RecyclerView with different number of columns using SpanSizeLookup

Using Camera in Android - Kotlin

Exploring Android Navigation Architecture Component - MVVM - Kotlin

TabLayout in Android with Kotlin

Room with LiveData, ViewModel - Android Architecture Components - Kotlin

Map, Location update and AutoComplete Places - Kotlin

Databinding in RecyclerView - Android - Kotlin

Stripe Integration in Android - Kotlin

Using RxJava, Retrofit in Android - Kotlin