Started DownloadServiceImpl refactor

This commit is contained in:
Nite 2020-06-21 09:31:38 +02:00
parent 96795701fe
commit 13b987791e
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
13 changed files with 2056 additions and 1876 deletions

View File

@ -118,7 +118,7 @@
<activity android:name=".activity.ServerSettingsActivity" /> <activity android:name=".activity.ServerSettingsActivity" />
<service <service
android:name=".service.DownloadServiceImpl" android:name=".service.MediaPlayerService"
android:label="UltraSonic Download Service" android:label="UltraSonic Download Service"
android:exported="false"> android:exported="false">
<intent-filter> <intent-filter>

View File

@ -36,6 +36,7 @@ import android.widget.TextView;
import org.moire.ultrasonic.R; import org.moire.ultrasonic.R;
import org.moire.ultrasonic.service.DownloadService; import org.moire.ultrasonic.service.DownloadService;
import org.moire.ultrasonic.service.DownloadServiceImpl; import org.moire.ultrasonic.service.DownloadServiceImpl;
import org.moire.ultrasonic.service.MediaPlayerService;
import org.moire.ultrasonic.service.MusicService; import org.moire.ultrasonic.service.MusicService;
import org.moire.ultrasonic.service.MusicServiceFactory; import org.moire.ultrasonic.service.MusicServiceFactory;
import org.moire.ultrasonic.util.Constants; import org.moire.ultrasonic.util.Constants;
@ -476,7 +477,7 @@ public class MainActivity extends SubsonicTabActivity
private void exit() private void exit()
{ {
stopService(new Intent(this, DownloadServiceImpl.class)); DownloadServiceImpl.getInstance().onCommand(new Intent(this, MediaPlayerService.class));
Util.unregisterMediaButtonEventReceiver(this); Util.unregisterMediaButtonEventReceiver(this);
finish(); finish();
} }

View File

@ -97,8 +97,7 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
applyTheme(); applyTheme();
super.onCreate(bundle); super.onCreate(bundle);
// This should always succeed as it is called when Ultrasonic is in the foreground if (DownloadServiceImpl.getInstance() == null) new DownloadServiceImpl(getApplicationContext());
startService(new Intent(this, DownloadServiceImpl.class));
setVolumeControlStream(AudioManager.STREAM_MUSIC); setVolumeControlStream(AudioManager.STREAM_MUSIC);
if (bundle != null) if (bundle != null)
@ -764,30 +763,17 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
public DownloadService getDownloadService() public DownloadService getDownloadService()
{ {
// If service is not available, request it to start and wait for it. DownloadService downloadService = DownloadServiceImpl.getInstance();
for (int i = 0; i < 5; i++)
if (downloadService != null)
{ {
DownloadService downloadService = DownloadServiceImpl.getInstance(); return downloadService;
if (downloadService != null)
{
return downloadService;
}
Log.w(TAG, "DownloadService not running. Attempting to start it.");
try
{
startService(new Intent(this, DownloadServiceImpl.class));
}
catch (IllegalStateException exception)
{
Log.w(TAG, "getDownloadService couldn't start DownloadServiceImpl because the application was in the background.");
return null;
}
Util.sleepQuietly(50L);
} }
Log.w(TAG, "DownloadService not running. Attempting to start it.");
new DownloadServiceImpl(getApplicationContext());
return DownloadServiceImpl.getInstance(); return DownloadServiceImpl.getInstance();
} }

View File

