androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.61k stars 380 forks source link

Custom uri icon for CommandButton #1783

Open patryk84a opened 2 days ago

patryk84a commented 2 days ago

I have noticed some inconsistencies in CommandButton.Builder. It has a setIconUri(uri) method which doesn't seem to work on my Android 14. Also, Builder() will be deprecated, so we will be forced to set one of the standard icons. I tried something like this:

new CommandButton.Builder()
.setIconUri(Icons.getIconUri(Icons.ICON_CLOSE, context))
.setDisplayName("Close service")
.setSessionCommand(new SessionCommand(CUSTOM_COMMAND_STOP_SERVICE, Bundle.EMPTY))
.build());

But this causes an error in onConnect:

return new MediaSession.ConnectionResult.AcceptedResultBuilder(session)
.setAvailableSessionCommands(mediaNotificationSessionCommands) 
.setCustomLayout(ImmutableList.copyOf(customLayout))
.build();

And the service does not start. How to set a custom icon from Uri?

tonihei commented 2 days ago

But this causes an error in onConnect

Could you tell us more about the error so that we can point you in the right direction?

we will be forced to set one of the standard icons

I'm curious if there is an icon missing from the list you would have liked to use?

patryk84a commented 2 days ago

Thank you for your quick response.

Could you tell us more about the error so that we can point you in the right direction?

Failed to add a session to session service (Ask Gemini)
                                                                                                      java.lang.IllegalArgumentException: You must specify an icon resource id to build a CustomAction
                                                                                                          at androidx.media3.session.legacy.PlaybackStateCompat$CustomAction$Builder.<init>(PlaybackStateCompat.java:1104)
                                                                                                          at androidx.media3.session.PlayerWrapper.createPlaybackStateCompat(PlayerWrapper.java:1102)
                                                                                                          at androidx.media3.session.MediaSessionLegacyStub.lambda$updateLegacySessionPlaybackState$23$androidx-media3-session-MediaSessionLegacyStub(MediaSessionLegacyStub.java:814)
                                                                                                          at androidx.media3.session.MediaSessionLegacyStub$$ExternalSyntheticLambda20.run(D8$$SyntheticClass:0)
                                                                                                          at androidx.media3.common.util.Util.postOrRun(Util.java:794)
                                                                                                          at androidx.media3.session.MediaSessionLegacyStub.updateLegacySessionPlaybackState(MediaSessionLegacyStub.java:812)
                                                                                                          at androidx.media3.session.MediaSessionImpl.setAvailableFrameworkControllerCommands(MediaSessionImpl.java:998)
                                                                                                          at androidx.media3.session.MediaSessionImpl.onConnectOnHandler(MediaSessionImpl.java:682)
                                                                                                          at androidx.media3.session.MediaSessionStub.lambda$connect$17$androidx-media3-session-MediaSessionStub(MediaSessionStub.java:485)
                                                                                                          at androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda44.run(D8$$SyntheticClass:0)
                                                                                                          at androidx.media3.common.util.Util.postOrRun(Util.java:794)
                                                                                                          at androidx.media3.session.MediaSessionStub.connect(MediaSessionStub.java:472)
                                                                                                          at androidx.media3.session.MediaSessionStub.connect(MediaSessionStub.java:636)
                                                                                                          at androidx.media3.session.MediaControllerImplBase.requestConnectToSession(MediaControllerImplBase.java:2530)
                                                                                                          at androidx.media3.session.MediaControllerImplBase.connect(MediaControllerImplBase.java:203)
                                                                                                          at androidx.media3.session.MediaController.<init>(MediaController.java:530)
                                                                                                          at androidx.media3.session.MediaController$Builder.buildAsync(MediaController.java:338)
                                                                                                          at androidx.media3.session.MediaNotificationManager.addSession(MediaNotificationManager.java:99)
                                                                                                          at androidx.media3.session.MediaSessionService.lambda$addSession$0$androidx-media3-session-MediaSessionService(MediaSessionService.java:278)
                                                                                                          at androidx.media3.session.MediaSessionService$$ExternalSyntheticLambda3.run(D8$$SyntheticClass:0)
                                                                                                          at androidx.media3.common.util.Util.postOrRun(Util.java:794)
                                                                                                          at androidx.media3.session.MediaSessionService.addSession(MediaSessionService.java:275)
                                                                                                          at androidx.media3.session.MediaSessionService$MediaSessionServiceStub.lambda$connect$0$androidx-media3-session-MediaSessionService$MediaSessionServiceStub(MediaSessionService.java:774)
                                                                                                          at androidx.media3.session.MediaSessionService$MediaSessionServiceStub$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
                                                                                                          at android.os.Handler.handleCallback(Handler.java:958)
                                                                                                          at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                          at android.os.Looper.loopOnce(Looper.java:222)
                                                                                                          at android.os.Looper.loop(Looper.java:314)
                                                                                                          at android.app.ActivityThread.main(ActivityThread.java:8658)
                                                                                                          at java.lang.reflect.Method.invoke(Native Method)
                                                                                                          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:565)
                                                                                                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)

