Skip to content

Instantly share code, notes, and snippets.

@0xcaff
Last active April 19, 2020 23:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0xcaff/c20e4ea226c33eb68a5cd9cbb80fbb96 to your computer and use it in GitHub Desktop.
Save 0xcaff/c20e4ea226c33eb68a5cd9cbb80fbb96 to your computer and use it in GitHub Desktop.
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer.audiodemo;
import static com.google.android.exoplayer.audiodemo.C.MEDIA_SESSION_TAG;
import static com.google.android.exoplayer.audiodemo.C.PLAYBACK_CHANNEL_ID;
import static com.google.android.exoplayer.audiodemo.C.PLAYBACK_NOTIFICATION_ID;
import static com.google.android.exoplayer.audiodemo.Samples.SAMPLES;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Debug;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.media.MediaDescriptionCompat;
import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
import com.google.android.exoplayer2.ui.PlayerNotificationManager.BitmapCallback;
import com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter;
import com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.NotificationUtil;
import com.google.android.exoplayer2.util.Util;
public class AudioPlayerService extends Service {
private SimpleExoPlayer player;
private PlayerNotificationManager playerNotificationManager;
private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;
@Override
public void onCreate() {
super.onCreate();
final Context context = this;
player = ExoPlayerFactory.newSimpleInstance(context, new DefaultTrackSelector());
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(
context, Util.getUserAgent(context, getString(R.string.application_name)));
ConcatenatingMediaSource concatenatingMediaSource = new ConcatenatingMediaSource();
for (Samples.Sample sample : SAMPLES) {
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(sample.uri);
concatenatingMediaSource.addMediaSource(mediaSource);
}
player.prepare(concatenatingMediaSource);
player.setPlayWhenReady(true);
NotificationUtil.createNotificationChannel(
context,
PLAYBACK_CHANNEL_ID,
R.string.playback_channel_name,
NotificationUtil.IMPORTANCE_LOW
);
MediaDescriptionAdapter descriptionAdapter = new MediaDescriptionAdapter() {
@Override
public String getCurrentContentTitle(Player player) {
return SAMPLES[player.getCurrentWindowIndex()].title;
}
@Nullable
@Override
public PendingIntent createCurrentContentIntent(Player player) {
return null;
}
@Nullable
@Override
public String getCurrentContentText(Player player) {
return SAMPLES[player.getCurrentWindowIndex()].description;
}
@Nullable
@Override
public Bitmap getCurrentLargeIcon(Player player, BitmapCallback callback) {
return Samples.getBitmap(
context, SAMPLES[player.getCurrentWindowIndex()].bitmapResource);
}
};
PlayerNotificationManager.NotificationDispatcher notificationDispatcher = new PlayerNotificationManager.NotificationDispatcher() {
boolean foregrounded = false;
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(AudioPlayerService.this);
@Override
public void notify(int notificationId, Notification notification) {
if (player.getPlayWhenReady() && !foregrounded) {
Util.startForegroundService(
AudioPlayerService.this,
new Intent(context, AudioPlayerService.class)
);
startForeground(notificationId, notification);
foregrounded = true;
} else {
notificationManager.notify(notificationId, notification);
}
if (!player.getPlayWhenReady() && foregrounded) {
stopForeground(false);
foregrounded = false;
}
}
@Override
public void cancel(int notificationId) {
notificationManager.cancel(notificationId);
stopForeground(true);
stopSelf();
foregrounded = false;
}
};
playerNotificationManager = new PlayerNotificationManager(
context,
PLAYBACK_CHANNEL_ID,
PLAYBACK_NOTIFICATION_ID,
descriptionAdapter,
null,
null,
notificationDispatcher
);
playerNotificationManager.setOngoing(false);
playerNotificationManager.setPlayer(player);
mediaSession = new MediaSessionCompat(context, MEDIA_SESSION_TAG);
mediaSession.setActive(true);
playerNotificationManager.setMediaSessionToken(mediaSession.getSessionToken());
mediaSessionConnector = new MediaSessionConnector(mediaSession);
mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
@Override
public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
return Samples.getMediaDescription(context, SAMPLES[windowIndex]);
}
});
mediaSessionConnector.setPlayer(player, null);
}
@Override
public void onDestroy() {
mediaSession.release();
mediaSessionConnector.setPlayer(null, null);
playerNotificationManager.setPlayer(null);
player.release();
player = null;
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
@ciaranodc
Copy link

Is the whole project for this available somewhere?

@0xcaff
Copy link
Author

0xcaff commented Nov 19, 2019

@ciaranodc Yeah, I don't remember what state I left it in exactly: https://github.com/forte-music/android

Copy link

ghost commented Apr 19, 2020

Where is the playerView and when to attach it to the play in case of MainActivity as a Service ? because I instantiated it either in onCreate MainActivity or the AudioPlayerService and all the mainActivity UI doesnt' show at all !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment