13

I am having this problem where I generate a Bitmap from a URL that I use in my notification. However, on my phone, the Bitmap shows up like a small white square. I looked into it and found many posts like so talking about it: Icon not displaying in notification: white square shown instead

and I know for sure my Small Icon for the notification indeed is transparent. However, for the Large Icon, I realize that the Large Icon cannot be transparent because it is actually a Bitmap that I generate from a URL. How can I get around this then and make sure that the image renders properly instead of having the Large Icon show up as a white square? Here is my attempt:

NotificationService.java:

    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
            .setContentTitle(getString(R.string.app_name))
            .setContentText(remoteMessage.getNotification().getBody())
            .setTicker(remoteMessage.getFrom() + " has responded!")
            .setLargeIcon(AndroidUtils.getBitmapFromURL(remoteMessage.getNotification().getIcon()))
            .setAutoCancel(true)
            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
            .setStyle(new NotificationCompat.BigTextStyle().bigText(remoteMessage.getNotification().getBody()))
            .setSmallIcon(R.drawable.ic_tabs_notification_transparent);

AndroidUtils.java:

public static Bitmap getBitmapFromURL(String userId) {
        try {
            URL imgUrl = new URL("https://graph.facebook.com/" + userId + "/picture?type=large");
            InputStream in = (InputStream) imgUrl.getContent();
            Bitmap  bitmap = BitmapFactory.decodeStream(in);
            Bitmap output;
            Rect srcRect;
            if (bitmap.getWidth() > bitmap.getHeight()) {
                output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
                srcRect = new Rect((bitmap.getWidth()-bitmap.getHeight())/2, 0, bitmap.getWidth()+(bitmap.getWidth()-bitmap.getHeight())/2, bitmap.getHeight());
            } else {
                output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Bitmap.Config.ARGB_8888);
                srcRect = new Rect(0, (bitmap.getHeight()-bitmap.getWidth())/2, bitmap.getWidth(), bitmap.getHeight()+(bitmap.getHeight()-bitmap.getWidth())/2);
            }

            Canvas canvas = new Canvas(output);

            final int color = 0xff424242;
            final Paint paint = new Paint();
            final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());

            float r;

            if (bitmap.getWidth() > bitmap.getHeight()) {
                r = bitmap.getHeight() / 2;
            } else {
                r = bitmap.getWidth() / 2;
            }

            paint.setAntiAlias(true);
            canvas.drawARGB(0, 0, 0, 0);
            paint.setColor(color);
            canvas.drawCircle(r, r, r, paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(bitmap, srcRect, rect, paint);
            return output;
        } catch (IOException e) {
            FirebaseCrash.report(e);
            return null;
        }

Image showing my problem:

enter image description here

EDIT: Build.gradle file showing:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    defaultConfig {
        applicationId '<ID>'
        multiDexEnabled true
        minSdkVersion 21
        targetSdkVersion 23
        versionCode 12
        versionName ".12"
        signingConfig signingConfigs.Tabs
    }
    buildTypes {
        release {
            minifyEnabled false
            shrinkResources false
            zipAlignEnabled true
            debuggable false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.Tabs
        }
        debug {
            applicationIdSuffix ".debug"
            debuggable true
            minifyEnabled false
            signingConfig signingConfigs.Tabs
        }
    }
    //DatabaseReference stuff
    packagingOptions {
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE-FIREBASE.txt'
        exclude 'META-INF/NOTICE'
    }
    dexOptions {
        javaMaxHeapSize "4g"
    }
    productFlavors {
    }
}
Community
  • 1
  • 1
user1871869
  • 3,079
  • 10
  • 46
  • 95

8 Answers8

