android – NotificationCompat.setStyle() can't get Notification.MediaStyle-ThrowExceptions

Exception or error:

I’ve found out that the MediaStyle setStyle is not working when I’m using
NotificationCompat.builder(this) to make a notification.

I mean, When using this on NotificationCompat.Builder(this):

.setStyle(new Notification.MediaStyle()
         .setMediaSession(mySession))

It saying it wants to get NotificationCompat.style instead of Notification.MediaStyle.

Can you help me solve that problem?
Is there any replacement for the NotificationCompat?

Thanks.

How to solve:

There is no `NotificationCompat.MediaStyle` in v4 package, however, it does exist in v7 package. Make sure to import:

import android.support.v7.app.NotificationCompat;

instead of the v4 package. It’s working for me as of v22.2.0 of the appcompat library.

As of version 26.0.0, the v7 package is deprecated. However, all functionality has been added to v4! Yay! 🎉

Source

###

Temporary Fix: As of 9/11/2017, One can use the fully qualified class as a work-around. Tested using Android 3.0 Beta 5 Preview, with API 26.0.1 build tools

// The notification builder
import android.support.v4.app.NotificationCompat;

// The media style should be of type, has "media in the path
// android.support.v4.media.app.NotificationCompat.MediaStyle;

    Notification noti = new NotificationCompat.Builder(this, "Quiz")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(getString(R.string.app_name))
            .setContentText("Hi this is a media notification")
            .setContentIntent(pendingIntent)
            .setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
                    .setMediaSession(mMediaSession.getSessionToken()))
            .build();

###

Guillermo is correct, the MediaStyle only exists in the v7 support package, but unfortunately it may still prove problematic for you when correcting your package as this may only part of your problem.

First some context…
Each call to configure the NotificationBuilder returns the builder instance, which in turn allows the implementor to chain configuration calls like so:

    // NOTE: To re-iterate, the import you would be using is:
    import android.support.v7.app.NotificationCompat;

    NotificationCompat.Builder myBuilder = new NotificationCompat.Builder(currContext)
    .setSmallIcon(R.drawable.ic_notification_small)
    .setLargeIcon(BitmapFactory.decodeResource(currContext.getResources(), R.drawable.ic_notification_large))
    .setStyle(new NotificationCompat.MediaStyle().setMediaSession(sessionCompat.getSessionToken()));

This is a very normal & convenient pattern, the only problem is that the Builder instance returned is of type android.support.v4.app.NotificationCompat.Builder, & not the android.support.v7.app.NotificationCompat.Builder that you are expecting.

So the fix is deceptively simple… just explicitly keep using your v7 Builder instance when making these calls 🙂

    // NOTE: To re-iterate, the import you would be using is:
    import android.support.v7.app.NotificationCompat;
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(currContext);
    mBuilder.setSmallIcon(R.drawable.ic_notification_small);
    mBuilder.setLargeIcon(BitmapFactory.decodeResource(currContext.getResources(), R.drawable.ic_notification_large));
    mBuilder.setStyle(new NotificationCompat.MediaStyle().setMediaSession(sessionCompat.getSessionToken()));

###

For AndroidX in 2020 you can use following code –

builder.setStyle(new androidx.media.app.NotificationCompat.MediaStyle());

don’t forget to add dependency in build.gradle(Module:app)

implementation "androidx.media:media:1.1.0"

###

Update

This problem is fixed now if you link in Android Support Library revision 22.2.1 (July 2015):

Older workaround

Here’s my workaround for “There is no NotificationCompat.MediaStyle in the support library“.

It avoids duplicating application logic and makes it easy to back out the workaround if/when NotificationCompat supports MediaStyle.

Purpose: This makes it easy to use the MediaStyle in API 21+ (offering compact and expanded notification layouts, with buttons), or an ordinary notification layout on older versions of Android (just one layout, with buttons).

Note: If your goal is to put buttons on the lock screen on multiple versions of Android, you can use this approach to implement lock screen notifications for API 21+, and also implement a lock screen widget for older APIs.

How to: First, create a new notification builder compatibility package, starting with an interface to alternate underlying implementations. Crib from NotificationCompat.Builder, stripped down to the needed features:

public interface NotificationBuilder {
    public NotificationBuilder setWhen(long when);
    public NotificationBuilder setUsesChronometer(boolean b);
    public NotificationBuilder setSmallIcon(int icon);
    // ...

    /** Sets MediaStyle with setShowActionsInCompactView(). */
    public NotificationBuilder setMediaStyleActionsInCompactView(int... actions);

    public Notification build();
}

Second, make an implementation built on NotificationCompat.Builder:

public class V20Builder implements NotificationBuilder {
    private NotificationCompat.Builder builder;

    public V20Builder(Context context) {
        builder = new NotificationCompat.Builder(context);
    }

    @Override
    public NotificationBuilder setWhen(long when) {
        builder.setWhen(when);
        return this;
    }

    @Override
    public NotificationBuilder setUsesChronometer(boolean b) {
        builder.setUsesChronometer(b);
        return this;
    }

    @Override
    public NotificationBuilder setSmallIcon(int icon) {
        builder.setSmallIcon(icon);
        return this;
    }

    // ...

    @Override
    public NotificationBuilder setMediaStyleActionsInCompactView(int... actions) {
        // Noop for Android API V20-.
        return this;
    }

    @Override
    public Notification build() {
        return builder.build();
    }
}

Third, make an implementation built on Notification.Builder:

@TargetApi(21)
public class V21Builder implements NotificationBuilder {
    private Notification.Builder builder;

    public V21Builder(Context context) {
        builder = new Notification.Builder(context);
    }

    @Override
    public NotificationBuilder setWhen(long when) {
        builder.setWhen(when);
        return this;
    }

    @Override
    public NotificationBuilder setUsesChronometer(boolean b) {
        builder.setUsesChronometer(b);
        return this;
    }

    @Override
    public NotificationBuilder setSmallIcon(int icon) {
        builder.setSmallIcon(icon);
        return this;
    }

    // ...

    @Override
    public NotificationBuilder setMediaStyleActionsInCompactView(int... actions) {
        new Notification.MediaStyle(builder).setShowActionsInCompactView(actions);
        return this;
    }

    @Override
    public Notification build() {
        return builder.build();
    }
}

Fourth, add a factory method to instantiate the right builder:

public NotificationBuilder makeBuilder() {
  if (Build.VERSION.SDK_INT >= 21) { // Load the API V21 class only if the OS can load it.
      return new V21Builder(context);
  }
  return new V20Builder(context);
}

###

There does not appear to be a backport of MediaStyle in the Android Support package at this time.

Eventually, once the Android 5.0 source code becomes available, somebody may be able to craft an independent backport. Or, perhaps the Android Support package will add a backport in the future.

But, at the present time, AFAICT, you cannot create a MediaStyle for use with NotificationCompat.

###

For Androidx add the following code

  • In build.gradle(Module:app) add this dependency
  implementation "androidx.media:media:1.1.0"
  • wherever you are using Notification.MediaStyle() in setStyle method,use the following code
  builder.setStyle(new androidx.media.app.NotificationCompat.MediaStyle());

Leave a Reply

Your email address will not be published. Required fields are marked *