2017-09-03 08:04:18 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2017 Mauricio Colli <mauriciocolli@outlook.com>
|
|
|
|
* BackgroundPlayer.java is part of NewPipe
|
|
|
|
*
|
|
|
|
* License: GPL-3.0+
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2016-02-22 20:28:37 +01:00
|
|
|
package org.schabi.newpipe.player;
|
2015-11-24 01:40:36 +01:00
|
|
|
|
2015-11-25 18:18:01 +01:00
|
|
|
import android.app.NotificationManager;
|
2015-11-29 18:05:44 +01:00
|
|
|
import android.app.PendingIntent;
|
2015-11-25 16:19:50 +01:00
|
|
|
import android.app.Service;
|
|
|
|
import android.content.Context;
|
2015-11-24 01:40:36 +01:00
|
|
|
import android.content.Intent;
|
2015-12-17 18:49:12 +01:00
|
|
|
import android.content.IntentFilter;
|
2015-12-25 00:09:35 +01:00
|
|
|
import android.graphics.Bitmap;
|
2015-11-25 16:19:50 +01:00
|
|
|
import android.net.wifi.WifiManager;
|
2017-10-03 08:38:46 +02:00
|
|
|
import android.os.Binder;
|
2017-04-17 06:19:53 +02:00
|
|
|
import android.os.Build;
|
2015-11-25 16:19:50 +01:00
|
|
|
import android.os.IBinder;
|
2015-11-24 01:40:36 +01:00
|
|
|
import android.os.PowerManager;
|
2017-04-17 06:19:53 +02:00
|
|
|
import android.support.annotation.IntRange;
|
2017-10-10 02:25:45 +02:00
|
|
|
import android.support.annotation.NonNull;
|
2017-09-24 22:44:31 +02:00
|
|
|
import android.support.annotation.Nullable;
|
2017-04-17 06:19:53 +02:00
|
|
|
import android.support.v4.app.NotificationCompat;
|
2015-11-25 18:18:01 +01:00
|
|
|
import android.util.Log;
|
2016-01-02 16:08:18 +01:00
|
|
|
import android.widget.RemoteViews;
|
2017-10-08 06:39:34 +02:00
|
|
|
import android.widget.Toast;
|
2015-11-24 01:40:36 +01:00
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
import com.google.android.exoplayer2.PlaybackParameters;
|
2017-09-05 00:38:58 +02:00
|
|
|
import com.google.android.exoplayer2.Player;
|
2017-09-06 02:48:48 +02:00
|
|
|
import com.google.android.exoplayer2.source.MediaSource;
|
2017-09-05 00:38:58 +02:00
|
|
|
|
2016-02-22 20:28:37 +01:00
|
|
|
import org.schabi.newpipe.BuildConfig;
|
2017-04-09 19:34:00 +02:00
|
|
|
import org.schabi.newpipe.MainActivity;
|
2016-02-22 20:28:37 +01:00
|
|
|
import org.schabi.newpipe.R;
|
2017-04-17 06:19:53 +02:00
|
|
|
import org.schabi.newpipe.extractor.MediaFormat;
|
2017-04-09 19:34:00 +02:00
|
|
|
import org.schabi.newpipe.extractor.StreamingService;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.AudioStream;
|
2017-09-06 02:48:48 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
2017-10-10 02:25:45 +02:00
|
|
|
import org.schabi.newpipe.playlist.PlayQueueItem;
|
2017-04-09 19:34:00 +02:00
|
|
|
import org.schabi.newpipe.util.Constants;
|
2017-09-06 02:48:48 +02:00
|
|
|
import org.schabi.newpipe.util.ListHelper;
|
2017-04-17 06:19:53 +02:00
|
|
|
import org.schabi.newpipe.util.ThemeHelper;
|
|
|
|
|
2015-11-24 01:40:36 +01:00
|
|
|
|
|
|
|
/**
|
2017-04-17 06:19:53 +02:00
|
|
|
* Base players joining the common properties
|
2015-11-24 01:40:36 +01:00
|
|
|
*
|
2017-04-17 06:19:53 +02:00
|
|
|
* @author mauriciocolli
|
2015-11-24 01:40:36 +01:00
|
|
|
*/
|
2017-09-15 04:52:40 +02:00
|
|
|
public final class BackgroundPlayer extends Service {
|
2017-04-17 06:19:53 +02:00
|
|
|
private static final String TAG = "BackgroundPlayer";
|
|
|
|
private static final boolean DEBUG = BasePlayer.DEBUG;
|
2015-11-25 16:19:50 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
public static final String ACTION_CLOSE = "org.schabi.newpipe.player.BackgroundPlayer.CLOSE";
|
|
|
|
public static final String ACTION_PLAY_PAUSE = "org.schabi.newpipe.player.BackgroundPlayer.PLAY_PAUSE";
|
|
|
|
public static final String ACTION_OPEN_DETAIL = "org.schabi.newpipe.player.BackgroundPlayer.OPEN_DETAIL";
|
|
|
|
public static final String ACTION_REPEAT = "org.schabi.newpipe.player.BackgroundPlayer.REPEAT";
|
|
|
|
public static final String ACTION_FAST_REWIND = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_FAST_REWIND";
|
|
|
|
public static final String ACTION_FAST_FORWARD = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_FAST_FORWARD";
|
2015-11-24 01:40:36 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private BasePlayerImpl basePlayerImpl;
|
|
|
|
private PowerManager powerManager;
|
|
|
|
private WifiManager wifiManager;
|
|
|
|
|
|
|
|
private PowerManager.WakeLock wakeLock;
|
|
|
|
private WifiManager.WifiLock wifiLock;
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
2017-10-03 08:38:46 +02:00
|
|
|
// Service-Activity Binder
|
2017-04-17 06:19:53 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
public interface PlayerEventListener {
|
2017-10-10 03:20:11 +02:00
|
|
|
void onPlaybackUpdate(int state, int repeatMode, boolean shuffled, PlaybackParameters parameters);
|
2017-10-03 08:38:46 +02:00
|
|
|
void onProgressUpdate(int currentProgress, int duration, int bufferPercent);
|
|
|
|
void onMetadataUpdate(StreamInfo info);
|
|
|
|
void onServiceStopped();
|
|
|
|
}
|
2017-09-30 05:38:26 +02:00
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
private PlayerEventListener activityListener;
|
|
|
|
private IBinder mBinder;
|
|
|
|
|
|
|
|
class LocalBinder extends Binder {
|
|
|
|
BasePlayerImpl getBackgroundPlayerInstance() {
|
|
|
|
return BackgroundPlayer.this.basePlayerImpl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Notification
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
private static final int NOTIFICATION_ID = 123789;
|
2017-04-17 06:19:53 +02:00
|
|
|
private NotificationManager notificationManager;
|
|
|
|
private NotificationCompat.Builder notBuilder;
|
|
|
|
private RemoteViews notRemoteView;
|
|
|
|
private RemoteViews bigNotRemoteView;
|
|
|
|
private final String setAlphaMethodName = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ? "setImageAlpha" : "setAlpha";
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Service's LifeCycle
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
2015-11-25 16:19:50 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCreate() {
|
2017-04-17 06:19:53 +02:00
|
|
|
if (DEBUG) Log.d(TAG, "onCreate() called");
|
|
|
|
notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
|
|
|
|
powerManager = ((PowerManager) getSystemService(POWER_SERVICE));
|
|
|
|
wifiManager = ((WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE));
|
|
|
|
|
2017-04-26 21:32:20 +02:00
|
|
|
ThemeHelper.setTheme(this);
|
2017-04-17 06:19:53 +02:00
|
|
|
basePlayerImpl = new BasePlayerImpl(this);
|
|
|
|
basePlayerImpl.setup();
|
2017-10-03 08:38:46 +02:00
|
|
|
|
|
|
|
mBinder = new LocalBinder();
|
2015-11-25 16:19:50 +01:00
|
|
|
}
|
2017-04-17 06:19:53 +02:00
|
|
|
|
2015-11-25 16:19:50 +01:00
|
|
|
@Override
|
|
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
2017-04-17 06:19:53 +02:00
|
|
|
if (DEBUG) Log.d(TAG, "onStartCommand() called with: intent = [" + intent + "], flags = [" + flags + "], startId = [" + startId + "]");
|
|
|
|
basePlayerImpl.handleIntent(intent);
|
2015-11-25 16:19:50 +01:00
|
|
|
return START_NOT_STICKY;
|
2015-11-24 01:40:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-04-17 06:19:53 +02:00
|
|
|
public void onDestroy() {
|
|
|
|
if (DEBUG) Log.d(TAG, "destroy() called");
|
|
|
|
releaseWifiAndCpu();
|
|
|
|
stopForeground(true);
|
|
|
|
if (basePlayerImpl != null) basePlayerImpl.destroy();
|
2015-11-25 16:19:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-04-17 06:19:53 +02:00
|
|
|
public IBinder onBind(Intent intent) {
|
2017-10-03 08:38:46 +02:00
|
|
|
return mBinder;
|
2015-11-25 16:19:50 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Actions
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
public void openControl(final Context context) {
|
|
|
|
final Intent intent = new Intent(context, BackgroundPlayerActivity.class);
|
|
|
|
context.startActivity(intent);
|
|
|
|
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private void onClose() {
|
2017-10-03 08:38:46 +02:00
|
|
|
if (basePlayerImpl != null) {
|
|
|
|
basePlayerImpl.stopActivityBinding();
|
|
|
|
basePlayerImpl.destroyPlayer();
|
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
stopForeground(true);
|
|
|
|
releaseWifiAndCpu();
|
|
|
|
stopSelf();
|
|
|
|
}
|
2016-01-02 16:08:18 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private void onScreenOnOff(boolean on) {
|
|
|
|
if (DEBUG) Log.d(TAG, "onScreenOnOff() called with: on = [" + on + "]");
|
2017-09-30 05:38:26 +02:00
|
|
|
if (on) {
|
|
|
|
if (basePlayerImpl.isPlaying() && !basePlayerImpl.isProgressLoopRunning()) {
|
|
|
|
basePlayerImpl.startProgressLoop();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
basePlayerImpl.stopProgressLoop();
|
|
|
|
}
|
2017-04-17 06:19:53 +02:00
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Notification
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-09-30 05:38:26 +02:00
|
|
|
private void resetNotification() {
|
2017-10-03 08:38:46 +02:00
|
|
|
notBuilder = createNotification();
|
2017-09-30 05:38:26 +02:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private NotificationCompat.Builder createNotification() {
|
|
|
|
notRemoteView = new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification);
|
|
|
|
bigNotRemoteView = new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification_expanded);
|
|
|
|
|
|
|
|
setupNotification(notRemoteView);
|
|
|
|
setupNotification(bigNotRemoteView);
|
|
|
|
|
2017-08-18 14:05:31 +02:00
|
|
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
|
2017-04-17 06:19:53 +02:00
|
|
|
.setOngoing(true)
|
|
|
|
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
|
|
.setCustomContentView(notRemoteView)
|
|
|
|
.setCustomBigContentView(bigNotRemoteView);
|
2017-08-18 14:05:31 +02:00
|
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) builder.setPriority(NotificationCompat.PRIORITY_MAX);
|
2017-04-17 06:19:53 +02:00
|
|
|
return builder;
|
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private void setupNotification(RemoteViews remoteViews) {
|
|
|
|
remoteViews.setOnClickPendingIntent(R.id.notificationPlayPause,
|
|
|
|
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT));
|
|
|
|
remoteViews.setOnClickPendingIntent(R.id.notificationStop,
|
|
|
|
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_CLOSE), PendingIntent.FLAG_UPDATE_CURRENT));
|
|
|
|
remoteViews.setOnClickPendingIntent(R.id.notificationContent,
|
|
|
|
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_OPEN_DETAIL), PendingIntent.FLAG_UPDATE_CURRENT));
|
|
|
|
remoteViews.setOnClickPendingIntent(R.id.notificationRepeat,
|
|
|
|
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_REPEAT), PendingIntent.FLAG_UPDATE_CURRENT));
|
|
|
|
|
|
|
|
remoteViews.setOnClickPendingIntent(R.id.notificationFRewind,
|
|
|
|
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_FAST_REWIND), PendingIntent.FLAG_UPDATE_CURRENT));
|
|
|
|
remoteViews.setOnClickPendingIntent(R.id.notificationFForward,
|
|
|
|
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_FAST_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT));
|
|
|
|
|
2017-09-05 00:38:58 +02:00
|
|
|
switch (basePlayerImpl.simpleExoPlayer.getRepeatMode()) {
|
|
|
|
case Player.REPEAT_MODE_OFF:
|
2017-04-17 06:19:53 +02:00
|
|
|
remoteViews.setInt(R.id.notificationRepeat, setAlphaMethodName, 77);
|
|
|
|
break;
|
2017-09-05 00:38:58 +02:00
|
|
|
case Player.REPEAT_MODE_ONE:
|
|
|
|
// todo change image
|
2017-10-03 08:38:46 +02:00
|
|
|
remoteViews.setInt(R.id.notificationRepeat, setAlphaMethodName, 168);
|
2017-04-17 06:19:53 +02:00
|
|
|
break;
|
2017-09-05 00:38:58 +02:00
|
|
|
case Player.REPEAT_MODE_ALL:
|
|
|
|
remoteViews.setInt(R.id.notificationRepeat, setAlphaMethodName, 255);
|
2017-04-17 06:19:53 +02:00
|
|
|
break;
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
2017-04-17 06:19:53 +02:00
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
/**
|
|
|
|
* Updates the notification, and the play/pause button in it.
|
|
|
|
* Used for changes on the remoteView
|
|
|
|
*
|
|
|
|
* @param drawableId if != -1, sets the drawable with that id on the play/pause button
|
|
|
|
*/
|
2017-09-07 22:01:02 +02:00
|
|
|
private synchronized void updateNotification(int drawableId) {
|
2017-09-08 06:47:43 +02:00
|
|
|
//if (DEBUG) Log.d(TAG, "updateNotification() called with: drawableId = [" + drawableId + "]");
|
2017-10-03 08:38:46 +02:00
|
|
|
if (notBuilder == null) return;
|
2017-04-17 06:19:53 +02:00
|
|
|
if (drawableId != -1) {
|
|
|
|
if (notRemoteView != null) notRemoteView.setImageViewResource(R.id.notificationPlayPause, drawableId);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewResource(R.id.notificationPlayPause, drawableId);
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
2017-04-17 06:19:53 +02:00
|
|
|
notificationManager.notify(NOTIFICATION_ID, notBuilder.build());
|
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private void setControlsOpacity(@IntRange(from = 0, to = 255) int opacity) {
|
|
|
|
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationPlayPause, setAlphaMethodName, opacity);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationPlayPause, setAlphaMethodName, opacity);
|
|
|
|
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationFForward, setAlphaMethodName, opacity);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationFForward, setAlphaMethodName, opacity);
|
|
|
|
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationFRewind, setAlphaMethodName, opacity);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationFRewind, setAlphaMethodName, opacity);
|
|
|
|
}
|
2015-11-25 18:18:01 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Utils
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
2015-12-25 00:09:35 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private void lockWifiAndCpu() {
|
|
|
|
if (DEBUG) Log.d(TAG, "lockWifiAndCpu() called");
|
|
|
|
if (wakeLock != null && wakeLock.isHeld() && wifiLock != null && wifiLock.isHeld()) return;
|
2015-12-17 18:49:12 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
|
|
|
wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG);
|
2015-12-17 18:49:12 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
if (wakeLock != null) wakeLock.acquire();
|
|
|
|
if (wifiLock != null) wifiLock.acquire();
|
|
|
|
}
|
2015-12-17 18:49:12 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
private void releaseWifiAndCpu() {
|
|
|
|
if (DEBUG) Log.d(TAG, "releaseWifiAndCpu() called");
|
|
|
|
if (wakeLock != null && wakeLock.isHeld()) wakeLock.release();
|
|
|
|
if (wifiLock != null && wifiLock.isHeld()) wifiLock.release();
|
2016-01-02 16:08:18 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
wakeLock = null;
|
|
|
|
wifiLock = null;
|
|
|
|
}
|
2016-12-27 14:37:18 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2016-12-27 14:37:18 +01:00
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
protected class BasePlayerImpl extends BasePlayer {
|
2016-12-27 14:37:18 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
BasePlayerImpl(Context context) {
|
|
|
|
super(context);
|
|
|
|
}
|
2016-02-21 17:55:00 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
|
|
|
public void handleIntent(Intent intent) {
|
|
|
|
super.handleIntent(intent);
|
2017-09-05 21:27:12 +02:00
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
resetNotification();
|
2017-09-05 21:27:12 +02:00
|
|
|
startForeground(NOTIFICATION_ID, notBuilder.build());
|
2017-04-17 06:19:53 +02:00
|
|
|
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false);
|
|
|
|
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false);
|
|
|
|
}
|
2016-02-19 13:22:49 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
2017-09-07 22:01:02 +02:00
|
|
|
public void initThumbnail(final String url) {
|
2017-09-30 05:38:26 +02:00
|
|
|
resetNotification();
|
2017-04-17 06:19:53 +02:00
|
|
|
if (notRemoteView != null) notRemoteView.setImageViewResource(R.id.notificationCover, R.drawable.dummy_thumbnail);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewResource(R.id.notificationCover, R.drawable.dummy_thumbnail);
|
|
|
|
updateNotification(-1);
|
2017-09-07 22:01:02 +02:00
|
|
|
super.initThumbnail(url);
|
2017-04-17 06:19:53 +02:00
|
|
|
}
|
2016-02-19 13:22:49 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
|
|
|
public void onThumbnailReceived(Bitmap thumbnail) {
|
|
|
|
super.onThumbnailReceived(thumbnail);
|
2017-09-07 22:01:02 +02:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
if (thumbnail != null) {
|
2017-09-07 22:01:02 +02:00
|
|
|
// rebuild notification here since remote view does not release bitmaps, causing memory leaks
|
2017-09-30 05:38:26 +02:00
|
|
|
resetNotification();
|
2017-09-07 22:01:02 +02:00
|
|
|
|
2017-09-08 06:47:43 +02:00
|
|
|
if (notRemoteView != null) notRemoteView.setImageViewBitmap(R.id.notificationCover, thumbnail);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, thumbnail);
|
2017-09-07 22:01:02 +02:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
updateNotification(-1);
|
2016-12-27 14:37:18 +01:00
|
|
|
}
|
2017-04-17 06:19:53 +02:00
|
|
|
}
|
2016-12-27 14:37:18 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
|
|
|
public void onPrepared(boolean playWhenReady) {
|
|
|
|
super.onPrepared(playWhenReady);
|
|
|
|
if (simpleExoPlayer.getDuration() < 15000) {
|
|
|
|
FAST_FORWARD_REWIND_AMOUNT = 2000;
|
|
|
|
} else if (simpleExoPlayer.getDuration() > 60 * 60 * 1000) {
|
|
|
|
FAST_FORWARD_REWIND_AMOUNT = 60000;
|
|
|
|
} else {
|
|
|
|
FAST_FORWARD_REWIND_AMOUNT = 10000;
|
2016-12-27 14:37:18 +01:00
|
|
|
}
|
2017-06-08 16:58:50 +02:00
|
|
|
PROGRESS_LOOP_INTERVAL = 1000;
|
2017-09-07 22:01:02 +02:00
|
|
|
simpleExoPlayer.setVolume(1f);
|
2016-01-02 16:08:18 +01:00
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
2017-10-10 03:20:11 +02:00
|
|
|
public void onShuffleClicked() {
|
|
|
|
super.onShuffleClicked();
|
|
|
|
updatePlayback();
|
2017-04-17 06:19:53 +02:00
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
|
|
|
public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) {
|
2017-09-30 05:38:26 +02:00
|
|
|
resetNotification();
|
2017-09-25 05:14:58 +02:00
|
|
|
if (bigNotRemoteView != null) {
|
2017-10-10 02:25:45 +02:00
|
|
|
if (currentItem != null) {
|
2017-09-25 06:10:45 +02:00
|
|
|
bigNotRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
|
|
|
|
bigNotRemoteView.setTextViewText(R.id.notificationArtist, getUploaderName());
|
|
|
|
}
|
2017-09-25 05:14:58 +02:00
|
|
|
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
|
|
|
|
bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration));
|
|
|
|
}
|
|
|
|
if (notRemoteView != null) {
|
2017-10-10 02:25:45 +02:00
|
|
|
if (currentItem != null) {
|
2017-09-25 06:10:45 +02:00
|
|
|
notRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
|
|
|
|
notRemoteView.setTextViewText(R.id.notificationArtist, getUploaderName());
|
|
|
|
}
|
2017-09-25 05:14:58 +02:00
|
|
|
notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
|
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
updateNotification(-1);
|
2017-10-03 08:38:46 +02:00
|
|
|
updateProgress(currentProgress, duration, bufferPercent);
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
|
|
|
public void onFastRewind() {
|
2017-09-06 08:49:00 +02:00
|
|
|
if (!isPlayerReady()) return;
|
2017-09-06 02:48:48 +02:00
|
|
|
|
2017-09-18 05:14:02 +02:00
|
|
|
onPlayPrevious();
|
2017-04-17 06:19:53 +02:00
|
|
|
triggerProgressUpdate();
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
|
|
|
public void onFastForward() {
|
2017-09-06 08:49:00 +02:00
|
|
|
if (!isPlayerReady()) return;
|
2017-09-06 02:48:48 +02:00
|
|
|
|
2017-09-18 05:14:02 +02:00
|
|
|
onPlayNext();
|
2017-04-17 06:19:53 +02:00
|
|
|
triggerProgressUpdate();
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
2017-10-03 08:38:46 +02:00
|
|
|
public void destroy() {
|
|
|
|
super.destroy();
|
|
|
|
if (notRemoteView != null) notRemoteView.setImageViewBitmap(R.id.notificationCover, null);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, null);
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-08-18 20:07:57 +02:00
|
|
|
@Override
|
2017-10-08 22:15:03 +02:00
|
|
|
public void onRecoverableError(Exception exception) {
|
2017-10-03 08:38:46 +02:00
|
|
|
exception.printStackTrace();
|
2017-10-08 06:39:34 +02:00
|
|
|
Toast.makeText(context, "Failed to play this audio", Toast.LENGTH_SHORT).show();
|
2017-10-03 08:38:46 +02:00
|
|
|
}
|
|
|
|
|
2017-10-08 22:15:03 +02:00
|
|
|
@Override
|
|
|
|
public void onUnrecoverableError(Exception exception) {
|
|
|
|
exception.printStackTrace();
|
|
|
|
Toast.makeText(context, "Unexpected error occurred", Toast.LENGTH_SHORT).show();
|
|
|
|
shutdown();
|
|
|
|
}
|
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ExoPlayer Listener
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
2017-08-18 20:07:57 +02:00
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
@Override
|
|
|
|
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
|
|
|
super.onPlaybackParametersChanged(playbackParameters);
|
|
|
|
updatePlayback();
|
2017-08-18 20:07:57 +02:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
2017-10-03 08:38:46 +02:00
|
|
|
public void onLoadingChanged(boolean isLoading) {
|
|
|
|
// Disable default behavior
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
2017-10-03 08:38:46 +02:00
|
|
|
public void onRepeatModeChanged(int i) {
|
|
|
|
int opacity = 255;
|
|
|
|
switch (simpleExoPlayer.getRepeatMode()) {
|
|
|
|
case Player.REPEAT_MODE_OFF:
|
|
|
|
opacity = 77;
|
|
|
|
break;
|
|
|
|
case Player.REPEAT_MODE_ONE:
|
|
|
|
// todo change image
|
|
|
|
opacity = 168;
|
|
|
|
break;
|
|
|
|
case Player.REPEAT_MODE_ALL:
|
|
|
|
opacity = 255;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, opacity);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, opacity);
|
|
|
|
updateNotification(-1);
|
|
|
|
updatePlayback();
|
2017-09-05 21:27:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Playback Listener
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-09-06 02:48:48 +02:00
|
|
|
@Override
|
2017-10-10 02:25:45 +02:00
|
|
|
public void sync(@NonNull final PlayQueueItem item, @Nullable final StreamInfo info) {
|
|
|
|
super.sync(item, info);
|
2017-09-06 02:48:48 +02:00
|
|
|
|
2017-09-30 05:38:26 +02:00
|
|
|
resetNotification();
|
2017-09-07 22:01:02 +02:00
|
|
|
notRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
|
|
|
|
notRemoteView.setTextViewText(R.id.notificationArtist, getUploaderName());
|
|
|
|
bigNotRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
|
|
|
|
bigNotRemoteView.setTextViewText(R.id.notificationArtist, getUploaderName());
|
2017-09-06 02:48:48 +02:00
|
|
|
updateNotification(-1);
|
2017-10-03 08:38:46 +02:00
|
|
|
updateMetadata();
|
2017-09-06 02:48:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-09-20 06:46:16 +02:00
|
|
|
public MediaSource sourceOf(final StreamInfo info) {
|
2017-09-25 05:14:58 +02:00
|
|
|
final int index = ListHelper.getDefaultAudioFormat(context, info.audio_streams);
|
2017-10-03 08:38:46 +02:00
|
|
|
if (index < 0) return null;
|
|
|
|
|
2017-09-25 05:14:58 +02:00
|
|
|
final AudioStream audio = info.audio_streams.get(index);
|
2017-09-24 06:50:32 +02:00
|
|
|
return buildMediaSource(audio.url, MediaFormat.getSuffixById(audio.format));
|
2017-09-06 02:48:48 +02:00
|
|
|
}
|
|
|
|
|
2017-09-05 21:27:12 +02:00
|
|
|
@Override
|
|
|
|
public void shutdown() {
|
|
|
|
super.shutdown();
|
2017-04-17 06:19:53 +02:00
|
|
|
stopSelf();
|
2017-10-03 08:38:46 +02:00
|
|
|
stopActivityBinding();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Activity Event Listener
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
public void setActivityListener(PlayerEventListener listener) {
|
|
|
|
activityListener = listener;
|
|
|
|
updateMetadata();
|
|
|
|
updatePlayback();
|
|
|
|
triggerProgressUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateMetadata() {
|
|
|
|
if (activityListener != null && currentInfo != null) {
|
|
|
|
activityListener.onMetadataUpdate(currentInfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updatePlayback() {
|
|
|
|
if (activityListener != null) {
|
2017-10-10 03:20:11 +02:00
|
|
|
activityListener.onPlaybackUpdate(currentState, simpleExoPlayer.getRepeatMode(), playQueue.isShuffled(), simpleExoPlayer.getPlaybackParameters());
|
2017-10-03 08:38:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateProgress(int currentProgress, int duration, int bufferPercent) {
|
|
|
|
if (activityListener != null) {
|
|
|
|
activityListener.onProgressUpdate(currentProgress, duration, bufferPercent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void stopActivityBinding() {
|
|
|
|
if (activityListener != null) {
|
|
|
|
activityListener.onServiceStopped();
|
|
|
|
activityListener = null;
|
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Broadcast Receiver
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void setupBroadcastReceiver(IntentFilter intentFilter) {
|
|
|
|
super.setupBroadcastReceiver(intentFilter);
|
|
|
|
intentFilter.addAction(ACTION_CLOSE);
|
|
|
|
intentFilter.addAction(ACTION_PLAY_PAUSE);
|
|
|
|
intentFilter.addAction(ACTION_OPEN_DETAIL);
|
|
|
|
intentFilter.addAction(ACTION_REPEAT);
|
|
|
|
intentFilter.addAction(ACTION_FAST_FORWARD);
|
|
|
|
intentFilter.addAction(ACTION_FAST_REWIND);
|
|
|
|
|
|
|
|
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
|
|
|
|
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
|
|
|
|
|
|
|
intentFilter.addAction(Intent.ACTION_HEADSET_PLUG);
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
@Override
|
|
|
|
public void onBroadcastReceived(Intent intent) {
|
|
|
|
super.onBroadcastReceived(intent);
|
|
|
|
if (DEBUG) Log.d(TAG, "onBroadcastReceived() called with: intent = [" + intent + "]");
|
|
|
|
switch (intent.getAction()) {
|
|
|
|
case ACTION_CLOSE:
|
|
|
|
onClose();
|
|
|
|
break;
|
|
|
|
case ACTION_PLAY_PAUSE:
|
|
|
|
onVideoPlayPause();
|
|
|
|
break;
|
|
|
|
case ACTION_OPEN_DETAIL:
|
2017-10-03 08:38:46 +02:00
|
|
|
openControl(BackgroundPlayer.this);
|
2017-04-17 06:19:53 +02:00
|
|
|
break;
|
|
|
|
case ACTION_REPEAT:
|
|
|
|
onRepeatClicked();
|
|
|
|
break;
|
|
|
|
case ACTION_FAST_REWIND:
|
|
|
|
onFastRewind();
|
|
|
|
break;
|
|
|
|
case ACTION_FAST_FORWARD:
|
|
|
|
onFastForward();
|
|
|
|
break;
|
|
|
|
case Intent.ACTION_SCREEN_ON:
|
|
|
|
onScreenOnOff(true);
|
|
|
|
break;
|
|
|
|
case Intent.ACTION_SCREEN_OFF:
|
|
|
|
onScreenOnOff(false);
|
|
|
|
break;
|
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// States
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-10-03 08:38:46 +02:00
|
|
|
@Override
|
|
|
|
public void changeState(int state) {
|
|
|
|
super.changeState(state);
|
|
|
|
updatePlayback();
|
|
|
|
}
|
|
|
|
|
2016-12-27 15:52:02 +01:00
|
|
|
@Override
|
2017-09-14 17:44:09 +02:00
|
|
|
public void onBlocked() {
|
|
|
|
super.onBlocked();
|
2017-04-17 06:19:53 +02:00
|
|
|
|
|
|
|
setControlsOpacity(77);
|
|
|
|
updateNotification(-1);
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-04-17 06:19:53 +02:00
|
|
|
public void onPlaying() {
|
|
|
|
super.onPlaying();
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
setControlsOpacity(255);
|
|
|
|
updateNotification(R.drawable.ic_pause_white);
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
lockWifiAndCpu();
|
|
|
|
}
|
2016-12-27 15:52:02 +01:00
|
|
|
|
|
|
|
@Override
|
2017-04-17 06:19:53 +02:00
|
|
|
public void onPaused() {
|
|
|
|
super.onPaused();
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
updateNotification(R.drawable.ic_play_arrow_white);
|
2017-09-07 22:01:02 +02:00
|
|
|
if (isProgressLoopRunning()) stopProgressLoop();
|
2016-12-27 15:52:02 +01:00
|
|
|
|
2017-04-17 06:19:53 +02:00
|
|
|
releaseWifiAndCpu();
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-04-17 06:19:53 +02:00
|
|
|
public void onCompleted() {
|
|
|
|
super.onCompleted();
|
|
|
|
|
|
|
|
setControlsOpacity(255);
|
|
|
|
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
|
|
|
|
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
|
|
|
|
updateNotification(R.drawable.ic_replay_white);
|
|
|
|
|
|
|
|
releaseWifiAndCpu();
|
2016-12-27 15:52:02 +01:00
|
|
|
}
|
|
|
|
}
|
2017-06-08 16:58:50 +02:00
|
|
|
}
|