@ -19,6 +19,7 @@ import org.moire.ultrasonic.activity.MainActivity;
import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.MusicDirectory;
import org.moire.ultrasonic.service.DownloadService; import org.moire.ultrasonic.service.DownloadService;
import org.moire.ultrasonic.service.DownloadServiceImpl; import org.moire.ultrasonic.service.DownloadServiceImpl;
import org.moire.ultrasonic.service.MediaPlayerService;
import org.moire.ultrasonic.util.FileUtil; import org.moire.ultrasonic.util.FileUtil;
public class UltraSonicAppWidgetProvider extends AppWidgetProvider public class UltraSonicAppWidgetProvider extends AppWidgetProvider
@ -69,11 +70,11 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider
/** /**
* Handle a change notification coming over from {@link DownloadService} * Handle a change notification coming over from {@link DownloadService}
*/ */
public void notifyChange(Context context, DownloadService service, boolean playing, boolean setAlbum) public void notifyChange(Context context, MusicDirectory.Entry currentSong, boolean playing, boolean setAlbum)
{ {
if (hasInstances(context)) if (hasInstances(context))
{ {
performUpdate(context, service, null, playing, setAlbum); performUpdate(context, currentSong, null, playing, setAlbum);
} }
} }
@ -96,15 +97,14 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider
/** /**
* Update all active widget instances by pushing changes * Update all active widget instances by pushing changes
*/ */
private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing, boolean setAlbum) private void performUpdate(Context context, MusicDirectory.Entry currentSong, int[] appWidgetIds, boolean playing, boolean setAlbum)
{ {
final Resources res = context.getResources(); final Resources res = context.getResources();
final RemoteViews views = new RemoteViews(context.getPackageName(), this.layoutId); final RemoteViews views = new RemoteViews(context.getPackageName(), this.layoutId);
MusicDirectory.Entry currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong(); String title = currentSong == null ? null : currentSong.getTitle();
String title = currentPlaying == null ? null : currentPlaying.getTitle(); String artist = currentSong == null ? null : currentSong.getArtist();
String artist = currentPlaying == null ? null : currentPlaying.getArtist(); String album = currentSong == null ? null : currentSong.getAlbum();
String album = currentPlaying == null ? null : currentPlaying.getAlbum();
CharSequence errorState = null; CharSequence errorState = null;
// Show error message? // Show error message?
@ -117,7 +117,7 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider
{ {
errorState = res.getText(R.string.widget_sdcard_missing); errorState = res.getText(R.string.widget_sdcard_missing);
} }
else if (currentPlaying == null) else if (currentSong == null)
{ {
errorState = res.getText(R.string.widget_initial_text); errorState = res.getText(R.string.widget_initial_text);
} }
@ -157,7 +157,7 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider
// Set the cover art // Set the cover art
try try
{ {
Bitmap bitmap = currentPlaying == null ? null : FileUtil.getAlbumArtBitmap(context, currentPlaying, 240, true); Bitmap bitmap = currentSong == null ? null : FileUtil.getAlbumArtBitmap(context, currentSong, 240, true);
if (bitmap == null) if (bitmap == null)
{ {
@ -176,7 +176,7 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider
} }
// Link actions buttons to intents // Link actions buttons to intents
linkButtons(context, views, currentPlaying != null); linkButtons(context, views, currentSong != null);
pushUpdate(context, appWidgetIds, views); pushUpdate(context, appWidgetIds, views);
} }
@ -200,19 +200,19 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider
// Emulate media button clicks. // Emulate media button clicks.
intent = new Intent("1"); intent = new Intent("1");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_play, pendingIntent); views.setOnClickPendingIntent(R.id.control_play, pendingIntent);
intent = new Intent("2"); // Use a unique action name to ensure a different PendingIntent to be created. intent = new Intent("2"); // Use a unique action name to ensure a different PendingIntent to be created.
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_next, pendingIntent); views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
intent = new Intent("3"); // Use a unique action name to ensure a different PendingIntent to be created. intent = new Intent("3"); // Use a unique action name to ensure a different PendingIntent to be created.
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent); views.setOnClickPendingIntent(R.id.control_previous, pendingIntent);

View File

