Firebase Cloud Messaging Android Push Notification

Use Firebase console to send FCM messages to device or emulator.

INTRODUCTION

SEND TO A SINGLE DEVICE

  • From Firebase console Notification section, click New Message.
  • Enter the text of your message in the Message Text field.
  • Set the target to Single Device.
  • Check the logs for the InstanceID token, copy and paste it into the Firebase console Token field.
    • If you cannot find the token in your logs, click on the LOG TOKEN button in the application and the token will be logged in logcat.
  • Click on the Send Message button.
  • If your application is in the foreground you should see the incoming message printed in the logs. If it is in the background, a system notification should be displayed. When the notification is tapped, the application should return to the quickstart application.

SEND TO A TOPIC

  • From Firebase console Notification section, click New Message.
  • Enter the text of your message in the Message Text field.
  • Click on the SUBSCRIBE TO NEWS button to subscribe to the news topic.
  • Set the target to Topic.
  • Select the news topic from the list of topics ("news" in this sample). You must subscribe from the device or emulator before the topic will will be visible in the console.
  • Click on the Send Message button.
  • If your application is in the foreground you should see the incoming message printed in the logs. If it is in the background, a system notification should be displayed. When the notification is tapped, the application should return to the quickstart application.

MainActivity


public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create channel to show notifications.       
     String channelId  = getString(R.string.default_notification_channel_id);
      String channelName =
 getString(R.string.default_notification_channel_name);
            NotificationManager notificationManager =
                    getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(new NotificationChannel
               (channelId,
                    channelName, NotificationManager.IMPORTANCE_LOW));
        }

        // If a notification message is tapped, any data accompanying the notification    
    // message is available in the intent extras. In this sample the launcher    
    // intent is fired when the notification is tapped, so any accompanying data would    
    // be handled here. If you want a different intent fired, set the click_action       
 // field of the notification message to the desired intent. The launcher intent       
 // is used when no click_action is specified.        //        
// Handle possible data accompanying notification message.      
  // [START handle_data_extras]        if (getIntent().getExtras() != null) {
            for (String key : getIntent().getExtras().keySet()) {
                Object value = getIntent().getExtras().get(key);
                Log.d(TAG, "Key: " + key + " Value: " + value);
            }
        }
        // [END handle_data_extras]
        Button subscribeButton = findViewById(R.id.subscribeButton);
        subscribeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // [START subscribe_topics]         
       FirebaseMessaging.getInstance().subscribeToTopic("news");
                // [END subscribe_topics]

                // Log and toast            
    String msg = getString(R.string.msg_subscribed);
                Log.d(TAG, msg);
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });

        Button logTokenButton = findViewById(R.id.logTokenButton);
        logTokenButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Get token            
   String token = FirebaseInstanceId.getInstance().getToken();

                // Log and toast           
     String msg = getString(R.string.msg_token_fmt, token);
                Log.d(TAG, msg);
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }

}

MyFirebaseInstanceIDService

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    /**     * Called if InstanceID token is updated.
 This may occur if the security of   
  * the previous token had been compromised. Note that this 
is called when the InstanceID token   
  * is initially generated so this is where you would 
retrieve the token.   
  */    // [START refresh_token]    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.    
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + 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);
    }
    // [END refresh_token]
    /**     * Persist token to third-party servers.     *   
  * Modify this method to associate the user's FCM Instan
ceID token with any server-side account    
 * maintained by your application.     
*     * @param token The new token.     */  
  private void sendRegistrationToServer(String token) {
        // TODO: Implement this method to send token to your app server.    }
}


MyFirebaseMessagingService

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMsgService";

    /**     * Called when message is received.     *    
 * @param remoteMessage Object representing the mess
age received from Firebase Cloud Messaging.     */    
// [START receive_message]    @Override
    public void 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 t
he 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 bac
kground an automatically generated notification is displayed.  
      // When the user taps on the notification they are r
turned to the app. Messages containing both notification

        // and data payloads are treated as notification mess
ages. The Firebase console always sends notification       
 // messages. For more see: https://firebase.google.co
m/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.getFrom());

        // Check if message contains a data payload.      
  if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());

            if (/* Check if data needs to be processed by long running job */
 true) 
{
                // For long-running tasks (10 seconds or more) u
se Firebase Job Dispatcher.                scheduleJob();
            } else {
                // Handle message within 10 seconds         
       handleNow();
            }

        }

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

        // Also if you intend on generating your own not
ifications as a result of a received FCM    
    // message, here is where that should be initia
