FCM

As everyone knows the importance of push notification in apps, we will discuss FCM (Firebase Cloud Messaging) in this article.
Let’s see what the definition of FCM is.
Firebase Cloud Messaging is a powerful API that lets you deliver the messages reliably and independently of the platform you are developing on. With the help of FCM, you can send notification and message to your client’s app. We can send instant messages of up to 4KB in size.
Before moving ahead, we will summarize how we are going to implement it.
Android app to display a notification
MyFirebaseInstanceIDService.java
  1. package com.infobytessolutions.sretailer;
  2. /**
  3. * Created by Nilesh on 05/12/2017.
  4. */
  5. import android.util.Log;
  6. import com.google.firebase.iid.FirebaseInstanceId;
  7. import com.google.firebase.iid.FirebaseInstanceIdService;
  8. public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
  9. private static final String TAG = "MyFirebaseIIDService";
  10. @Override
  11. public void onTokenRefresh() {
  12. //Getting registration token
  13. String refreshedToken = FirebaseInstanceId.getInstance().getToken();
  14. //Displaying token on logcat
  15. Log.d(TAG, "Refreshed token: " + refreshedToken);
  16. //calling the method store token and passing token
  17. storeToken(refreshedToken);
  18. }
  19. private void storeToken(String token) {
  20. //saving the token on shared preferences
  21. SharedPrefManager.getInstance(getApplicationContext()).saveDeviceToken(token);
  22. }
  23. }
SharedPrefManager.java
  1. package com.infobytessolutions.sretailer;
  2. /**
  3. * Created by Nilesh on 05/12/2017.
  4. */
  5. import android.content.Context;
  6. import android.content.SharedPreferences;
  7. public class SharedPrefManager {
  8. private static final String SHARED_PREF_NAME = "FCMSharedPref";
  9. private static final String TAG_TOKEN = "tagtoken";
  10. private static SharedPrefManager mInstance;
  11. private static Context mCtx;
  12. private SharedPrefManager(Context context) {
  13. mCtx = context;
  14. }
  15. public static synchronized SharedPrefManager getInstance(Context context) {
  16. if (mInstance == null) {
  17. mInstance = new SharedPrefManager(context);
  18. }
  19. return mInstance;
  20. }
  21. //this method will save the device token to shared preferences
  22. public boolean saveDeviceToken(String token){
  23. SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
  24. SharedPreferences.Editor editor = sharedPreferences.edit();
  25. editor.putString(TAG_TOKEN, token);
  26. editor.apply();
  27. return true;
  28. }
  29. //this method will fetch the device token from shared preferences
  30. public String getDeviceToken(){
  31. SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
  32. return sharedPreferences.getString(TAG_TOKEN, null);
  33. }
  34. }
MyFirebaseMessagingService.java
  1. package com.infobytessolutions.sretailer;
  2. /**
  3. * Created by Nilesh on 05/12/2017.
  4. */
  5. import android.app.NotificationManager;
  6. import android.app.PendingIntent;
  7. import android.content.Context;
  8. import android.content.Intent;
  9. import android.media.RingtoneManager;
  10. import android.net.Uri;
  11. import android.support.v4.app.NotificationCompat;
  12. import android.util.Log;
  13. import com.google.firebase.messaging.FirebaseMessagingService;
  14. import com.google.firebase.messaging.RemoteMessage;
  15. import org.json.JSONException;
  16. import org.json.JSONObject;
  17. public class MyFirebaseMessagingService extends FirebaseMessagingService {
  18. private static final String TAG = "MyFirebaseMsgService";
  19. @Override
  20. public void onMessageReceived(RemoteMessage remoteMessage) {
  21. if (remoteMessage.getData().size() > 0) {
  22. Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
  23. try {
  24. JSONObject json = new JSONObject(remoteMessage.getData().toString());
  25. // sendPushNotification(json);
  26. sendNotification(json);
  27. } catch (Exception e) {
  28. Log.e(TAG, "Exception: " + e.getMessage());
  29. }
  30. }
  31. }
  32. private void sendNotification(JSONObject json) {
  33. Intent intent = new Intent(this, MainActivity.class);
  34. intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
  35. Log.e(TAG, "Notification JSON " + json.toString());
  36. try{
  37. JSONObject data = json.getJSONObject("data");
  38. String title = data.getString("title");
  39. String message = data.getString("message");
  40. String imageUrl = data.getString("image");
  41. PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
  42. PendingIntent.FLAG_ONE_SHOT);
  43. Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
  44. NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
  45. .setSmallIcon(R.drawable.ic_launcher_background)
  46. .setContentTitle(title)
  47. .setContentText(message)
  48. .setAutoCancel(true)
  49. .setSound(defaultSoundUri)
  50. .setContentIntent(pendingIntent);
  51. NotificationManager notificationManager =
  52. (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  53. notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
  54. } catch (JSONException e) {
  55. Log.e(TAG, "Json Exception: " + e.getMessage());
  56. } catch (Exception e) {
  57. Log.e(TAG, "Exception: " + e.getMessage());
  58. }
  59. }
  60. }