FATAL EXCEPTION: main (Ask Gemini)
                                                                                                        Process: androidx.media3.demo.session, PID: 11183
                                                                                                    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:575)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
                                                                                                    Caused by: java.lang.reflect.InvocationTargetException
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:565)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081) 
                                                                                                    Caused by: java.util.concurrent.ExecutionException: java.lang.SecurityException: Session rejected the connection request.
                                                                                                        at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:594)
                                                                                                        at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:553)
                                                                                                        at androidx.media3.demo.session.MainActivity.getBrowser(MainActivity.kt:45)
                                                                                                        at androidx.media3.demo.session.MainActivity.pushRoot(MainActivity.kt:192)
                                                                                                        at androidx.media3.demo.session.MainActivity.initializeBrowser$lambda$3(MainActivity.kt:140)
                                                                                                        at androidx.media3.demo.session.MainActivity.$r8$lambda$HIt8HSUyPRhVvWb1EnKavKlFEpc(Unknown Source:0)
                                                                                                        at androidx.media3.demo.session.MainActivity$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
                                                                                                        at android.os.Handler.handleCallback(Handler.java:958)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:222)
                                                                                                        at android.os.Looper.loop(Looper.java:314)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:8658)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method) 
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:565) 
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081) 
                                                                                                    Caused by: java.lang.SecurityException: Session rejected the connection request.
                                                                                                        at androidx.media3.session.MediaControllerHolder.maybeSetException(MediaControllerHolder.java:67)
                                                                                                        at androidx.media3.session.MediaControllerHolder.onRejected(MediaControllerHolder.java:57)
                                                                                                        at androidx.media3.session.MediaController.release(MediaController.java:595)
                                                                                                        at androidx.media3.session.MediaControllerImplBase$$ExternalSyntheticLambda42.run(D8$$SyntheticClass:0)
                                                                                                        at androidx.media3.common.util.Util.postOrRun(Util.java:794)
                                                                                                        at androidx.media3.session.MediaController.runOnApplicationLooper(MediaController.java:2011)
                                                                                                        at androidx.media3.session.MediaControllerStub.lambda$onDisconnected$1(MediaControllerStub.java:106)
                                                                                                        at androidx.media3.session.MediaControllerStub$$ExternalSyntheticLambda9.run(D8$$SyntheticClass:0)
                                                                                                        at androidx.media3.session.MediaControllerStub.lambda$dispatchControllerTaskOnHandler$14(MediaControllerStub.java:374)
                                                                                                        at androidx.media3.session.MediaControllerStub$$ExternalSyntheticLambda6.run(D8$$SyntheticClass:0)
                                                                                                        at androidx.media3.common.util.Util.postOrRun(Util.java:794)
                                                                                                        at androidx.media3.session.MediaControllerStub.dispatchControllerTaskOnHandler(MediaControllerStub.java:366)
                                                                                                        at androidx.media3.session.MediaControllerStub.onDisconnected(MediaControllerStub.java:104)
                                                                                                        at androidx.media3.session.MediaSessionService$MediaSessionServiceStub.lambda$connect$0$androidx-media3-session-MediaSessionService$MediaSessionServiceStub(MediaSessionService.java:786)
                                                                                                        at androidx.media3.session.MediaSessionService$MediaSessionServiceStub$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
                                                                                                        at android.os.Handler.handleCallback(Handler.java:958) 
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99) 
                                                                                                        at android.os.Looper.loopOnce(Looper.java:222) 
                                                                                                        at android.os.Looper.loop(Looper.java:314) 
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:8658) 
                                                                                                        at java.lang.reflect.Method.invoke(Native Method) 
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:565) 
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081) 

I'm curious if there is an icon missing from the list you would have liked to use?

My usage is more specific. I want to use this library as an extension for AppInventor. I don't have access to resources and therefore icons from media3. I thought the setIconUri method would be perfect in this case.

tonihei commented 2 days ago

.setIconUri(Icons.getIconUri(Icons.ICON_CLOSE, context)) You must specify an icon resource id to build a CustomAction

The error message highlights that you must specify a resource id and not just a Uri. This isn't very well documented I'm afraid and we also want to restrict the Uris to just content Uris that can be more easily understood by some controllers.

My usage is more specific. I want to use this library as an extension for AppInventor. I don't have access to resources and therefore icons from media3

If you are able to access the media3 APIs you should also have access to its resources as they are bundled into the dependency.

patryk84a commented 2 days ago

The error message highlights that you must specify a resource id and not just a Uri. This isn't very well documented I'm afraid and we also want to restrict the Uris to just content Uris that can be more easily understood by some controllers.

When adding icon id and icon uri, only icon id is taken into account, icon from uri is never displayed. I don't really understand what this method does and where icon from uri is used. Either something is not finished or stopped working in some version of the library.

If you are able to access the media3 APIs you should also have access to its resources as they are bundled into the dependency.

Unfortunately, extensions for AppInventor can only contain jar libraries without additional resources from aar. For this reason, sometimes you have to use various workarounds to run a library on this platform. Do you know in which android resources are these three standard notification icons? Maybe there are multimedia icons somewhere in android other than android.R.drawable.icmedia**?

tonihei commented 2 days ago

I don't really understand what this method does and where icon from uri is used

The Uri have only been added recently and are only understood by a limited set of controllers (e.g. the connection to WearOS devices). We have plans to make this more flexible/automatic and generally move towards content Uris, but for now the Uris are not widely implemented and you definitely need an icon resource I'm afraid.

Unfortunately, extensions for AppInventor can only contain jar libraries without additional resources from aar

I'm not very familiar with this system to provide more detailed help here. The media3 icons are part of the aar, and there are also some limited icons in the android platform I believe (like the one you mentioned), but I don't think there are any others.