ted. See sendNotification method below.    }
    // [END receive_message]
    /**     * Schedule a job using FirebaseJobDispatcher.     */  
  private void scheduleJob() {
        // [START dispatch_job]    
    FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher
(new GooglePlayDriver(this));
        Job myJob = dispatcher.newJobBuilder()
                .setService(MyJobService.class)
                .setTag("my-job-tag")
                .build();
        dispatcher.schedule(myJob);
        // [END dispatch_job]    }

    /**     * Handle time allotted to BroadcastReceivers.     */   
 private void handleNow() {
        Log.d(TAG, "Short lived task is done.");
    }

    /**     * Create and show a simple notification containing the received
 FCM message.     *   
  * @param messageBody FCM message body received.    
 */    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0
 /* Request code */, 
intent,
                PendingIntent.FLAG_ONE_SHOT);

        String channelId = getString(R.string.default_notification_channel_id);
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.
TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.drawable.ic_stat_ic_notification)
                .setContentTitle("FCM Message")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0 /* ID of notification */, 
notificationBuilder.build());
    }
}

MyJobService

public class MyJobService extends JobService {

    private static final String TAG = "MyJobService";

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        Log.d(TAG, "Performing long running task in scheduled job");
        // TODO(developer): add long running task here.        return false;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        return false;
    }

}

NotificationChannel | Android Developers Exploring Android O: Notification Channels


public class MyGcmListenerService extends GcmListenerService {

    private static final String TAG = "MyGcmListenerService";
    private NotificationManager notifManager;
    private NotificationChannel mChannel;

    /**     * Called when message is received.     *     
* @param from SenderID of the sender.    

 * @param data Data bundle containing message data as key/value pairs.    
 *             For Set of keys use data.keySet().   
  */    // [START receive_message]    @Override   
 public void onMessageReceived (String from, Bundle data) {
        String message = data.getString ("message");
        Log.d (TAG, "Message: " + message);

        sendNotification (message, message);

        // [END_EXCLUDE]    }
    // [END receive_message]
    /**     * Create and show a simple notification containing the 
received GCM message.     *   
  * @param message GCM message received.     */ 
   private void sendNotification (String message, String title) {
        Intent intent;
        PendingIntent pendingIntent;
        NotificationCompat.Builder builder;
        if (notifManager == null) {
            notifManager = (NotificationManager) getSystemService 
(Context.NOTIFICATION_SERVICE);
        }

        intent = new Intent (this, MainActivity.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_HIGH;
            if (mChannel == null) {
                NotificationChannel mChannel = new NotificationChannel 
("0", title, importance);
                mChannel.setDescription (message);
                mChannel.enableVibration (true);
                mChannel.setVibrationPattern (new long[]
{100, 200, 300, 400, 500, 400, 300, 200, 400});
                notifManager.createNotificationChannel (mChannel);
            }
            builder = new NotificationCompat.Builder (this, "0");

            intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP |
 Intent.FLAG_ACTIVITY_SINGLE_TOP);
            pendingIntent = PendingIntent.getActivity (this, 0, intent, 0);
            builder.setContentTitle (title)  // flare_icon_30             
       .setSmallIcon (R.mipmap.app_icon) // required                 
   .setContentText (message)  // required                
    .setDefaults (Notification.DEFAULT_ALL)
                    .setAutoCancel (true)
                    .setLargeIcon (BitmapFactory.decodeResource 
(getResources (), R.mipmap.app_icon))
                    .setBadgeIconType (R.mipmap.app_icon)
                    .setContentIntent (pendingIntent)
                    .setSound (RingtoneManager.getDefaultUri 
(RingtoneManager.TYPE_NOTIFICATION))
                    .setVibrate (new long[]{100, 200, 300, 400, 
500, 400, 300, 200, 400});
        } else {

            builder = new NotificationCompat.Builder (this);

            intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP |
 Intent.FLAG_ACTIVITY_SINGLE_TOP);
            pendingIntent = PendingIntent.getActivity (this, 0, intent, 0);
            builder.setContentTitle (title)
                    .setSmallIcon (R.mipmap.app_icon) // required  
                  .setContentText (message)  // required            
        .setDefaults (Notification.DEFAULT_ALL)
                    .setAutoCancel (true)
                    .setContentIntent (pendingIntent)
                    .setSound (RingtoneManager.getDefaultUri 
(RingtoneManager.TYPE_NOTIFICATION))
                    .setVibrate (new long[]{100, 200, 300, 400, 500,
 400, 300, 200, 400})
                    .setPriority (Notification.PRIORITY_HIGH);
        } // else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Notification notification = builder.build ();
        notifManager.notify (0, notification);
    }
}