@ -25,9 +25,9 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable; import android.os.Parcelable;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent;
import org.moire.ultrasonic.service.DownloadServiceImpl; import org.moire.ultrasonic.service.DownloadServiceImpl;
import org.moire.ultrasonic.service.MediaPlayerService;
import org.moire.ultrasonic.util.Util; import org.moire.ultrasonic.util.Util;
/** /**
@ -57,42 +57,23 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver
Parcelable event = (Parcelable) extras.get(Intent.EXTRA_KEY_EVENT); Parcelable event = (Parcelable) extras.get(Intent.EXTRA_KEY_EVENT);
Log.i(TAG, "Got MEDIA_BUTTON key event: " + event); Log.i(TAG, "Got MEDIA_BUTTON key event: " + event);
Intent serviceIntent = new Intent(context, DownloadServiceImpl.class); Intent serviceIntent = new Intent(context, MediaPlayerService.class);
serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event); serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
try try
{ {
context.startService(serviceIntent); if (DownloadServiceImpl.getInstance() == null) new DownloadServiceImpl(context);
} DownloadServiceImpl.getInstance().onCommand(serviceIntent);
catch (IllegalStateException exception)
{
Log.i(TAG, "MediaButtonIntentReceiver couldn't start DownloadServiceImpl because the application was in the background.");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN && keyEvent.getRepeatCount() == 0)
{
int keyCode = keyEvent.getKeyCode();
if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
keyCode == KeyEvent.KEYCODE_MEDIA_PLAY)
{
// TODO: The only time it is OK to start DownloadServiceImpl as a foreground service is when we now it will display its notification.
// When DownloadServiceImpl is refactored to a proper foreground service, this can be removed.
context.startForegroundService(serviceIntent);
Log.i(TAG, "MediaButtonIntentReceiver started DownloadServiceImpl as foreground service");
}
}
}
}
try
{
if (isOrderedBroadcast()) if (isOrderedBroadcast())
{ {
abortBroadcast(); abortBroadcast();
} }
} }
catch (IllegalStateException exception)
{
Log.w(TAG, "MediaButtonIntentReceiver couldn't start DownloadServiceImpl because the application was in the background.");
}
catch (Exception x) catch (Exception x)
{ {
// Ignored. // Ignored.

View File

@ -441,10 +441,7 @@ public class DownloadFile
new CacheCleaner(context, DownloadServiceImpl.getInstance()).cleanSpace(); new CacheCleaner(context, DownloadServiceImpl.getInstance()).cleanSpace();
if (DownloadServiceImpl.getInstance() != null) MediaPlayerService.checkDownloads(context);
{
((DownloadServiceImpl) DownloadServiceImpl.getInstance()).checkDownloads();
}
} }
} }

View File

@ -67,6 +67,7 @@ public class DownloadServiceLifecycleSupport
private boolean externalStorageAvailable = true; private boolean externalStorageAvailable = true;
private Lock lock = new ReentrantLock(); private Lock lock = new ReentrantLock();
private final AtomicBoolean setup = new AtomicBoolean(false); private final AtomicBoolean setup = new AtomicBoolean(false);
private Context context;
/** /**
* This receiver manages the intent that could come from other applications. * This receiver manages the intent that could come from other applications.
@ -107,9 +108,10 @@ public class DownloadServiceLifecycleSupport
}; };
public DownloadServiceLifecycleSupport(DownloadServiceImpl downloadService) public DownloadServiceLifecycleSupport(Context context, DownloadServiceImpl downloadService)
{ {
this.downloadService = downloadService; this.downloadService = downloadService;
this.context = context;
} }
public void onCreate() public void onCreate()
@ -121,7 +123,7 @@ public class DownloadServiceLifecycleSupport
{ {
try try
{ {
downloadService.checkDownloads(); MediaPlayerService.checkDownloads(context);
} }
catch (Throwable x) catch (Throwable x)
{ {
@ -156,10 +158,10 @@ public class DownloadServiceLifecycleSupport
IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT); IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT);
ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
ejectFilter.addDataScheme("file"); ejectFilter.addDataScheme("file");
downloadService.registerReceiver(ejectEventReceiver, ejectFilter); context.registerReceiver(ejectEventReceiver, ejectFilter);
// React to media buttons. // React to media buttons.
Util.registerMediaButtonEventReceiver(downloadService); Util.registerMediaButtonEventReceiver(context);
// Pause temporarily on incoming phone calls. // Pause temporarily on incoming phone calls.
//phoneStateListener = new MyPhoneStateListener(); //phoneStateListener = new MyPhoneStateListener();
@ -174,20 +176,20 @@ public class DownloadServiceLifecycleSupport
commandFilter.addAction(DownloadServiceImpl.CMD_STOP); commandFilter.addAction(DownloadServiceImpl.CMD_STOP);
commandFilter.addAction(DownloadServiceImpl.CMD_PREVIOUS); commandFilter.addAction(DownloadServiceImpl.CMD_PREVIOUS);
commandFilter.addAction(DownloadServiceImpl.CMD_NEXT); commandFilter.addAction(DownloadServiceImpl.CMD_NEXT);
downloadService.registerReceiver(intentReceiver, commandFilter); context.registerReceiver(intentReceiver, commandFilter);
int instance = Util.getActiveServer(downloadService); int instance = Util.getActiveServer(context);
downloadService.setJukeboxEnabled(Util.getJukeboxEnabled(downloadService, instance)); downloadService.setJukeboxEnabled(Util.getJukeboxEnabled(context, instance));
deserializeDownloadQueue(); deserializeDownloadQueue();
new CacheCleaner(downloadService, downloadService).clean(); new CacheCleaner(context, downloadService).clean();
} }
private void registerHeadsetReceiver() { private void registerHeadsetReceiver() {
// Pause when headset is unplugged. // Pause when headset is unplugged.
final SharedPreferences sp = Util.getPreferences(downloadService); final SharedPreferences sp = Util.getPreferences(context);
final String spKey = downloadService final String spKey = context
.getString(R.string.settings_playback_resume_play_on_headphones_plug); .getString(R.string.settings_playback_resume_play_on_headphones_plug);
headsetEventReceiver = new BroadcastReceiver() { headsetEventReceiver = new BroadcastReceiver() {
@ -218,7 +220,7 @@ public class DownloadServiceLifecycleSupport
IntentFilter headsetIntentFilter = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) ? IntentFilter headsetIntentFilter = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) ?
new IntentFilter(AudioManager.ACTION_HEADSET_PLUG) : new IntentFilter(AudioManager.ACTION_HEADSET_PLUG) :
new IntentFilter(Intent.ACTION_HEADSET_PLUG); new IntentFilter(Intent.ACTION_HEADSET_PLUG);
downloadService.registerReceiver(headsetEventReceiver, headsetIntentFilter); context.registerReceiver(headsetEventReceiver, headsetIntentFilter);
} }
public void onStart(Intent intent) public void onStart(Intent intent)
@ -238,12 +240,9 @@ public class DownloadServiceLifecycleSupport
executorService.shutdown(); executorService.shutdown();
serializeDownloadQueueNow(); serializeDownloadQueueNow();
downloadService.clear(false); downloadService.clear(false);
downloadService.unregisterReceiver(ejectEventReceiver); context.unregisterReceiver(ejectEventReceiver);
downloadService.unregisterReceiver(headsetEventReceiver); context.unregisterReceiver(headsetEventReceiver);
downloadService.unregisterReceiver(intentReceiver); context.unregisterReceiver(intentReceiver);
//TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
//telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
} }
public boolean isExternalStorageAvailable() public boolean isExternalStorageAvailable()
@ -273,7 +272,7 @@ public class DownloadServiceLifecycleSupport
state.currentPlayingPosition = downloadService.getPlayerPosition(); state.currentPlayingPosition = downloadService.getPlayerPosition();
Log.i(TAG, String.format("Serialized currentPlayingIndex: %d, currentPlayingPosition: %d", state.currentPlayingIndex, state.currentPlayingPosition)); Log.i(TAG, String.format("Serialized currentPlayingIndex: %d, currentPlayingPosition: %d", state.currentPlayingIndex, state.currentPlayingPosition));
FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER); FileUtil.serialize(context, state, FILENAME_DOWNLOADS_SER);
} }
private void deserializeDownloadQueue() private void deserializeDownloadQueue()
@ -283,7 +282,7 @@ public class DownloadServiceLifecycleSupport
private void deserializeDownloadQueueNow() private void deserializeDownloadQueueNow()
{ {
State state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER); State state = FileUtil.deserialize(context, FILENAME_DOWNLOADS_SER);
if (state == null) if (state == null)
{ {
return; return;

View File

@ -67,6 +67,7 @@ public class JukeboxService
private VolumeToast volumeToast; private VolumeToast volumeToast;
private AtomicBoolean running = new AtomicBoolean(); private AtomicBoolean running = new AtomicBoolean();
private Thread serviceThread; private Thread serviceThread;
private Context context;
// TODO: Report warning if queue fills up. // TODO: Report warning if queue fills up.
// TODO: Create shutdown method? // TODO: Create shutdown method?
@ -74,8 +75,9 @@ public class JukeboxService
// TODO: Persist RC state? // TODO: Persist RC state?
// TODO: Minimize status updates. // TODO: Minimize status updates.
public JukeboxService(DownloadServiceImpl downloadService) public JukeboxService(Context context, DownloadServiceImpl downloadService)
{ {
this.context = context;
this.downloadService = downloadService; this.downloadService = downloadService;
} }
@ -149,7 +151,7 @@ public class JukeboxService
try try
{ {
if (!Util.isOffline(downloadService)) if (!Util.isOffline(context))
{ {
task = tasks.take(); task = tasks.take();
JukeboxStatus status = task.execute(); JukeboxStatus status = task.execute();
@ -212,7 +214,7 @@ public class JukeboxService
@Override @Override
public void run() public void run()
{ {
Util.toast(downloadService, resourceId, false); Util.toast(context, resourceId, false);
} }
}); });
@ -282,14 +284,14 @@ public class JukeboxService
if (volumeToast == null) if (volumeToast == null)
{ {
volumeToast = new VolumeToast(downloadService); volumeToast = new VolumeToast(context);
} }
volumeToast.setVolume(gain); volumeToast.setVolume(gain);
} }
private MusicService getMusicService() private MusicService getMusicService()
{ {
return MusicServiceFactory.getMusicService(downloadService); return MusicServiceFactory.getMusicService(context);
} }
public int getPositionSeconds() public int getPositionSeconds()
@ -380,7 +382,7 @@ public class JukeboxService
@Override @Override
JukeboxStatus execute() throws Exception JukeboxStatus execute() throws Exception
{ {
return getMusicService().getJukeboxStatus(downloadService, null); return getMusicService().getJukeboxStatus(context, null);
} }
} }
@ -396,7 +398,7 @@ public class JukeboxService
@Override @Override
JukeboxStatus execute() throws Exception JukeboxStatus execute() throws Exception
{ {
return getMusicService().updateJukeboxPlaylist(ids, downloadService, null); return getMusicService().updateJukeboxPlaylist(ids, context, null);
} }
} }
@ -414,7 +416,7 @@ public class JukeboxService
@Override @Override
JukeboxStatus execute() throws Exception JukeboxStatus execute() throws Exception
{ {
return getMusicService().skipJukebox(index, offsetSeconds, downloadService, null); return getMusicService().skipJukebox(index, offsetSeconds, context, null);
} }
} }
@ -423,7 +425,7 @@ public class JukeboxService
@Override @Override
JukeboxStatus execute() throws Exception JukeboxStatus execute() throws Exception
{ {
return getMusicService().stopJukebox(downloadService, null); return getMusicService().stopJukebox(context, null);
} }
} }
@ -432,7 +434,7 @@ public class JukeboxService
@Override @Override
JukeboxStatus execute() throws Exception JukeboxStatus execute() throws Exception
{ {
return getMusicService().startJukebox(downloadService, null); return getMusicService().startJukebox(context, null);
} }
} }
@ -449,7 +451,7 @@ public class JukeboxService
@Override @Override
JukeboxStatus execute() throws Exception JukeboxStatus execute() throws Exception
{ {
return getMusicService().setJukeboxGain(gain, downloadService, null); return getMusicService().setJukeboxGain(gain, context, null);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
package org.moire.ultrasonic.service;
public abstract class Supplier<T>
{
public abstract T get();
}

View File

@ -4,7 +4,7 @@ import android.util.Log;
import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.MusicDirectory;
import org.moire.ultrasonic.service.DownloadFile; import org.moire.ultrasonic.service.DownloadFile;
import org.moire.ultrasonic.service.DownloadService; import org.moire.ultrasonic.service.Supplier;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -32,9 +32,9 @@ public class StreamProxy implements Runnable
private boolean isRunning; private boolean isRunning;
private ServerSocket socket; private ServerSocket socket;
private int port; private int port;
private DownloadService downloadService; private Supplier<DownloadFile> currentPlaying;
public StreamProxy(DownloadService downloadService) public StreamProxy(Supplier<DownloadFile> currentPlaying)
{ {
// Create listening socket // Create listening socket
@ -43,7 +43,7 @@ public class StreamProxy implements Runnable
socket = new ServerSocket(0, 0, InetAddress.getByAddress(new byte[]{127, 0, 0, 1})); socket = new ServerSocket(0, 0, InetAddress.getByAddress(new byte[]{127, 0, 0, 1}));
socket.setSoTimeout(5000); socket.setSoTimeout(5000);
port = socket.getLocalPort(); port = socket.getLocalPort();
this.downloadService = downloadService; this.currentPlaying = currentPlaying;
} }
catch (UnknownHostException e) catch (UnknownHostException e)
{ // impossible { // impossible
@ -170,7 +170,7 @@ public class StreamProxy implements Runnable
public void run() public void run()
{ {
Log.i(TAG, "Streaming song in background"); Log.i(TAG, "Streaming song in background");
DownloadFile downloadFile = downloadService.getCurrentPlaying(); DownloadFile downloadFile = currentPlaying.get();
MusicDirectory.Entry song = downloadFile.getSong(); MusicDirectory.Entry song = downloadFile.getSong();
long fileSize = downloadFile.getBitRate() * ((song.getDuration() != null) ? song.getDuration() : 0) * 1000 / 8; long fileSize = downloadFile.getBitRate() * ((song.getDuration() != null) ? song.getDuration() : 0) * 1000 / 8;
Log.i(TAG, String.format("Streaming fileSize: %d", fileSize)); Log.i(TAG, String.format("Streaming fileSize: %d", fileSize));

View File

@ -56,6 +56,7 @@ import org.moire.ultrasonic.receiver.MediaButtonIntentReceiver;
import org.moire.ultrasonic.service.DownloadFile; import org.moire.ultrasonic.service.DownloadFile;
import org.moire.ultrasonic.service.DownloadService; import org.moire.ultrasonic.service.DownloadService;
import org.moire.ultrasonic.service.DownloadServiceImpl; import org.moire.ultrasonic.service.DownloadServiceImpl;
import org.moire.ultrasonic.service.MediaPlayerService;
import org.moire.ultrasonic.service.MusicServiceFactory; import org.moire.ultrasonic.service.MusicServiceFactory;
import java.io.*; import java.io.*;
@ -1045,38 +1046,31 @@ public class Util extends DownloadActivity
context.sendBroadcast(avrcpIntent); context.sendBroadcast(avrcpIntent);
} }
public static void broadcastA2dpPlayStatusChange(Context context, PlayerState state, DownloadService downloadService) public static void broadcastA2dpPlayStatusChange(Context context, PlayerState state, Entry currentSong, Integer listSize, Integer id, Integer playerPosition)
{ {
if (!Util.getShouldSendBluetoothNotifications(context) || downloadService == null) if (!Util.getShouldSendBluetoothNotifications(context))
{ {
return; return;
} }
DownloadFile currentPlaying = downloadService.getCurrentPlaying(); if (currentSong != null)
if (currentPlaying != null)
{ {
Intent avrcpIntent = new Intent(CM_AVRCP_PLAYSTATE_CHANGED); Intent avrcpIntent = new Intent(CM_AVRCP_PLAYSTATE_CHANGED);
Entry song = currentPlaying.getSong(); if (currentSong == null)
if (song == null)
{ {
return; return;
} }
if (song != currentSong) if (currentSong != currentSong)
{ {
currentSong = song; Util.currentSong = currentSong;
} }
String title = song.getTitle(); String title = currentSong.getTitle();
String artist = song.getArtist(); String artist = currentSong.getArtist();
String album = song.getAlbum(); String album = currentSong.getAlbum();
Integer duration = song.getDuration(); Integer duration = currentSong.getDuration();
Integer listSize = downloadService.getDownloads().size();
Integer id = downloadService.getCurrentPlayingIndex() + 1;
Integer playerPosition = downloadService.getPlayerPosition();
avrcpIntent.putExtra("track", title); avrcpIntent.putExtra("track", title);
avrcpIntent.putExtra("track_name", title); avrcpIntent.putExtra("track_name", title);
@ -1089,7 +1083,7 @@ public class Util extends DownloadActivity
if (Util.getShouldSendBluetoothAlbumArt(context)) if (Util.getShouldSendBluetoothAlbumArt(context))
{ {
File albumArtFile = FileUtil.getAlbumArtFile(context, song); File albumArtFile = FileUtil.getAlbumArtFile(context, currentSong);
avrcpIntent.putExtra("coverart", albumArtFile.getAbsolutePath()); avrcpIntent.putExtra("coverart", albumArtFile.getAbsolutePath());
avrcpIntent.putExtra("cover", albumArtFile.getAbsolutePath()); avrcpIntent.putExtra("cover", albumArtFile.getAbsolutePath());
} }
@ -1290,55 +1284,55 @@ public class Util extends DownloadActivity
// Emulate media button clicks. // Emulate media button clicks.
intent = new Intent("1"); intent = new Intent("1");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_play, pendingIntent); views.setOnClickPendingIntent(R.id.control_play, pendingIntent);
intent = new Intent("2"); intent = new Intent("2");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_next, pendingIntent); views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
intent = new Intent("3"); intent = new Intent("3");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent); views.setOnClickPendingIntent(R.id.control_previous, pendingIntent);
intent = new Intent("4"); intent = new Intent("4");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_STOP)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_STOP));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_stop, pendingIntent); views.setOnClickPendingIntent(R.id.control_stop, pendingIntent);
intent = new Intent("RATE_1"); intent = new Intent("RATE_1");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_1)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_1));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.notification_five_star_1, pendingIntent); views.setOnClickPendingIntent(R.id.notification_five_star_1, pendingIntent);
intent = new Intent("RATE_2"); intent = new Intent("RATE_2");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_2)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_2));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.notification_five_star_2, pendingIntent); views.setOnClickPendingIntent(R.id.notification_five_star_2, pendingIntent);
intent = new Intent("RATE_3"); intent = new Intent("RATE_3");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_3)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_3));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.notification_five_star_3, pendingIntent); views.setOnClickPendingIntent(R.id.notification_five_star_3, pendingIntent);
intent = new Intent("RATE_4"); intent = new Intent("RATE_4");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_4)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_4));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.notification_five_star_4, pendingIntent); views.setOnClickPendingIntent(R.id.notification_five_star_4, pendingIntent);
intent = new Intent("RATE_5"); intent = new Intent("RATE_5");
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); intent.setComponent(new ComponentName(context, MediaPlayerService.class));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_5)); intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_5));
pendingIntent = PendingIntent.getService(context, 0, intent, 0); pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.notification_five_star_5, pendingIntent); views.setOnClickPendingIntent(R.id.notification_five_star_5, pendingIntent);