Don't send bitmaps through a parcel; send Uri instead

This speeds things up quite a bit, but requires some reworking to the widget
layouts...
This commit is contained in:
Christopher Eby 2011-09-16 22:56:52 -05:00
parent 4311632dd5
commit 25ce5d6daf
9 changed files with 94 additions and 164 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -29,7 +29,6 @@ THE SOFTWARE.
android:background="#B2191919">
<ImageView
android:id="@+id/cover"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
@ -46,6 +45,7 @@ THE SOFTWARE.
android:paddingRight="8dip">
<TextView
android:id="@+id/title"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#fff"
@ -56,6 +56,7 @@ THE SOFTWARE.
android:ellipsize="none" />
<TextView
android:id="@+id/artist"
android:text="@string/app_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#fff"
@ -66,6 +67,7 @@ THE SOFTWARE.
android:ellipsize="none" />
</LinearLayout>
<LinearLayout
android:id="@+id/buttons"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent">
@ -88,4 +90,4 @@ THE SOFTWARE.
android:background="#0000"
android:scaleType="fitCenter" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2010 Christopher Eby <kreed@kreed.org>
Copyright (C) 2010, 2011 Christopher Eby <kreed@kreed.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -29,69 +29,75 @@ THE SOFTWARE.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/black"
android:adjustViewBounds="true"
android:padding="5dip"
android:background="#B2191919"
android:scaleType="fitCenter" />
<LinearLayout
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_alignTop="@id/cover"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/cover"
android:layout_alignLeft="@+id/cover"
android:layout_alignRight="@+id/cover"
android:layout_margin="10dip"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#fff"
android:textSize="18dip"
android:shadowColor="#f000"
android:shadowDx="0"
android:shadowDy="0"
android:shadowRadius="5"
android:textStyle="bold"
android:ellipsize="none"
android:shadowDx="0"
android:shadowDy="0"
android:shadowRadius="5"
android:textStyle="bold"
android:ellipsize="marquee"
android:singleLine="true" />
<TextView
android:id="@+id/artist"
android:text="@string/app_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#fff"
android:shadowColor="#f000"
android:shadowDx="0"
android:shadowDy="0"
android:shadowRadius="5"
android:shadowDx="0"
android:shadowDy="0"
android:shadowRadius="5"
android:textSize="15dip"
android:ellipsize="none"
android:ellipsize="marquee"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/buttons"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/cover"
android:layout_alignLeft="@+id/cover"
android:layout_alignRight="@+id/cover">
<ImageButton
android:id="@+id/play_pause"
android:src="@drawable/hidden_play"
android:background="#0000"
android:layout_height="wrap_content"
android:layout_width="0px"
android:layout_weight="1" />
<ImageButton
android:id="@+id/next"
android:src="@drawable/hidden_next"
android:background="#0000"
android:layout_height="wrap_content"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical">
<!-- A dummy view that takes up the top half of the widget -->
<LinearLayout
android:layout_height="0px"
android:layout_width="0px"
android:layout_weight="1" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="1">
<ImageButton
android:id="@+id/play_pause"
android:src="@drawable/hidden_play"
android:background="@null"
android:layout_height="fill_parent"
android:layout_width="0px"
android:layout_weight="1" />
<ImageButton
android:id="@+id/next"
android:src="@drawable/hidden_next"
android:background="@null"
android:layout_height="fill_parent"
android:layout_width="0px"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2010 Christopher Eby <kreed@kreed.org>
Copyright (C) 2010, 2011 Christopher Eby <kreed@kreed.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -25,9 +25,23 @@ THE SOFTWARE.
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<ImageView
android:id="@+id/cover_view"
android:layout_height="fill_parent"
android:layout_width="fill_parent" />
android:id="@+id/cover"
android:layout_centerInParent="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
<TextView
android:id="@+id/title"
android:text="@string/app_name"
android:layout_alignBottom="@id/cover"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#fff"
android:background="#a000"
android:textSize="12dip"
android:textStyle="bold"
android:ellipsize="marquee"
android:singleLine="true" />
<LinearLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
@ -35,16 +49,16 @@ THE SOFTWARE.
<ImageButton
android:id="@+id/play_pause"
android:src="@drawable/hidden_play"
android:background="#0000"
android:background="@null"
android:layout_height="0px"
android:layout_width="fill_parent"
android:layout_weight="1" />
<ImageButton
android:id="@+id/next"
android:src="@drawable/hidden_next"
android:background="#0000"
android:background="@null"
android:layout_height="0px"
android:layout_width="fill_parent"
android:layout_weight="1" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

