androidpush-notificationgoogle-cloud-messaginggcmlistenerservice

How to show custom UI for a GCM push notification?


I want to show a notification like in the snap below in my app:

Push Notification

I have already gone through this question and this Github issue. It says you have to send your data as payload in the message to GCM server, and you can access this data in the app through intent when the user clicks on the notification.

The message I am sending is:

body: {"to":"\/topics\/global","data":{"LOL":"abc","LOL1":"xyz"},"notification":{"icon":"icon","title":"App Notification Title","body":"qwerty","click_action":"notification_click_action","sound":"default"}}

This is my code of GCM listener service:

   public class MyGcmListenerService extends GcmListenerService {

    VolleySingleton mVolleySingleton;
    ImageLoader mImageLoader;
    Bitmap bitmap;

    /**
     * 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) {

        Log.e("Message Received: ", from);

        String title = data.getString("title");
        System.out.println("Title "+ data.toString());
        String subTitle = data.getString("subTitle");
        String expandTitle = data.getString("expandTitle");
        String imageUrl = data.getString("imageUrl");
        String action = data.getString("action");
        String offerAction = data.getString("offerAction");
        String offerImageUrl = data.getString("offerImageUrl");
        System.out.println(bundleToString(data));

        sendNotification(data);
    }

    @Override
    public void onDeletedMessages() {
//        sendNotification("Deleted messages on server");
    }

    @Override
    public void onMessageSent(String msgId) {
//        sendNotification("Upstream message sent. Id=" + msgId);
    }

    @Override
    public void onSendError(String msgId, String error) {
//        sendNotification("Upstream message send error. Id=" + msgId + ", error" + error);
    }

    private void sendNotification(final Bundle data) {

        if(data.getString("imageUrl") == null){
            sendNotification(data,null);
        } else {
            mVolleySingleton = VolleySingleton.getInstance();
            
            Handler uiHandler = new Handler(Looper.getMainLooper());
            uiHandler.post(new Runnable() {
                @Override
                public void run() {
                    mImageLoader = mVolleySingleton.getImageLoader();
                    mImageLoader.get(data.getString("imageUrl"), new ImageLoader.ImageListener() {
                        @Override
                        public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {

                            if (response.getBitmap() != null) {
                                bitmap = response.getBitmap();
                                sendNotification(data, bitmap);
                            }
                        }

                        @Override
                        public void onErrorResponse(VolleyError error) {
                            bitmap = null;/*BitmapFactory.decodeResource(getApplicationContext().getResources(),
                            R.mipmap.logo);*/
                        }
                    });
                }
            });

        }
    }

    private void sendNotification(Bundle data,Bitmap bitmap){

        String title = data.getString("title");
        String subTitle = data.getString("subTitle");
        String expandTitle = data.getString("expandTitle");
        String imageUrl = data.getString("imageUrl");
        String action = data.getString("action");
        String offerAction = data.getString("offerAction");
        String offerImageUrl = data.getString("offerImageUrl");
        long defaultId = Long.parseLong(data.getString("Id"));
        long defaulttitleId = Long.parseLong(data.getString("titleId"));
        long defaultTagId = Long.parseLong(data.getString("tagId"));

        Log.d("Test321", "in MyGcmListenerService Id = " + defaultId + " PtitleId = " +
                defaulttitleId + " TagId = " + defaultTagId);

        int smallIconDrawable;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            smallIconDrawable = R.mipmap.logo;
        } else {
            smallIconDrawable = R.mipmap.logo;
        }
        Intent intent;
        Bundle bundle = new Bundle();

        if(defaultId != 0 && defaulttitleId != 0 ){
            Log.d("Test123","Push to 2page");
            intent = new Intent(this, DetailActivity.class);
            bundle.putLong(KEY_ID,defaultId);
            bundle.putLong(KEY_TITLE_ID, defaulttitleId);
            bundle.putLong(KEY_TAGID, defaultTagId);
            bundle.putLong("pushnotification",1);
            intent.putExtras(bundle);
        } else {
            Log.d("Test123","push to mainactivity");
            intent = new Intent(this, MainActivity.class);
        }
        intent.putExtra("pushnotification",action);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(smallIconDrawable)
                .setLargeIcon(BitmapFactory.decodeResource(getApplication().getResources(),R.mipmap.logo))
                .setContentTitle(title)
                .setContentText(subTitle)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);
        if(bitmap != null){
            notificationBuilder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap));
        }else{
            notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(expandTitle));
        }
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

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

    }

    public static String bundleToString(Bundle bundle) {
        if (bundle == null) {
            return null;
        }
        String string = "Bundle{";
        for (String key : bundle.keySet()) {
            string += " " + key + " => " + bundle.get(key) + ";";
        }
        string += " }Bundle";
        return string;
    }
}

The message is successfully received, notification appears but not exactly what I wanted as the onMessageReceived() is not called. I can get the data I am passing as key-value pairs only when user clicks the default notification sent by GCM in my Activity. I have seen many apps displaying a custom notification. So, there must be some way to implement this kind of notification? Any help is appreciated.


Solution

  • onMessageReceived does not get called because you have the notification tag in your payload.

    If you want to have your own notification you need to remove that and just send data in your payload. When you do that your onMessageReceived will be called and you will then have to create your own notification using the Notification.Builder class.

    If you want something beyond the builder you can create your own notification by reading this