Load image from url in notification Android

80,225

Solution 1

Changed my code as below and its working now :

private class sendNotification extends AsyncTask<String, Void, Bitmap> {

        Context ctx;
        String message;

        public sendNotification(Context context) {
            super();
            this.ctx = context;
        }

        @Override
        protected Bitmap doInBackground(String... params) {

            InputStream in;
            message = params[0] + params[1];
            try {

                  URL url = new URL(params[2]);
                  HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                  connection.setDoInput(true);
                  connection.connect();
                  in = connection.getInputStream();
                  Bitmap myBitmap = BitmapFactory.decodeStream(in);
                  return myBitmap;
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap result) {

            super.onPostExecute(result);
            try {
                NotificationManager notificationManager = (NotificationManager) ctx
                        .getSystemService(Context.NOTIFICATION_SERVICE);

                Intent intent = new Intent(ctx, NotificationsActivity.class);
                intent.putExtra("isFromBadge", false);


                Notification notification = new Notification.Builder(ctx)
                        .setContentTitle(
                                ctx.getResources().getString(R.string.app_name))
                        .setContentText(message)
                        .setSmallIcon(R.drawable.ic_launcher)
                        .setLargeIcon(result).build();

                // hide the notification after its selected
                notification.flags |= Notification.FLAG_AUTO_CANCEL;

                notificationManager.notify(1, notification);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

Solution 2

How to implement BigPicture style Notification:

Miracle has been done by .setStyle(new Notification.BigPictureStyle().bigPicture(result)) :

I have done this way with:

enter image description here

Generate notification by AsyncTask:

new generatePictureStyleNotification(this,"Title", "Message", 
                 "http://api.androidhive.info/images/sample.jpg").execute();

AsyncTask:

public class generatePictureStyleNotification extends AsyncTask<String, Void, Bitmap> {

        private Context mContext;
        private String title, message, imageUrl;

        public generatePictureStyleNotification(Context context, String title, String message, String imageUrl) {
            super();
            this.mContext = context;
            this.title = title;
            this.message = message;
            this.imageUrl = imageUrl;
        }

        @Override
        protected Bitmap doInBackground(String... params) {

            InputStream in;
            try {
                URL url = new URL(this.imageUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setDoInput(true);
                connection.connect();
                in = connection.getInputStream();
                Bitmap myBitmap = BitmapFactory.decodeStream(in);
                return myBitmap;
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);

            Intent intent = new Intent(mContext, MyOpenableActivity.class);
            intent.putExtra("key", "value");
            PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 100, intent, PendingIntent.FLAG_ONE_SHOT);

            NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
            Notification notif = new Notification.Builder(mContext)
                    .setContentIntent(pendingIntent)
                    .setContentTitle(title)
                    .setContentText(message)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(result)
                    .setStyle(new Notification.BigPictureStyle().bigPicture(result))
                    .build();
            notif.flags |= Notification.FLAG_AUTO_CANCEL;
            notificationManager.notify(1, notif);
        }
    }

Solution 3

you can do this using Glide like this:

val notificationBuilder = NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.drawable.ic_message)
        .setContentTitle("title")
        .setContentText("text")

val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

val futureTarget = Glide.with(this)
        .asBitmap()
        .load(photoUrl)
        .submit()

val bitmap = futureTarget.get()
notificationBuilder.setLargeIcon(bitmap)

Glide.with(this).clear(futureTarget)

notificationManager.notify(0, notificationBuilder.build())

preview

Solution 4

Top answer in Kotlin and with Coroutines. This method applies the bitmap to the builder instead of a direct assignment, and of course if bitmap available. It's nice because if the url is wrong it will be caught in the try/catch.

fun applyImageUrl(
    builder: NotificationCompat.Builder, 
    imageUrl: String
) = runBlocking {
    val url = URL(imageUrl)

    withContext(Dispatchers.IO) {
        try {
            val input = url.openStream()
            BitmapFactory.decodeStream(input)
        } catch (e: IOException) {
            null
        }
    }?.let { bitmap ->
        builder.setLargeIcon(bitmap)
    }
}

with Kotlin & RxJava

fun applyImageUrl(
    builder: NotificationCompat.Builder,
    imageUrl: String
) {
    val url = URL(imageUrl)

    Single.create<Bitmap> { emitter ->
        try {
            val input = url.openStream()
            val bitmap = BitmapFactory.decodeStream(input)
            emitter.onSuccess(bitmap)
        } catch (e: Exception) {
            emitter.onError(e)
        }
    }.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            {
                builder.setLargeIcon(it)
            }, {
                Timber.e("error generating bitmap for notification")
            }
        )
}

Solution 5

Since image is loaded from internet, it should be done async in a background thread. Either use async task or Glide (for efficient image loading).

To load image notification, you need to use "NotificationCompat.BigPictureStyle()". This requires a bitmap (which has to be extracted from image url)

Most of the API's and methods of Glide are now deprecated. Below is working with Glide 4.9 and upto Android 10.

 // Load bitmap from image url on background thread and display image notification
        private void getBitmapAsyncAndDoWork(String imageUrl) {

            final Bitmap[] bitmap = {null};

            Glide.with(getApplicationContext())
                    .asBitmap()
                    .load(imageUrl)
                    .into(new CustomTarget<Bitmap>() {
                        @Override
                        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {

                            bitmap[0] = resource;
                            // TODO Do some work: pass this bitmap
                            displayImageNotification(bitmap[0]);
                        }

                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        }
                    });
        }

Display the image notification once, the bitmap is ready.

private void displayImageNotification(Bitmap bitmap) {

      NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), getChannelId());
            builder
                    .setContentTitle(title)
                    .setContentText(subtext)
                    .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE)
                    .setSmallIcon(SMALL_ICON)
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                    .setColor(getApplicationContext().getColor(color))
                    .setAutoCancel(true)
                    .setOngoing(false)
                    .setOnlyAlertOnce(true)
                    .setContentIntent(pendingIntent)
                     .setStyle(
                     new NotificationCompat.BigPictureStyle().bigPicture(bitmap))
                    .setPriority(Notification.PRIORITY_HIGH);

        getManager().notify(tag, id, builder.build());
}
Share:
80,225
Zankhna
Author by

