Improve lock screen reliability, add 4.3 specific lockscreen features, add scanning of media after download, improve image caching

This commit is contained in:
Joshua Bahnsen 2014-01-20 23:16:24 -07:00
parent d4227b460f
commit 2b7ce9cb2c
12 changed files with 319 additions and 196 deletions

View File

@ -372,6 +372,8 @@
<string name="settings.show_all_songs_by_artist">Voir toutes les titres par artiste</string>
<string name="settings.show_all_songs_by_artist_summary">Ajouter une nouvelle entrée de l\'affichage de l\'artiste pour accéder à toutes les titres pour un artiste</string>
<string name="download.menu_show_artist">Afficher l\'artiste</string>
<string name="settings.scan_media">Scan Media After Download</string>
<string name="settings.scan_media_summary">Automatically scan media after download</string>
<plurals name="select_album_n_songs">
<item quantity="zero">Aucun titre</item>

View File

@ -372,6 +372,8 @@
<string name="settings.show_all_songs_by_artist">Az előadó összes dalának megjelenítése</string>
<string name="settings.show_all_songs_by_artist_summary">Új bejegyzés hozzáadása az előadóhoz, az előadó összes dalának eléréséhez.</string>
<string name="download.menu_show_artist">Ugrás az előadóhoz</string>
<string name="settings.scan_media">Scan Media After Download</string>
<string name="settings.scan_media_summary">Automatically scan media after download</string>
<plurals name="select_album_n_songs">
<item quantity="zero">Nincsenek dalok</item>

View File

@ -372,6 +372,8 @@
<string name="settings.show_all_songs_by_artist">Show All Songs By Artist</string>
<string name="settings.show_all_songs_by_artist_summary">Add new entry in artist view to access all songs for an artist</string>
<string name="download.menu_show_artist">Show Artist</string>
<string name="settings.scan_media">Scan Media After Download</string>
<string name="settings.scan_media_summary">Automatically scan media after download</string>
<plurals name="select_album_n_songs">
<item quantity="zero">No songs</item>

View File

@ -83,6 +83,11 @@
a:key="clearBookmark"
a:summary="@string/settings.clear_bookmark_summary"
a:title="@string/settings.clear_bookmark"/>
<CheckBoxPreference
a:defaultValue="false"
a:key="scanMedia"
a:summary="@string/settings.scan_media_summary"
a:title="@string/settings.scan_media"/>
<ListPreference
a:defaultValue="5000"
a:entries="@array/bufferLengthNames"

View File

