Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foreground service types are required since Android 14 #11239

Closed
devno44 opened this issue Jul 5, 2023 · 7 comments
Closed

Foreground service types are required since Android 14 #11239

devno44 opened this issue Jul 5, 2023 · 7 comments
Assignees

Comments

@devno44
Copy link

devno44 commented Jul 5, 2023

Hello,

Regarding to the behavior changes since Android 14, If your app targets Android 14, it must specify appropriate foreground service types.
https://developer.android.com/about/versions/14/changes/fgs-types-required

Can you tell me what service type that we should use for all service class of ExoPlayer ?
For example: DownloadService.etc..

@Tolriq
Copy link
Contributor

Tolriq commented Jul 10, 2023

This is the fun part about Android 14 and the future :)

DownloadService should be "dataSync" with the corresponding permission (FOREGROUND_SERVICE_DATA_SYNC). But they already warn that "dataSync" will be deprecated and removed in the future (And guarded by Google Play review team).

So according to Google DownloadService should not exist and should be migrated to user-initiated data transfer jobs / workmanager.

I have hope that teams like Media3 can explain to the other Google team that syncing data should be possible without using an ultra limiting API. (The new API requires that you put constraints on Internet conditions and can't run without connectivity).
So the other nice stuff like TransformerAPI that would require a foreground service to convert a large file urgently can't be done efficiently now. All the other API that some limitations that could prevent the job from starting when wanted.

TL;DR; For Android 14 use "dataSync", but keep in mind that they may break everything as soon as Android 15 and should plan.

@tonihei tonihei self-assigned this Jul 10, 2023
@tonihei
Copy link
Collaborator

tonihei commented Jul 10, 2023

all service class of ExoPlayer

The answer to your questions depends on which type of service we are talking about exactly.

  • For background media playback, we recommend to use the MediaSessionService or MediaLibraryService we provide as part of Media3. These classes internally already set the FOREGROUND_SERVICE_MEDIA_PLAYBACK correctly. You may still need to declare this type in your manifest (this part is slightly unclear as we have to figure out the detailed requirements too).
  • For ExoPlayer's DownloadService and any custom background download service, FOREGROUND_SERVICE_DATA_SYNC should be used. As @Tolriq already pointed out above, this type is an intermediate solution to give apps and libraries more time to migrate to more suitable structures than plain Service instances. There won't be any enforcement for this in the near future and ExoPlayer needs to migrate its DownloadService to something else too. Background downloads are generally not time-critical and should ideally use WorkManager or user-initiated data transfer jobs.
  • Background processing, e.g. for Media3's Transformer API, is sometimes time-critical (e.g. if the user is waiting for the transformed media to share it further). The preferred solution for this case is use a service with type shortService that has no restrictions, is run immediately, but limited to 3 minutes. Media3 provides no out-of-the-box service for background transformations at the moment, so this is up to each app to integrate into their workflows (since it also depends on the expected work duration).

I'll leave this issue open as an enhancement to clarify the open question about whether the media playback use case needs to be declared in the manifest too and to track alternative solutions for our DownloadService for the longer-term future.

@Tolriq
Copy link
Contributor

Tolriq commented Jul 10, 2023

@tonihei The permission is mandatory too and it does not seem to be present for now (in media3 or here)

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

For the rest shortService limits to 3 minutes is really short to transcode video on low end devices. And downloads / transformer can often be time critical. (And those kind of jobs should not be cancelled as not really resumable in most of the cases).

Not everyone play media from servers with different streams and all the nice stuff :)

Some apps play user content stored on simple web servers that does not support transcode or things like that and the playback action is actually download / transform to something that the device can play then play.

Relying on APIs that can delay the start of the job for undetermined time based on impossible to know limits at the time the job start is just not an acceptable from the user POV.

Blocking of foreground services started when the app is visible for those kind of use case without an appropriate solution will trigger issues.

Of course the workaround will simply be to bind everything to the playback service and have the playback notification show a preparing media but then this defeat everything and does not solve what all those changes are supposed to do.
Keep dataSync, make the permission requiring a validation from the user to get.

@tonihei
Copy link
Collaborator

tonihei commented Jul 10, 2023

Thanks for the additional details!

the playback action is actually download / transform to something that the device can play then play

If the task is that tightly coupled to the actual playback, then I think FOREGROUND_SERVICE_MEDIA_PLAYBACK is an appropriate choice and in line with the what those foreground service types are supposed to achieve.