Zankhna

Enthusiastic Software Engineer interested in developing Mobile and Web application that can transform Visualization to the Reality.

Updated on July 05, 2022

Comments

  • Zankhna
    Zankhna almost 2 years

    In my android application, i want to set Notification icons dynamically which will be loaded from URL. For that, i have used setLargeIcon property of NotificationBuilder in receiver.I reffered many link and tried various solutions but couldn't get desired output. Though i downloaded that image from url and setting that bitmap in notification, it is not being displayed. Instead it displays the setSmallIcon image as large icon. I don't know where i am going wrong. Here i am posting my code. Please help me to solve this issue. Thank you.

    Code:

    @SuppressLint("NewApi")
    public class C2DMMessageReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if ("com.google.android.c2dm.intent.RECEIVE".equals(action)) {
                Log.e("C2DM", "received message");
                final String fullName = intent.getStringExtra("message");
                final String payload1 = intent.getStringExtra("message1");
                final String payload2 = intent.getStringExtra("message2");
                final String userImage = intent.getStringExtra("userImage");
    
                Log.e("userImage Url :", userImage); //it shows correct url
    
                new sendNotification(context)
                        .execute(fullName, payload1, userImage);
            }
        }
    
    private class sendNotification extends AsyncTask<String, Void, Bitmap> {
    
            Context ctx;
            String message;
    
            public sendNotification(Context context) {
                super();
                this.ctx = context;
            }
    
            @Override
            protected Bitmap doInBackground(String... params) {
    
                InputStream in;
                message = params[0] + params[1];
                try {
    
                    in = new URL(params[2]).openStream();
                    Bitmap bmp = BitmapFactory.decodeStream(in);
                    return bmp;
    
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(Bitmap result) {
    
                super.onPostExecute(result);
                try {
                    NotificationManager notificationManager = (NotificationManager) ctx
                            .getSystemService(Context.NOTIFICATION_SERVICE);
    
                    Intent intent = new Intent(ctx, NotificationsActivity.class);
                    intent.putExtra("isFromBadge", false);
    
    
                    Notification notification = new Notification.Builder(ctx)
                            .setContentTitle(
                                    ctx.getResources().getString(R.string.app_name))
                            .setContentText(message)
                            .setSmallIcon(R.drawable.ic_launcher)
                            .setLargeIcon(result).build();
    
                    // hide the notification after its selected
                    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    
                    notificationManager.notify(1, notification);
    
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
  • Paresh Mayani
    Paresh Mayani over 8 years
    Put some details along with code! It would help someone to understand the APIs, functionality and the implantation exactly!
  • Erum
    Erum over 7 years
    how to handle image size ??
  • Arpit Patel
    Arpit Patel over 7 years
    i am not able to call this method in FirebaseMessagingService How can i implement it.
  • AxA
    AxA over 7 years
    @ArpitPatel May be the service is ending prior to retrieving image asynchronously. Did you try getting the image synchronously? Like here: androidbash.com/firebase-push-notification-android
  • Arpit Patel
    Arpit Patel over 7 years
    ya i already solve using this tutorial. It is well explained. thanks by the for guidance @rpattabi
  • Prashant Gosai
    Prashant Gosai over 7 years
    @rpattabi androidbash.com/firebase-push-notification-android I try this tutorial, but there is some restrictions Like Notification with image an fetched from the url is displayed to the user (with BigImage). But if the app is background or killed state, then onMessageReceived () method will not be called. Hence a simple notification containing just a message will be displayed in the notification bar on your Android device.
  • Narendra Singh
    Narendra Singh about 7 years
    Its working, but it takes a few seconds to display the notification, it doesn't display immediately. Is there some way that, notification generate immediately. Is there any way to display notification immediately, and load image from url meanwhile?
  • Tejas Pandya
    Tejas Pandya almost 6 years
    @PrashantGosai is there any way to show image in background state also ?
  • EdgeDev
    EdgeDev over 5 years
    Why did you have the notification code in Async Task?
  • Hiren Patel
    Hiren Patel over 5 years
    @Micklo_Nerd, We are loading image in background thread that's why we've used Async Task. You probably can use Rx java instead to eliminate the code.
  • EdgeDev
    EdgeDev over 5 years
    Okay, i get it now. Thanks
  • ismail alaoui
    ismail alaoui over 5 years
    you should call input stream in = new Url .....() in a asynctask , never perform network request in the main thread
  • Juan Mendez
    Juan Mendez almost 5 years
    see my answer in 2019 implementing this answer using Coroutines and Kotlin :)
  • faizanjehangir
    faizanjehangir about 4 years
    Very solid answer! Works as is in Kotlin!
  • Juan Mendez
    Juan Mendez about 4 years
    I have applied this code in two apps and has worked great. Thanks for sharing your experience.
  • skygeek
    skygeek almost 4 years
    This is more lucrative.
  • Juan Mendez
    Juan Mendez over 3 years
    I edited the answer by appending RxJava solution as well.
  • Rumit Patel
    Rumit Patel about 2 years
    Is there any special purpose to using setPriority twice?