View File

@ -59,8 +59,6 @@ public final class CoverBitmap {
private static int TEXT_SIZE = -1;
private static int TEXT_SIZE_BIG;
private static int PADDING;
private static int TEXT_SIZE_COMPACT = -1;
private static int PADDING_COMPACT;
private static int TEXT_SPACE;
private static Bitmap SONG_ICON;
private static Bitmap ALBUM_ICON;
@ -78,16 +76,6 @@ public final class CoverBitmap {
TEXT_SPACE = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, metrics);
}
/**
* Initialize the compact text size members.
*/
private static void loadMiniTextSizes()
{
DisplayMetrics metrics = ContextApplication.getContext().getResources().getDisplayMetrics();
TEXT_SIZE_COMPACT = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, metrics);
PADDING_COMPACT = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, metrics);
}
/**
* Initialize the icon bitmaps.
*/
@ -126,75 +114,6 @@ public final class CoverBitmap {
canvas.restore();
}
/**
* Create a compact image, displaying cover art with the song title
* overlaid at the bottom edge.
*
* @param song The song to display information for
* @param width Desired width of image
* @param height Desired height of image
* @return The image, or null if the song was null, or width or height
* were less than 1
*/
public static Bitmap createCompactBitmap(Song song, int width, int height)
{
if (song == null || width < 1 || height < 1)
return null;
if (TEXT_SIZE_COMPACT == -1)
loadMiniTextSizes();
int textSize = TEXT_SIZE_COMPACT;
int padding = PADDING_COMPACT;
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(textSize);
String title = song.title == null ? "" : song.title;
Bitmap cover = song.getCover();
int titleWidth = (int)paint.measureText(title);
int boxWidth = width;
int boxHeight = Math.min(height, textSize + padding * 2);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
if (cover != null) {
int coverWidth = cover.getWidth();
int coverHeight = cover.getHeight();
float scale = Math.min((float)width / coverWidth, (float)height / coverHeight);
coverWidth *= scale;
coverHeight *= scale;
int x = (width - coverWidth) / 2;
int y = (height - coverHeight) / 2;
Rect rect = new Rect(x, y, x + coverWidth, y + coverHeight);
canvas.drawBitmap(cover, null, rect, paint);
}
int left = 0;
int top = height - boxHeight;
int right = width;
int bottom = height;
paint.setARGB(150, 0, 0, 0);
canvas.drawRect(left, top, right, bottom, paint);
int maxWidth = boxWidth - padding * 2;
paint.setARGB(255, 255, 255, 255);
top += padding;
left += padding;
drawText(canvas, title, left, top, titleWidth, maxWidth, paint);
return bitmap;
}
/**
* Create an image representing the given song. Includes cover art and
* possibly song title/artist/ablum, depending on the given style.

View File

@ -28,8 +28,6 @@ import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.view.View;
import android.widget.RemoteViews;
@ -102,30 +100,19 @@ public class FourLongWidget extends AppWidgetProvider {
if (ids == null || ids.length == 0)
return;
Resources res = context.getResources();
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.four_long_widget);
Bitmap cover = null;
if (song == null) {
views.setViewVisibility(R.id.buttons, View.GONE);
views.setViewVisibility(R.id.title, View.GONE);
views.setViewVisibility(R.id.next, View.GONE);
views.setViewVisibility(R.id.play_pause, View.GONE);
views.setTextViewText(R.id.artist, res.getText(R.string.no_songs));
views.setInt(R.id.artist, "setText", R.string.no_songs);
views.setImageViewResource(R.id.cover, 0);
} else {
views.setViewVisibility(R.id.title, View.VISIBLE);
views.setViewVisibility(R.id.next, View.VISIBLE);
views.setViewVisibility(R.id.play_pause, View.VISIBLE);
views.setViewVisibility(R.id.buttons, View.VISIBLE);
views.setTextViewText(R.id.title, song.title);
views.setTextViewText(R.id.artist, song.artist);
cover = song.getCover();
}
if (cover == null) {
views.setViewVisibility(R.id.cover, View.GONE);
} else {
views.setViewVisibility(R.id.cover, View.VISIBLE);
views.setImageViewBitmap(R.id.cover, cover);
views.setImageViewUri(R.id.cover, song.getCoverUri());
}
if (state != -1) {

View File

@ -28,8 +28,6 @@ import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.view.View;
import android.widget.RemoteViews;
@ -102,28 +100,21 @@ public class FourSquareWidget extends AppWidgetProvider {
if (ids == null || ids.length == 0)
return;
Resources res = context.getResources();
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.four_square_widget);
Bitmap cover = null;
if (song == null) {
views.setViewVisibility(R.id.title, View.GONE);
views.setViewVisibility(R.id.buttons, View.GONE);
views.setTextViewText(R.id.artist, res.getText(R.string.no_songs));
views.setViewVisibility(R.id.title, View.GONE);
views.setInt(R.id.artist, "setText", R.string.no_songs);
views.setImageViewResource(R.id.cover, 0);
} else {
views.setViewVisibility(R.id.title, View.VISIBLE);
views.setViewVisibility(R.id.buttons, View.VISIBLE);
views.setTextViewText(R.id.title, song.title);
views.setTextViewText(R.id.artist, song.artist);
cover = song.getCover();
views.setImageViewUri(R.id.cover, song.getCoverUri());
}
if (cover == null)
views.setImageViewResource(R.id.cover, R.drawable.black);
else
views.setImageViewBitmap(R.id.cover, cover);
if (state != -1) {
boolean playing = (state & PlaybackService.FLAG_PLAYING) != 0;
views.setImageViewResource(R.id.play_pause, playing ? R.drawable.hidden_pause : R.drawable.hidden_play);

View File

@ -30,7 +30,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.TypedValue;
import android.widget.RemoteViews;
/**
@ -122,10 +121,11 @@ public class OneCellWidget extends AppWidgetProvider {
views.setOnClickPendingIntent(R.id.next, PendingIntent.getService(context, 0, next, 0));
if (song == null) {
views.setImageViewResource(R.id.cover_view, R.drawable.icon);
views.setImageViewResource(R.id.cover, 0);
views.setInt(R.id.title, "setText", R.string.no_songs);
} else {
int size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 72, context.getResources().getDisplayMetrics());
views.setImageViewBitmap(R.id.cover_view, CoverBitmap.createCompactBitmap(song, size, size));
views.setImageViewUri(R.id.cover, song.getCoverUri());
views.setTextViewText(R.id.title, song.title);
}
manager.updateAppWidget(ids, views);

View File

@ -412,6 +412,20 @@ public class Song implements Parcelable {
return cover;
}
/**
* 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)
return null;
return Uri.parse("content://media/external/audio/media/" + id + "/albumart");
}
/**
* Attempts to read the album art directly from a media file using the
* media ContentProvider.
@ -421,13 +435,10 @@ public class Song implements Parcelable {
*/
private Bitmap getCoverFromMediaFile(ContentResolver resolver)
{
// 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
Bitmap cover = null;
try {
Uri uri = Uri.parse("content://media/external/audio/media/" + id + "/albumart");
ParcelFileDescriptor parcelFileDescriptor = resolver.openFileDescriptor(uri, "r");
ParcelFileDescriptor parcelFileDescriptor = resolver.openFileDescriptor(getCoverUri(), "r");
if (parcelFileDescriptor != null) {
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
cover = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, BITMAP_OPTIONS);