Revert to using Bitmaps and a cache for cover art instead of URIs
While storing a Bitmap in a Bundle for RemoteViews seems to be spectacularly slow, using URIs to prevent this does not seem to be worth the additional disk I/O they incur.
This commit is contained in:
parent
0866b50ac4
commit
0f54cb6242
@ -216,7 +216,6 @@ public final class CoverBitmap {
|
||||
int y = (bitmapHeight - coverHeight) / 2;
|
||||
Rect rect = new Rect(x, y, x + coverWidth, y + coverHeight);
|
||||
canvas.drawBitmap(cover, null, rect, paint);
|
||||
cover.recycle();
|
||||
}
|
||||
|
||||
int left = (bitmapWidth - boxWidth) / 2;
|
||||
@ -313,7 +312,6 @@ public final class CoverBitmap {
|
||||
int y = horizontal ? (bitmapHeight - coverHeight) / 2 : 0;
|
||||
Rect rect = new Rect(x, y, x + coverWidth, y + coverHeight);
|
||||
canvas.drawBitmap(cover, null, rect, paint);
|
||||
cover.recycle();
|
||||
}
|
||||
|
||||
int top;
|
||||
@ -382,7 +380,6 @@ public final class CoverBitmap {
|
||||
Rect src = new Rect(xOffset, yOffset, sourceWidth - xOffset, sourceHeight - yOffset);
|
||||
Rect dest = new Rect(0, 0, width, height);
|
||||
canvas.drawBitmap(source, src, dest, null);
|
||||
source.recycle();
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
@ -409,9 +406,7 @@ public final class CoverBitmap {
|
||||
float scale = Math.min((float)width / sourceWidth, (float)height / sourceHeight);
|
||||
sourceWidth *= scale;
|
||||
sourceHeight *= scale;
|
||||
Bitmap result = Bitmap.createScaledBitmap(source, sourceWidth, sourceHeight, false);
|
||||
source.recycle();
|
||||
return result;
|
||||
return Bitmap.createScaledBitmap(source, sourceWidth, sourceHeight, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,7 @@ import android.appwidget.AppWidgetProvider;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
@ -106,11 +106,11 @@ public class FourLongWidget extends AppWidgetProvider {
|
||||
views.setViewVisibility(R.id.buttons, View.VISIBLE);
|
||||
views.setTextViewText(R.id.title, song.title);
|
||||
views.setTextViewText(R.id.artist, song.artist);
|
||||
Uri uri = song.getCoverUri();
|
||||
if (uri == null)
|
||||
Bitmap cover = song.getCover(context);
|
||||
if (cover == null)
|
||||
views.setImageViewResource(R.id.cover, 0);
|
||||
else
|
||||
views.setImageViewUri(R.id.cover, uri);
|
||||
views.setImageViewBitmap(R.id.cover, cover);
|
||||
}
|
||||
|
||||
boolean playing = (state & PlaybackService.FLAG_PLAYING) != 0;
|
||||
|
@ -28,7 +28,7 @@ import android.appwidget.AppWidgetProvider;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
@ -106,11 +106,11 @@ public class FourSquareWidget extends AppWidgetProvider {
|
||||
views.setViewVisibility(R.id.buttons, View.VISIBLE);
|
||||
views.setTextViewText(R.id.title, song.title);
|
||||
views.setTextViewText(R.id.artist, song.artist);
|
||||
Uri uri = song.getCoverUri();
|
||||
if (uri == null)
|
||||
Bitmap cover = song.getCover(context);
|
||||
if (cover == null)
|
||||
views.setImageViewResource(R.id.cover, 0);
|
||||
else
|
||||
views.setImageViewUri(R.id.cover, uri);
|
||||
views.setImageViewBitmap(R.id.cover, cover);
|
||||
}
|
||||
|
||||
boolean playing = (state & PlaybackService.FLAG_PLAYING) != 0;
|
||||
|
@ -31,6 +31,7 @@ import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.PaintDrawable;
|
||||
import android.net.Uri;
|
||||
@ -1073,7 +1074,7 @@ public class LibraryActivity
|
||||
super.onSongChange(song);
|
||||
|
||||
if (mTitle != null) {
|
||||
Uri cover = null;
|
||||
Bitmap cover = null;
|
||||
|
||||
if (song == null) {
|
||||
mTitle.setText(R.string.none);
|
||||
@ -1084,7 +1085,7 @@ public class LibraryActivity
|
||||
String artist = song.artist == null ? res.getString(R.string.unknown) : song.artist;
|
||||
mTitle.setText(title);
|
||||
mArtist.setText(artist);
|
||||
cover = song.hasCover(this) ? song.getCoverUri() : null;
|
||||
cover = song.getCover(this);
|
||||
}
|
||||
|
||||
if (Song.mDisableCoverArt)
|
||||
@ -1092,7 +1093,7 @@ public class LibraryActivity
|
||||
else if (cover == null)
|
||||
mCover.setImageResource(R.drawable.albumart_mp_unknown_list);
|
||||
else
|
||||
mCover.setImageURI(cover);
|
||||
mCover.setImageBitmap(cover);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.graphics.Bitmap;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
/**
|
||||
@ -108,18 +108,18 @@ public class OneCellWidget extends AppWidgetProvider {
|
||||
views.setOnClickPendingIntent(R.id.next, PendingIntent.getService(context, 0, next, 0));
|
||||
|
||||
if ((state & PlaybackService.FLAG_NO_MEDIA) != 0) {
|
||||
views.setImageViewResource(R.id.cover, 0);
|
||||
views.setInt(R.id.title, "setText", R.string.no_songs);
|
||||
} else if (song == null) {
|
||||
views.setImageViewResource(R.id.cover, 0);
|
||||
} else if (song == null) {
|
||||
views.setInt(R.id.title, "setText", R.string.app_name);
|
||||
views.setImageViewResource(R.id.cover, 0);
|
||||
} else {
|
||||
Uri uri = song.getCoverUri();
|
||||
if (uri == null)
|
||||
views.setTextViewText(R.id.title, song.title);
|
||||
Bitmap cover = song.getCover(context);
|
||||
if (cover == null)
|
||||
views.setImageViewResource(R.id.cover, 0);
|
||||
else
|
||||
views.setImageViewUri(R.id.cover, uri);
|
||||
views.setTextViewText(R.id.title, song.title);
|
||||
views.setImageViewBitmap(R.id.cover, cover);
|
||||
}
|
||||
|
||||
manager.updateAppWidget(new ComponentName(context, OneCellWidget.class), views);
|
||||
|
@ -36,6 +36,7 @@ import android.content.res.TypedArray;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
@ -1437,10 +1438,11 @@ public final class PlaybackService extends Service
|
||||
|
||||
RemoteViews views = new RemoteViews(getPackageName(), R.layout.notification);
|
||||
|
||||
if (!Song.mDisableCoverArt && song.hasCover(this)) {
|
||||
views.setImageViewUri(R.id.icon, song.getCoverUri());
|
||||
} else {
|
||||
Bitmap cover = song.getCover(this);
|
||||
if (cover == null) {
|
||||
views.setImageViewResource(R.id.icon, R.drawable.icon);
|
||||
} else {
|
||||
views.setImageViewBitmap(R.id.icon, cover);
|
||||
}
|
||||
if (playing) {
|
||||
views.setTextViewText(R.id.title, song.title);
|
||||
|
@ -32,7 +32,6 @@ import android.os.ParcelFileDescriptor;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
/**
|
||||
* Represents a Song backed by the MediaStore. Includes basic metadata and
|
||||
@ -80,6 +79,11 @@ public class Song implements Comparable<Song> {
|
||||
MediaStore.Audio.Playlists.Members.TRACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache of 8 covers.
|
||||
*/
|
||||
private static final Cache<Bitmap> sCoverCache = new Cache<Bitmap>(8);
|
||||
|
||||
/**
|
||||
* If true, will not attempt to load any cover art in getCover()
|
||||
*/
|
||||
@ -131,9 +135,10 @@ public class Song implements Comparable<Song> {
|
||||
public int flags;
|
||||
|
||||
/**
|
||||
* 1 if this song has cover art in the MediaStore, 0 if not, -1 if uninitialized.
|
||||
* If true, this song has no cover art. If false, this song may or may not
|
||||
* have cover art.
|
||||
*/
|
||||
public int hasCover = -1;
|
||||
public boolean noCover;
|
||||
|
||||
/**
|
||||
* Initialize the song with the specified id. Call populate to fill fields
|
||||
@ -193,42 +198,6 @@ public class Song implements Comparable<Song> {
|
||||
return song.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this song has cover art stored in the MediaStore.
|
||||
*
|
||||
* @param context A context to use to query the MediaStore
|
||||
*/
|
||||
public boolean hasCover(Context context)
|
||||
{
|
||||
if (hasCover == -1) {
|
||||
Uri uri = getCoverUri();
|
||||
if (uri == null) {
|
||||
hasCover = 0;
|
||||
} else {
|
||||
try {
|
||||
hasCover = context.getContentResolver().openFileDescriptor(uri, "r") == null ? 0 : 1;
|
||||
} catch (FileNotFoundException e) {
|
||||
hasCover = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasCover == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a URI describing where the cover art is stored, or null if this
|
||||
* song has not been populated.
|
||||
*/
|
||||
public Uri getCoverUri()
|
||||
{
|
||||
// Use undocumented API to extract the cover from the media file from Eclair
|
||||
// See http://android.git.kernel.org/?p=platform/packages/apps/Music.git;a=blob;f=src/com/android/music/MusicUtils.java;h=d1aea0660009940a0160cb981f381e2115768845;hb=0749a3f1c11e052f97a3ba60fd624c9283ee7331#l986
|
||||
|
||||
if (id == -1 || hasCover == 0 || mDisableCoverArt)
|
||||
return null;
|
||||
return Uri.parse("content://media/external/audio/media/" + id + "/albumart");
|
||||
}
|
||||
|
||||
private static final BitmapFactory.Options BITMAP_OPTIONS = new BitmapFactory.Options();
|
||||
|
||||
static {
|
||||
@ -244,23 +213,34 @@ public class Song implements Comparable<Song> {
|
||||
*/
|
||||
public Bitmap getCover(Context context)
|
||||
{
|
||||
Uri uri = getCoverUri();
|
||||
if (uri == null)
|
||||
if (mDisableCoverArt || id == -1 || noCover)
|
||||
return null;
|
||||
|
||||
Bitmap cover = sCoverCache.get(id);
|
||||
if (cover != null) {
|
||||
return cover;
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse("content://media/external/audio/media/" + id + "/albumart");
|
||||
ContentResolver res = context.getContentResolver();
|
||||
hasCover = 0;
|
||||
try {
|
||||
ParcelFileDescriptor parcelFileDescriptor = res.openFileDescriptor(uri, "r");
|
||||
if (parcelFileDescriptor != null) {
|
||||
hasCover = 1;
|
||||
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
|
||||
return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, BITMAP_OPTIONS);
|
||||
cover = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, BITMAP_OPTIONS);
|
||||
if (cover != null) {
|
||||
Bitmap discarded = sCoverCache.discardOldest();
|
||||
if (discarded != null)
|
||||
discarded.recycle();
|
||||
sCoverCache.put(id, cover);
|
||||
return cover;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d("VanillaMusic", "Failed to load cover art for " + path, e);
|
||||
}
|
||||
|
||||
noCover = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ import android.appwidget.AppWidgetProvider;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
@ -106,11 +106,11 @@ public class WidgetD extends AppWidgetProvider {
|
||||
views.setViewVisibility(R.id.buttons, View.VISIBLE);
|
||||
views.setTextViewText(R.id.title, song.title);
|
||||
views.setTextViewText(R.id.artist, song.artist);
|
||||
Uri uri = song.getCoverUri();
|
||||
if (uri == null)
|
||||
Bitmap cover = song.getCover(context);
|
||||
if (cover == null)
|
||||
views.setImageViewResource(R.id.cover, 0);
|
||||
else
|
||||
views.setImageViewUri(R.id.cover, uri);
|
||||
views.setImageViewBitmap(R.id.cover, cover);
|
||||
}
|
||||
|
||||
boolean playing = (state & PlaybackService.FLAG_PLAYING) != 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user