3
try {
            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
            mBuilder.setSmallIcon(getNotificationIcon());
            Bitmap icon = BitmapFactory.decodeResource(CXGcmListenerService.this.getResources(), R.drawable.ic_launcher);
            mBuilder.setLargeIcon(icon);
            //Define sound URI
            Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            mBuilder.setContentIntent(pendingIntent);
            mBuilder.setContentText(msg);
            mBuilder.setStyle(new NotificationCompat.BigTextStyle()
                    .bigText(msg));
            mBuilder.setContentTitle(getString(R.string.app_name));
            mBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
            mBuilder.setAutoCancel(true);
            mBuilder.setSound(soundUri); //This sets the sound to play
            Intent intent = new Intent(CXGcmListenerService.this, CXMainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            PendingIntent notificationIntent = PendingIntent.getActivity(this, 0, intent, 0);
            mBuilder.setContentIntent(notificationIntent);

            NotificationManager notifyManager = (NotificationManager) CXGcmListenerService.this.getSystemService(Context.NOTIFICATION_SERVICE);
            NOTIFICATION_ID++;
            notifyManager.notify("" + System.currentTimeMillis(), NOTIFICATION_ID, mBuilder.build());
        } catch (Resources.NotFoundException e) {
            CXLog.e(TAG, "" + e.getLocalizedMessage(), e);
        }

Please try this to get the icon in the notification.

Jayamurugan
  • 542
  • 2
  • 9
2

You can use different icon for different version:

int bigIcon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.logo_who_is_not_white: R.drawable.logo_who_is_in_whit_tint;
1

I think you have been downloading the image from an URL right?. So, please place an Asynctask to download the image from the url and then use the notification builder to show the notification as like this SO post: https://stackoverflow.com/a/24866080/6452886

Community
  • 1
  • 1
Madhan
  • 485
  • 4
  • 18
1

Lilipop have this problem exists, You just look at other phone prior to Lolipop that have no problem.

please refer these following links

https://material.google.com/style/icons.html

https://developer.android.com/about/versions/android-5.0-changes.html

otherwise you can change the compiled SDK

Jijo
  • 482
  • 7
  • 12
1

There is a change in the notification for Lollipop and later on android API levels. To override this problem you can follow these ways:

Way1: Either change you targetSdkVersion from 23 to 19 in build.gradle of your app module. This will solve the problem for that.

Note: Maybe this solution will create issue in your build system(I prefer you should not go with this way, but you can check your issue with this way)

Way2: Change your notification icon with a black and white icon. Because notification builder doesn't support color icons from lollipop API level.

Way to get black and white icon in Android Studio:

  1. Right-Click Drawable folder > Add image asset (any resource folder should do) enter image description here

  2. Click on Notification Icon from the top drop-down list (default is Launcher Icon) enter image description here

  3. Select Image > Browse to image> click okenter image description here

this is normal since the Lollipop SDK (API 21 - Ver 5.0.1) only allows this type of color scheme

Or you can generate from here: http://romannurik.github.io/AndroidAssetStudio/icons-notification.html

Ready Android
  • 3,070
  • 1
  • 20
  • 34
1

I think the problem is with image size, Status bar icons size follows as below -

ldpi - 18 x 18 px
mdpi - 24 x 24 px
hdpi - 36 x 36 px
xhdpi - 48 x 48 px

you can also take a look at this developer doc

you need to change dimension of received bitmap to above mentioned sizes and it should work.

kevz
  • 2,632
  • 12
  • 38
1

Well its because google has changed notification style in API 21+, and recommend to use white notification icon

Though you can use silhouette icon on 21+ and older icon on all other devices, Something like below

private int getNotificationIcon() {
    boolean icon = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP);
    return icon ? R.drawable.silhouette : R.drawable.ic_launcher;
}

and here is the actual notification builder code:

Notification builder = new Notification.Builder(context)
        .setSmallIcon(getNotificationIcon())
        .build();
Max
  • 12,408
  • 4
  • 48
  • 62
  • I do have my image of my small icon set to transparent, but I don't see why my `Large Icon` isn't appearing correctly. Does the Large Icon need be transparent also? In that case, when I draw my bitmap, does it also need to be transparent? – user1871869 Oct 24 '16 at 08:16
1

Per the setColor() documentation

Parameters

argb -The accent color to use

You are passing in 2, which is not a valid ARGB color, hence why the background color of your small icon does not appear correctly. Instead, choose a valid ARGB color.

If you have a color resource you'd like to use, you can use code such as

.setColor(context.getResources().getColor(R.color.notification_color))

In addition, note the Android 5.0 changes state:

Update or remove assets that involve color. The system ignores all non-alpha channels in action icons and in the main notification icon. You should assume that these icons will be alpha-only. The system draws notification icons in white and action icons in dark gray.

Your small icon should be entirely white and transparent - you can use tools such as the Notification Icon Generator to generate an appropriate icon.

or you can try this :

int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.your_logo_for_Kitkat : R.mipmap.your_logo_for_Lolipop_and_uper_version;
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(icon)
            .setContentTitle(remoteMessage.getData().get("title"))
            .setContentText(remoteMessage.getData().get("shortDescription"))
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setColor(Color.RED)
            .setStyle(notiStyle)
            .setContentIntent(pendingIntent);

For Url image Load:

 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();
            }
        }
    }
Jamil Hasnine Tamim
  • 3,459
  • 20
  • 39
  • Is the `setColor` supposed to be for the bitmap and not for the `smallIcon`? I am having trouble rendering the Bitmap correctly. – user1871869 Oct 24 '16 at 08:15
  • what kinds of problem you face? and what kinds of error show? – Jamil Hasnine Tamim Oct 24 '16 at 10:13
  • The problem is no error shows when I send my notification to my friends phone. It just is that when I try to use a bit map to show a photo, it just comes out as a white square and I'm really not sure why. – user1871869 Oct 24 '16 at 16:25
  • I see what you are trying to do, but what if I don't have my drawable icon as a resource? What if the image comes from a URL like I posted above? – user1871869 Oct 25 '16 at 05:15
  • @user1871869 now see my updated answer its loading from URL! Hope it will be working for you..thanks :) – Jamil Hasnine Tamim Oct 25 '16 at 06:12