have the playback notification show a preparing media

The best way to integrate this is probably via a WrappingMediaSource or similar that loads the necessary data before preparing the actual wrapped source. This means you can use a player and set up a MediaSession as you would normally and the notification will just automatically show the item that the user selected for playback.

@Tolriq
Copy link
Contributor

Tolriq commented Jul 10, 2023

The best way to integrate this is probably via a WrappingMediaSource or similar that loads the necessary data before preparing the actual wrapped source. This means you can use a player and set up a MediaSession as you would normally and the notification will just automatically show the item that the user selected for playback.

This triggers many UX/UI issues to properly notify the user about what is going on, estimated time for end of transcoding or at least a percentage and everything needed for the user to not click everywhere as he think the media is started when it's not.

We have the buffering state to handle relatively fast case like when we can transcode server side and just need to wait for the process to have transcoded enough to start playback. But for longer things like described above this does not really fit.

Not sure this is something that can easily be handled / exposed directly via ExoPlayer. But even for the fast case of starting the transcode on server then wait for enough data to be buffered, having an internal state in ExoPlayer for long media preparation would effectively solve this and allow usage of WrappingMediaSource or equivalent and properly be a mediaPlayback foreground service type.

@tonihei
Copy link
Collaborator

tonihei commented Jul 18, 2023

We made some changes to improve Android 14 foreground service compatibility:

  • Updated all of our own demo apps to target API 34 to show how it can be used.
  • Updated documentation to highlight required permissions for background playback with MediaSessionService and for DownloadService.
  • Added missing type declaration in DownloadService itself.

I think this addresses all of the issues here.

@Tolriq The points you raise in your last post are all valid and you may be able to achieve this by customizing the notification that gets created for MediaSessionService. But this discussion is more about an advanced use case and how to integrate it nicely and not fully related to the original question. If you feel there are more improvements we could do, please let us know in a new issue specifically for that.

@tonihei tonihei closed this as completed Jul 18, 2023
icbaker pushed a commit that referenced this issue Jul 21, 2023
This helps to highlight and document new requirements for apps,
e.g. to add the FOREGROUND_SERVICE_MEDIA_PLAYBACK permission for
background playback.

Issue: #11239
PiperOrigin-RevId: 548666056
icbaker pushed a commit that referenced this issue Jul 21, 2023
This ensures the DownloadService stays functional on Android 14
where defining this type is required. On Android 14 and above,
the app also needs to define the DATA_SYNC permission, which is
added to the demo app as well. In the future, this service type
will no longer be supported and DownloadService needs to be
rewritten with another background scheduling framework.

Issue: #11239
PiperOrigin-RevId: 548994842
icbaker pushed a commit to androidx/media that referenced this issue Jul 21, 2023
This helps to highlight and document new requirements for apps,
e.g. to add the FOREGROUND_SERVICE_MEDIA_PLAYBACK permission for
background playback.

Issue: google/ExoPlayer#11239
PiperOrigin-RevId: 548666056
icbaker pushed a commit to androidx/media that referenced this issue Jul 21, 2023
This ensures the DownloadService stays functional on Android 14
where defining this type is required. On Android 14 and above,
the app also needs to define the DATA_SYNC permission, which is
added to the demo app as well. In the future, this service type
will no longer be supported and DownloadService needs to be
rewritten with another background scheduling framework.

Issue: google/ExoPlayer#11239
PiperOrigin-RevId: 548994842
@Allanksr
Copy link

Allanksr commented Sep 13, 2023

Hello,

Regarding to the behavior changes since Android 14, If your app targets Android 14, it must specify appropriate foreground service types. https://developer.android.com/about/versions/14/changes/fgs-types-required

Can you tell me what service type that we should use for all service class of ExoPlayer ? For example: DownloadService.etc..

In the service type I used ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK and it is also necessary to use the permissions in the manifest

if (SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { startForeground( notificationId, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, ) }

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" android:maxSdkVersion="34" />

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

<service android:name=".DownloadService" android:foregroundServiceType="mediaPlayback" android:enabled="true" android:exported="false"> <property android:name="android.app.FOREGROUND_SERVICE_MEDIA_PLAYBACK" android:value="test"/> </service>

for me it works

@google google locked and limited conversation to collaborators Sep 17, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants