28

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.

user3184899
  • 3,019
  • 6
  • 30
  • 38
  • 1
    Please use "android.support.v4.media.app.NotificationCompat.MediaStyle" instead. More details are on the good article: https://medium.com/google-developers/migrating-mediastyle-notifications-to-support-android-o-29c7edeca9b7 – Maxim Firsoff Oct 27 '17 at 11:56
  • try this if you are using `AndroidX` https://stackoverflow.com/a/60060610/9699634 – VikaS GuttE Feb 04 '20 at 15:29

8 Answers8

29

For AndroidX in 2020 you can use following code -

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

don't forget to add the androidx.media dependency in build.gradle(Module:app)

implementation "androidx.media:media:1.2.0"
Breair Sabir
  • 54
  • 1
  • 15
VikaS GuttE
  • 1,636
  • 2
  • 14
  • 38
21
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

19

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();
Andrew Lam
  • 1,371
  • 17
  • 35
  • I am building an Android app with minimum requirements of Lollipop 5.1.1 API 22, and this works! – Player1 Mar 26 '18 at 11:03
10

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()));
Marc
  • 101
  • 1
  • 5
7

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);
}
Jerry101
  • 12,157
  • 5
  • 44
  • 63
  • Does this 'fix' allow the media buttons on the locked screen with EITHER version? – Kevin Jan 17 '15 at 07:06
  • @kevin Android < 21 has no notifications at all on the lock screen, nor a MediaStyle for the notification area. So on Android < 21 this `setMediaStyleActionsInCompactView()` method does nothing, gracefully, while it does add the compact media style buttons on Android 21. Calls to `builder.addAction()` will still add buttons to the notification in all Android versions that support it. – Jerry101 Jan 17 '15 at 07:27
  • Gotcha. But...I know it's possible to get media buttons on – Kevin Jan 18 '15 at 07:56
  • @kevin it depends on just what you're asking for. Before API 21 you can still call `addAction()` to add up to 3 action buttons, and you can download Android Design Icons to get button images for pause, play, stop, etc. API 21 introduces `MediaStyle` which supports up to 5 buttons in the large view; 3 in the compact view. It's also possible to define a custom layout. If you're comparing with Cyanogen's built-in music player Apollo, does Cyanogen offer custom APIs for that? – Jerry101 Jan 18 '15 at 08:14
  • Ah, I didn't realize apollo was from a custom ROM... Forgot I did that to my wife's phone years ago :) so there is no way to get buttons/actions – Kevin Jan 20 '15 at 04:37
  • @Kevin in stock Android, an app _can_ put buttons on the lock screen but it requires two completely different implementations: notifications for API 21+; lock screen widgets for older APIs. (The previous comment was specific to notifications, whether they're on the lock screen or not.) – Jerry101 Jan 20 '15 at 04:49
  • I like this. This is how the appcompat library works as well. +1 – frostymarvelous Apr 01 '15 at 05:50
  • 1
    This is the full source if anyone is looking https://github.com/1fish2/BBQTimer/tree/master/BBQ%20Timer/src/main/java/com/onefishtwo/bbqtimer/notificationCompat – frostymarvelous Apr 01 '15 at 06:01
3

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.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • So, do you have any replacement? Something you put inside an "if" and it will make a media style notfication if its Android 5.0? – user3184899 Oct 19 '14 at 17:44
  • @user3184899: You would have to switch to using `Notification.Builder`, not `NotificationCompat.Builder`, if `Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP`. – CommonsWare Oct 19 '14 at 17:46
  • See https://code.google.com/p/android-developer-preview/issues/detail?id=1659&thanks=1659&ts=1413837975 – Jerry101 Oct 20 '14 at 20:47
3

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());
sai Pavan Kumar
  • 1,129
  • 12
  • 20
0
implementation 'androidx.media:media:1.6.0'

When you create a notification then use always androidX related imports for NotificationCompat 


 1. import androidx.media.app.NotificationCompat
 val mediaStyle = NotificationCompat.MediaStyle().setMediaSession(token)

 2. import android.support.v4.media.session.MediaSessionCompat
 val mediaSession = MediaSessionCompat(requireContext(), "session tag")


  val mediaSession = MediaSessionCompat(requireContext(), "session tag")
  val token = mediaSession.sessionToken
  val mediaStyle = NotificationCompat.MediaStyle().setMediaSession(token)
Dishant Kawatra
  • 638
  • 7
  • 5