activity_main.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:id="@+id/activity_main"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:paddingBottom="@dimen/activity_vertical_margin"
  8. android:paddingLeft="@dimen/activity_horizontal_margin"
  9. android:paddingRight="@dimen/activity_horizontal_margin"
  10. android:paddingTop="@dimen/activity_vertical_margin"
  11. tools:context=".MainActivity">
  12. <EditText
  13. android:id="@+id/editTextPhoneNo"
  14. android:layout_width="match_parent"
  15. android:layout_height="wrap_content"
  16. android:layout_above="@+id/buttonRegister"
  17. android:hint="Enter Phone No"
  18. android:inputType="phone" />
  19. <Button
  20. android:layout_centerVertical="true"
  21. android:text="Register Device"
  22. android:id="@+id/buttonRegister"
  23. android:layout_width="match_parent"
  24. android:layout_height="wrap_content" />
  25. </RelativeLayout>
MainActivity.java
  1. package com.infobytessolutions.sretailer;
  2. import android.app.ProgressDialog;
  3. import android.os.Bundle;
  4. import android.os.StrictMode;
  5. import android.util.Log;
  6. import android.view.View;
  7. import android.support.v7.app.AppCompatActivity;
  8. import android.widget.Button;
  9. import android.widget.EditText;
  10. import android.widget.TextView;
  11. import android.widget.Toast;
  12. import com.google.firebase.messaging.FirebaseMessaging;
  13. import org.ksoap2.SoapEnvelope;
  14. import org.ksoap2.serialization.SoapObject;
  15. import org.ksoap2.serialization.SoapSerializationEnvelope;
  16. import org.ksoap2.transport.AndroidHttpTransport;
  17. import org.xmlpull.v1.XmlPullParserException;
  18. import java.io.IOException;
  19. public class MainActivity extends AppCompatActivity
  20. implements View.OnClickListener {
  21. //defining views
  22. private Button buttonRegister ;
  23. private TextView textViewToken;
  24. private EditText editTextPhoneNo;
  25. private ProgressDialog progressDialog;
  26. @Override
  27. protected void onCreate(Bundle savedInstanceState) {
  28. super.onCreate(savedInstanceState);
  29. setContentView(R.layout.activity_main);
  30. //getting views from xml
  31. editTextPhoneNo= (EditText) findViewById(R.id.editTextPhoneNo);
  32. buttonRegister = (Button) findViewById(R.id.buttonRegister);
  33. //adding listener to view
  34. buttonRegister.setOnClickListener(this);
  35. onNewIntent(getIntent());
  36. FirebaseMessaging.getInstance();
  37. }
  38. private void sendTokenToServer(){
  39. progressDialog = new ProgressDialog(this);
  40. progressDialog.setMessage("Registering Device...");
  41. progressDialog.show();
  42. final String token = SharedPrefManager.getInstance(this).getDeviceToken();
  43. final String phoneNo = editTextPhoneNo.getText().toString();
  44. if (token == null) {
  45. progressDialog.dismiss();
  46. Toast.makeText(this, "Token not generated", Toast.LENGTH_LONG).show();
  47. return;
  48. }
  49. String TAG = "Update token id";
  50. String nameSpace="http://ws.mywebservice.com/";
  51. String url="http://ws.mywebservice.com/WebService.asmx";
  52. String SOAPACTION_getLandmark="http://ws.mywebservice.com/updateTokenID";
  53. String method_name_getLandmark="updateTokenID";
  54. // Allow internet
  55. if (android.os.Build.VERSION.SDK_INT > 9) {
  56. StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
  57. .permitAll().build();
  58. StrictMode.setThreadPolicy(policy);
  59. }
  60. SoapObject Request = new SoapObject(nameSpace,method_name_getLandmark);
  61. Request.addProperty("phoneNo",phoneNo.trim());
  62. Request.addProperty("TokenID",token);
  63. // Create a envelope
  64. SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
  65. SoapEnvelope.VER12);
  66. envelope.dotNet = true;
  67. envelope.setOutputSoapObject(Request);
  68. try {
  69. AndroidHttpTransport transp = new AndroidHttpTransport(url);
  70. transp.call(SOAPACTION_getLandmark, envelope);
  71. SoapObject obj1 = (SoapObject) envelope.bodyIn;
  72. // String obj2 =(String) obj1.getProperty(0);
  73. Log.d("Token:----", obj1.toString());
  74. // Log.d("OTP:----", obj1.getProperty(0).toString());
  75. Log.d(TAG, "Token finished");
  76. } catch (IOException e) {
  77. Log.d(e.getMessage(), "Token");
  78. e.printStackTrace();
  79. } catch (XmlPullParserException e) {
  80. e.printStackTrace();
  81. }
  82. progressDialog.dismiss();
  83. }
  84. @Override
  85. public void onClick(View view) {
  86. if (view == buttonRegister) {
  87. //getting token from shared preferences
  88. String token = SharedPrefManager.getInstance(this).getDeviceToken();
  89. //if token is not null
  90. if (token != null) {
  91. //displaying the token
  92. // textViewToken.setText(token);
  93. sendTokenToServer();
  94. } else {
  95. //if token is null that means something wrong
  96. textViewToken.setText("Token not generated");
  97. }
  98. }
  99. }
  100. }