@ -957,7 +957,7 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
}
}
protected synchronized ImageLoader getImageLoader()
public synchronized ImageLoader getImageLoader()
{
if (IMAGE_LOADER == null)
{

View File

@ -297,11 +297,9 @@ public class DownloadFile
private class DownloadTask extends CancellableTask
{
@Override
public void execute()
{
InputStream in = null;
FileOutputStream out = null;
PowerManager.WakeLock wakeLock = null;
@ -417,19 +415,29 @@ public class DownloadFile
{
Util.renameFile(partialFile, saveFile);
mediaStoreService.saveInMediaStore(DownloadFile.this);
if (Util.getShouldScanMedia(context))
{
Util.scanMedia(context, saveFile);
}
}
else
{
Util.renameFile(partialFile, completeFile);
}
}
if (Util.getShouldScanMedia(context))
{
Util.scanMedia(context, completeFile);
}
}
}
}
catch (Exception x)
{
Util.close(out);
Util.delete(completeFile);
Util.delete(saveFile);
if (!isCancelled())
{
failed = true;
@ -450,7 +458,9 @@ public class DownloadFile
{
wifiLock.release();
}
new CacheCleaner(context, DownloadServiceImpl.getInstance()).cleanSpace();
if (DownloadServiceImpl.getInstance() != null)
{
((DownloadServiceImpl) DownloadServiceImpl.getInstance()).checkDownloads();

View File

@ -136,7 +136,6 @@ public class DownloadServiceImpl extends Service implements DownloadService
private boolean jukeboxEnabled;
private PositionCache positionCache;
private StreamProxy proxy;
private static MusicDirectory.Entry currentSong;
private RemoteControlClient remoteControlClient;
private AudioManager audioManager;
private int secondaryProgress = -1;
@ -220,6 +219,11 @@ public class DownloadServiceImpl extends Service implements DownloadService
audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
if (Util.isLockScreenEnabled(this))
{
setUpRemoteControlClient();
}
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
notification.contentView = new RemoteViews(this.getPackageName(), R.layout.notification);
Util.linkButtons(this, notification.contentView, false);
@ -275,6 +279,8 @@ public class DownloadServiceImpl extends Service implements DownloadService
{
super.onDestroy();
try
{
instance = null;
lifecycleSupport.onDestroy();
mediaPlayer.release();
@ -291,23 +297,12 @@ public class DownloadServiceImpl extends Service implements DownloadService
{
equalizerController.release();
}
if (visualizerController != null)
{
visualizerController.release();
}
try
{
Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mediaPlayer.getAudioSessionId());
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
sendBroadcast(i);
}
catch (Throwable e)
{
// Froyo or lower
}
if (bufferTask != null)
{
bufferTask.cancel();
@ -318,8 +313,20 @@ public class DownloadServiceImpl extends Service implements DownloadService
nextPlayingTask.cancel();
}
audioManager.unregisterRemoteControlClient(remoteControlClient);
notification = null;
Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mediaPlayer.getAudioSessionId());
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
sendBroadcast(i);
audioManager.unregisterRemoteControlClient(remoteControlClient);
wakeLock.release();
}
catch (Throwable ignored)
{
}
}
public static DownloadService getInstance()
@ -958,6 +965,8 @@ public class DownloadServiceImpl extends Service implements DownloadService
{
mediaPlayer.seekTo(position);
cachedPosition = position;
updateRemoteControl();
}
}
catch (Exception x)
@ -1213,8 +1222,11 @@ public class DownloadServiceImpl extends Service implements DownloadService
Util.broadcastPlaybackStatusChange(this, this.playerState);
Util.broadcastA2dpPlayStatusChange(this, this.playerState, instance);
if (this.playerState == PlayerState.STARTED || this.playerState == PlayerState.PAUSED)
{
// Set remote control
updateRemoteControl();
}
// Update widget
UltraSonicAppWidgetProvider4x1.getInstance().notifyChange(this, this, this.playerState == PlayerState.STARTED, false);
@ -1423,27 +1435,59 @@ public class DownloadServiceImpl extends Service implements DownloadService
jukeboxService.adjustVolume(up);
}
private void updateRemoteControl()
@SuppressLint("NewApi")
private void setUpRemoteControlClient()
{
if (Util.isLockScreenEnabled(this))
{
if (remoteControlClient == null)
{
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.setComponent(new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName()));
remoteControlClient = new RemoteControlClient(PendingIntent.getBroadcast(this, 0, intent, 0));
remoteControlClient.setTransportControlFlags(RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS |
RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE |
RemoteControlClient.FLAG_KEY_MEDIA_STOP);
final Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setComponent(new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName()));
remoteControlClient = new RemoteControlClient(PendingIntent.getBroadcast(this, 0, mediaButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT));
audioManager.registerRemoteControlClient(remoteControlClient);
// Flags for the media transport control that this client supports.
int flags = RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS | RemoteControlClient.FLAG_KEY_MEDIA_NEXT | RemoteControlClient.FLAG_KEY_MEDIA_PLAY | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_STOP;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
{
flags |= RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE;
remoteControlClient.setOnGetPlaybackPositionListener(new RemoteControlClient.OnGetPlaybackPositionListener()
{
@Override
public long onGetPlaybackPosition()
{
return mediaPlayer.getCurrentPosition();
}
});
remoteControlClient.setPlaybackPositionUpdateListener(new RemoteControlClient.OnPlaybackPositionUpdateListener()
{
@Override
public void onPlaybackPositionUpdate(long newPositionMs)
{
seekTo((int) newPositionMs);
}
});
}
remoteControlClient.setTransportControlFlags(flags);
}
private void updateRemoteControl()
{
if (!Util.isLockScreenEnabled(this))
{
if (remoteControlClient != null)
{
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
audioManager.unregisterRemoteControlClient(remoteControlClient);
remoteControlClient = null;
}
return;
}
//try
//{
Log.i(TAG, String.format("In updateRemoteControl, playerState: %s [%d]", playerState, getPlayerPosition()));
switch (playerState)
@ -1455,74 +1499,60 @@ public class DownloadServiceImpl extends Service implements DownloadService
}
else
{
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING, getPlayerPosition(), 1);
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING, getPlayerPosition(), 1.0f);
}
break;
case PAUSED:
default:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
{
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
}
else
{
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED, getPlayerPosition(), 1);
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED, getPlayerPosition(), 1.0f);
}
break;
case DOWNLOADING:
case PREPARING:
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_BUFFERING);
break;
case IDLE:
case COMPLETED:
case PREPARED:
case STOPPED:
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
break;
default:
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
break;
// case DOWNLOADING:
// case PREPARING:
// remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_BUFFERING);
// break;
// case IDLE:
// case COMPLETED:
// case PREPARED:
// case STOPPED:
// remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
// break;
// default:
// remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
// break;
}
try
{
if (currentPlaying != null)
{
Bitmap lockScreenBitmap;
if (currentSong != currentPlaying.getSong())
{
currentSong = currentPlaying.getSong();
lockScreenBitmap = FileUtil.getAlbumArtBitmap(this, currentSong, lockScreenBitmapSize, true);
}
else
{
return;
}
MusicDirectory.Entry currentSong = currentPlaying.getSong();
Bitmap lockScreenBitmap = FileUtil.getAlbumArtBitmap(this, currentSong, 0, true);
String artist = currentSong.getArtist();
String album = currentSong.getAlbum();
String title = String.format("%s - %s", artist, currentSong.getTitle());
String title = currentSong.getTitle();
Long duration = (long) currentSong.getDuration() * 1000;
remoteControlClient.editMetadata(true).putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, artist).putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, artist).putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, album).putString(MediaMetadataRetriever.METADATA_KEY_TITLE, title).putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration).putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, lockScreenBitmap).apply();
// Update the remote controls
remoteControlClient.editMetadata(true).putString(MediaMetadataRetriever.METADATA_KEY_TITLE, title).putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, artist).putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, album).apply();
remoteControlClient.editMetadata(false).putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, lockScreenBitmap).apply();
remoteControlClient.editMetadata(false).putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration).apply();
}
}
catch (Exception e)
{
Log.e(TAG, "Exception in updateRemoteControl", e);
}
}
else
{
if (remoteControlClient != null)
{
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
audioManager.unregisterRemoteControlClient(remoteControlClient);
remoteControlClient = null;
}
//remoteControlClient.editMetadata(true).putString(MediaMetadataRetriever.METADATA_KEY_TITLE, title).putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, artist).putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, artist).putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, album).apply();
//remoteControlClient.editMetadata(false).putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, lockScreenBitmap).apply();
//remoteControlClient.editMetadata(false).putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration).apply();
}
//}
//catch (Exception e)
//{
//Log.e(TAG, "Exception in updateRemoteControl", e);
//}
}
private synchronized void bufferAndPlay()
@ -1591,7 +1621,7 @@ public class DownloadServiceImpl extends Service implements DownloadService
SeekBar progressBar = DownloadActivity.getProgressBar();
MusicDirectory.Entry song = downloadFile.getSong();
if (progressBar != null && song.getTranscodedContentType() == null && Util.getMaxBitRate(getApplicationContext()) == 0)
if (progressBar != null && song.getTranscodedContentType() == null && Util.getMaxBitRate(DownloadServiceImpl.this) == 0)
{
secondaryProgress = (int) (((double) percent / (double) 100) * progressBar.getMax());
progressBar.setSecondaryProgress(secondaryProgress);
@ -1621,7 +1651,7 @@ public class DownloadServiceImpl extends Service implements DownloadService
if (position != 0)
{
Log.i(TAG, String.format("Restarting player from position %d", position));
mediaPlayer.seekTo(position);
seekTo(position);
}
cachedPosition = position;
@ -1947,6 +1977,11 @@ public class DownloadServiceImpl extends Service implements DownloadService
DownloadFile downloadFile = backgroundDownloadList.get(i);
if (downloadFile.isWorkDone() && (!downloadFile.shouldSave() || downloadFile.isSaved()))
{
if (Util.getShouldScanMedia(this))
{
Util.scanMedia(this, downloadFile.getCompleteFile());
}
// Don't need to keep list like active song list
backgroundDownloadList.remove(i);
revision++;

View File

@ -38,10 +38,12 @@ import java.util.List;
public class IndexesParser extends AbstractParser
{
private static final String TAG = IndexesParser.class.getSimpleName();
private Context context;
public IndexesParser(Context context)
{
super(context);
this.context = context;
}
public Indexes parse(Reader reader, ProgressListener progressListener) throws Exception
@ -87,7 +89,7 @@ public class IndexesParser extends AbstractParser
if (artists.size() % 10 == 0)
{
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
String msg = this.context.getResources().getString(R.string.parser_artist_count, artists.size());
updateProgress(progressListener, msg);
}
}
@ -116,7 +118,7 @@ public class IndexesParser extends AbstractParser
long t1 = System.currentTimeMillis();
Log.d(TAG, "Got " + artists.size() + " artist(s) in " + (t1 - t0) + "ms.");
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
String msg = this.context.getResources().getString(R.string.parser_artist_count, artists.size());
updateProgress(progressListener, msg);
return new Indexes(lastModified == null ? 0L : lastModified, ignoredArticles, shortcuts, artists);

View File

@ -127,6 +127,7 @@ public final class Constants
public static final String PREFERENCES_KEY_DEFAULT_SHARE_GREETING = "sharingDefaultGreeting";
public static final String PREFERENCES_KEY_DEFAULT_SHARE_EXPIRATION = "sharingDefaultExpiration";
public static final String PREFERENCES_KEY_SHOW_ALL_SONGS_BY_ARTIST = "showAllSongsByArtist";
public static final String PREFERENCES_KEY_SCAN_MEDIA = "scanMedia";
// Name of the preferences file.
public static final String PREFERENCES_FILE_NAME = "com.thejoshwa.ultrasonic.androidapp_preferences";

View File

@ -24,6 +24,7 @@ import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;
import com.thejoshwa.ultrasonic.androidapp.activity.SubsonicTabActivity;
import com.thejoshwa.ultrasonic.androidapp.domain.Artist;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
@ -125,8 +126,17 @@ public class FileUtil
public static Bitmap getAlbumArtBitmap(Context context, MusicDirectory.Entry entry, int size, boolean highQuality)
{
if (entry == null) return null;
File albumArtFile = getAlbumArtFile(context, entry);
Bitmap bitmap = SubsonicTabActivity.getInstance().getImageLoader().getImageBitmap(entry, true, size);
if (bitmap != null)
{
return bitmap.copy(bitmap.getConfig(), false);
}
if (albumArtFile != null && albumArtFile.exists())
{
final BitmapFactory.Options opt = new BitmapFactory.Options();
@ -147,9 +157,14 @@ public class FileUtil
opt.inJustDecodeBounds = false;
}
Bitmap bitmap = BitmapFactory.decodeFile(albumArtFile.getPath(), opt);
bitmap = BitmapFactory.decodeFile(albumArtFile.getPath(), opt);
Log.i("getAlbumArtBitmap", String.valueOf(size));
if (bitmap != null)
{
SubsonicTabActivity.getInstance().getImageLoader().addImageToCache(bitmap, entry, size);
}
return bitmap == null ? null : bitmap;
}

View File

@ -131,7 +131,37 @@ public class ImageLoader implements Runnable
private static String getKey(String coverArtId, int size)
{
return coverArtId + size;
return coverArtId + ":" + size;
}
public Bitmap getImageBitmap(MusicDirectory.Entry entry, boolean large, int size)
{
if (entry == null)
{
return null;
}
String coverArt = entry.getCoverArt();
if (coverArt == null)
{
return null;
}
if (size <= 0)
{
size = large ? imageSizeLarge : imageSizeDefault;
}
Bitmap bitmap = cache.get(getKey(coverArt, size));
if (bitmap != null)
{
Bitmap.Config config = bitmap.getConfig();
return bitmap.copy(config, false);
}
return null;
}
private void setImageBitmap(View view, Bitmap bitmap, boolean crossFade)
@ -183,6 +213,11 @@ public class ImageLoader implements Runnable
}
}
public void addImageToCache(Bitmap bitmap, MusicDirectory.Entry entry, int size)
{
cache.put(getKey(entry.getCoverArt(), size), bitmap);
}
public void clear()
{
queue.clear();
@ -233,7 +268,7 @@ public class ImageLoader implements Runnable
MusicService musicService = MusicServiceFactory.getMusicService(view.getContext());
final Bitmap bitmap = musicService.getCoverArt(view.getContext(), entry, size, saveToFile, highQuality, null);
cache.put(getKey(entry.getCoverArt(), size), bitmap);
addImageToCache(bitmap, entry, size);
handler.post(new Runnable()
{

View File

@ -37,6 +37,7 @@ import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.Parcelable;
@ -1611,4 +1612,17 @@ public class Util extends DownloadActivity
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SHOW_ALL_SONGS_BY_ARTIST, false);
}
public static boolean getShouldScanMedia(Context context)
{
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SCAN_MEDIA, false);
}
public static void scanMedia(Context context, File file)
{
Uri uri = Uri.fromFile(file);
Intent scanFileIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
context.sendBroadcast(scanFileIntent);
}
}