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.
(d) Then download google_services.json file, by clicking download button and follow the instructions on that screen. Now the FCM is configured.
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" />
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
Post a Comment