Android - use external profile image in notification bar like Facebook
Asked Answered
L

5

21

I know you can send info in the push notification parameters like message, title, image URL, etc. How does Facebook show your profile pic with your message in the notification area? I want to use an external image in the notification area, so when you pull it down you see the profile image with the message. Right now, mine just shows the default icon from the drawable folder. I figured this might be a common question but couldn't find anything. Any help would be nice.

Lunarian answered 15/4, 2013 at 3:50 Comment(0)
M
36

This statement will use a method to convert a URL (naturally, one that points to an image) into a Bitmap.

Bitmap bitmap = getBitmapFromURL("https://graph.facebook.com/YOUR_USER_ID/picture?type=large");

Note: Since you mention a Facebook profile, I have included an URL that gets your the large size profile picture of a Facebook User. You can however, change this to any URL that points to an image that you need to display in the Notification.

And the method that will get the image from the URL you specified in the statement above:

public Bitmap getBitmapFromURL(String strURL) {
    try {
        URL url = new URL(strURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

Now pass the bitmap instance created above to the Notification.Builder instance. I call it builder in this example code. It is used in this line: builder.setLargeIcon(bitmap);. I am assuming you know how to display the actual Notification and it's configurations. So I will skip that part and add just the builder.

// CONSTRUCT THE NOTIFICATION DETAILS
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("Some Title");
builder.setContentText("Some Content Text");
builder.setLargeIcon(bitmap);
builder.setContentIntent(pendingIntent);

Oh, almost forgot, if you haven't already done so, you will need this permission setup in the Manifest:

<uses-permission android:name="android.permission.INTERNET" />
Mesial answered 15/4, 2013 at 4:30 Comment(9)
This is plain and simple and meets what I needed and it works.Lunarian
@Pjack: I am glad to have been of help. :-)Mesial
any idea how to load the image in ImageView inside a RemoteViews ?Isotope
@MahmoudBadri: I am mobile ATM and don't have access to my code base (I am vacationing. :-) ). But I found this in my Chrome bookmarks. See if this is helpful. I will post an update or, if you post a question, and answer in a couple of days. android.codota.com/scenarios/518915e1da0a0401949d16f2/…Mesial
Note that this code is synchronous and will delay the notification in case of disconnect. It's best to set short connect and read timeouts in the connection.Merth
This code leads some day seriously to an OutOfMemoryError. Depends on the currently used heap space of the app itself and how big the image is. You need a scaling algorithm instead. Also this Bitmap.decode() shouldn't be executed on the UI thread. Think about good software quality.Pulsate
@drindt: Of course there is potential for OOMs as well as, in it's current form, NetworkOnThread error. But this answer is merely a pointer on what is needed to display a Bitmap in the NotificationBar. Not it's optimization. Combining this answer with others on SO that specifically deal with the OOM and NoT issues is really not the purpose nor my intention. Moving the contents of the try..catch block in an AsyncTask is a fairly ease thing to do eh?Mesial
If you use picasso. Bitmap bitmap = Picasso.with(app.context).load(sender.getPicture()).placeholder(R.mipmap.dummy_user).get();Consistency
@user303730: That is now an option. Yes. However, if I recall correctly, Picasso wasn't released when this answer was posted.Mesial
S
19

enter image description here

download image first using below code:

private Bitmap getBitmap(String url)
    {
        File f=fileCache.getFile(url);

        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;

        //from web
        try {
            Bitmap bitmap=null;
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is=conn.getInputStream();
            OutputStream os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex){
           ex.printStackTrace();
           return null;
        }
    }

    //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=70;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }

use that image as bitmap in below code:

Bitmap icon1 = downloadedBitmap;

            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                    this).setAutoCancel(true)
                    .setContentTitle("DJ-Android notification")
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentText("Hello World!");

            NotificationCompat.BigPictureStyle bigPicStyle = new NotificationCompat.BigPictureStyle();
            bigPicStyle.bigPicture(icon1);
            bigPicStyle.setBigContentTitle("Dhaval Sodha Parmar");
            mBuilder.setStyle(bigPicStyle);

            // Creates an explicit intent for an Activity in your app
            Intent resultIntent = new Intent(this, testActivity.class);

            // The stack builder object will contain an artificial back stack
            // for
            // the
            // started Activity.
            // This ensures that navigating backward from the Activity leads out
            // of
            // your application to the Home screen.
            TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

            // Adds the back stack for the Intent (but not the Intent itself)
            stackBuilder.addParentStack(testActivity.class);

            // Adds the Intent that starts the Activity to the top of the stack
            stackBuilder.addNextIntent(resultIntent);
            PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
                    0, PendingIntent.FLAG_UPDATE_CURRENT);
            mBuilder.setContentIntent(resultPendingIntent);

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

            // mId allows you to update the notification later on.
            mNotificationManager.notify(100, mBuilder.build());

i thing you k'no about android permission:

<uses-permission android:name="android.permission.INTERNET" />

for more detail check this artical and android developer

Sym answered 15/4, 2013 at 5:38 Comment(5)
Very nice, I like the links to the articles. Question, does this make the entire screen the photo or just the notification bar have the photo? I currently only want it to show in the notification are only that has the title with it.Lunarian
Ahh. nevermind.. I see where you set it in the builder parmaters. Nice. thanks for this and I will try your other layouts as well.Lunarian
Question, when I added the code I'm getting two errors. Utils cannot be resolved and fileCache cannot be resolved. How do i fix those?Lunarian
@Pjack: download code from here androidhive.info/2012/07/android-loading-image-from-url-httpSym
Thanks for the answer. However I think it's a bit complicated for a simple avatar. The link requires several classes and the use is for display general images. I would need time to dissect it and use the parts I need. I might revisit caching the photo at another time.Lunarian
H
0

I used Universal Image Loader to solve this. Take a look at the wiki on how to set it up. After you instantiate it once, this is the code I use in my GCM listener to download and display the image. I download the bitmap and then set it in the notification:

// Download profile picture of the user with Universal Image Loader
Bitmap bitmap =  ImageLoader.getInstance().loadImageSync(profilePhotoUrl);

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(R.drawable.ic_my_app)
        .setLargeIcon(bitmap) // This is the image displayed on the lock screen
        .setContentTitle("My App")
        .setContentText(message)
        .setAutoCancel(true)
        .setSound(defaultSoundUri)
        .setContentIntent(pendingIntent);
Highoctane answered 11/3, 2016 at 1:40 Comment(0)
F
0

Since image is loaded from internet, it should be done async in a background thread.You can use (1) async task or (2) 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.

Step 1: Load bitmap from image url on background thread

   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: Load image notification from here
                            displayImageNotification(bitmap[0]);
                        }

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

Step 2: 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());
}
Fact answered 8/11, 2019 at 6:57 Comment(0)
M
-3
Notification notif = new Notification.Builder(context)
     .setContentTitle("Title")
     .setContentText("content")
     .setSmallIcon(R.drawable.ic_small)
     .setLargeIcon(bitmap)
     .setStyle(new Notification.BigPictureStyle()
         .bigPicture(bigBitmap)
         .setBigContentTitle("big title"))
     .build();
Moslemism answered 3/2, 2015 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.