AndroidManifest.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.infobytessolutions.sretailer">
  4. <uses-permission android:name="android.permission.INTERNET" />
  5. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  6. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  7. <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
  8. <uses-permission android:name="android.permission.WAKE_LOCK"/>
  9. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  10. <uses-permission android:name="android.permission.VIBRATE" />
  11. <permission
  12. android:name="${applicationId}.permission.C2D_MESSAGE"
  13. android:protectionLevel="signature"/>
  14. <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/>
  15. <application
  16. android:allowBackup="true"
  17. android:icon="@mipmap/ic_launcher"
  18. android:label="@string/app_name"
  19. android:roundIcon="@mipmap/ic_launcher_round"
  20. android:supportsRtl="true"
  21. android:theme="@style/AppTheme">
  22. <activity
  23. android:name=".MainActivity"
  24. android:label="@string/app_name"
  25. android:theme="@style/AppTheme.NoActionBar">
  26. <intent-filter>
  27. <action android:name="android.intent.action.MAIN" />
  28. <category android:name="android.intent.category.LAUNCHER" />
  29. </intent-filter>
  30. </activity>
  31. <service
  32. android:name=".MyFirebaseInstanceIDService">
  33. <intent-filter>
  34. <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
  35. </intent-filter>
  36. </service>
  37. <service
  38. android:name=".MyFirebaseMessagingService">
  39. <intent-filter>
  40. <action android:name="com.google.firebase.MESSAGING_EVENT"/>
  41. </intent-filter>
  42. </service>
  43. </application>
  44. </manifest>
Setting up FCM in Firebase console
Saving token ID generated from android device to server using web service developed in .net
If you have knowledge of creating a web service, then add the below code to it, else learn it by searching on Google because our main focus in this article is FCM.
To run web service properly in Android, you have to add ksoap2-android-assembly-2.5.8-jar-with-dependencies.jar in Android project.
Also, have a look at mainactivity.java file's sendTokenToServer() method where web service call is handled.
Sending notification message from C# code
Create a new C# project and add the following class and call it in any event like button.
  1. public class FCMPushNotification {
  2. public FCMPushNotification() {
  3. // TODO: Add constructor logic here
  4. }
  5. public bool Successful {
  6. get;
  7. set;
  8. }
  9. public string Response {
  10. get;
  11. set;
  12. }
  13. public Exception Error {
  14. get;
  15. set;
  16. }
  17. public FCMPushNotification SendNotification(string _title, string _message, string _topic, string deviceId) {
  18. FCMPushNotification result = new FCMPushNotification();
  19. try {
  20. result.Successful = true;
  21. result.Error = null;
  22. // var value = message;
  23. string serverKey = "Your server key";
  24. string senderId = "your sender id";
  25. var requestUri = "https://fcm.googleapis.com/fcm/send";
  26. WebRequest webRequest = WebRequest.Create(requestUri);
  27. webRequest.Method = "POST";
  28. webRequest.Headers.Add(string.Format("Authorization: key={0}", serverKey));
  29. webRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
  30. webRequest.ContentType = "application/json";
  31. var data = new {
  32. to = deviceId, // this if you want to test for a single device
  33. // to = "/topics/" + _topic, // this is for topic
  34. priority = "high",
  35. notification = new {
  36. title = _title,
  37. body = _message,
  38. show_in_foreground = "True",
  39. icon = "myicon"
  40. }
  41. };
  42. var serializer = new JavaScriptSerializer();
  43. var json = serializer.Serialize(data);
  44. Byte[] byteArray = Encoding.UTF8.GetBytes(json);
  45. webRequest.ContentLength = byteArray.Length;
  46. using(Stream dataStream = webRequest.GetRequestStream()) {
  47. dataStream.Write(byteArray, 0, byteArray.Length);
  48. using(WebResponse webResponse = webRequest.GetResponse()) {
  49. using(Stream dataStreamResponse = webResponse.GetResponseStream()) {
  50. using(StreamReader tReader = new StreamReader(dataStreamResponse)) {
  51. String sResponseFromServer = tReader.ReadToEnd();
  52. result.Response = sResponseFromServer;
  53. }
  54. }
  55. }
  56. }
  57. } catch (Exception ex) {
  58. result.Successful = false;
  59. result.Response = null;
  60. result.Error = ex;
  61. }
  62. return result;
  63. }
  64. }
How to get server key and sender id
So that’s it. Though a few mobile phones will kill this notification when an application is killed. I am working on it too. Feel free to comment, I would like to guide you if you are stuck somewhere and also like to learn more from you guys.