Remove ContextApplication
This commit is contained in:
parent
5837753b4a
commit
2023409bd9
@ -27,8 +27,7 @@ THE SOFTWARE.
|
|||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<application
|
<application
|
||||||
android:icon="@drawable/icon"
|
android:icon="@drawable/icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name">
|
||||||
android:name="ContextApplication">
|
|
||||||
<activity
|
<activity
|
||||||
android:name="LaunchActivity"
|
android:name="LaunchActivity"
|
||||||
android:theme="@style/NoBackground">
|
android:theme="@style/NoBackground">
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kreed.vanilla;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclass of Application that provides various static utility functions
|
|
||||||
*/
|
|
||||||
public class ContextApplication extends Application {
|
|
||||||
private static ContextApplication mInstance;
|
|
||||||
private static Random mRandom;
|
|
||||||
|
|
||||||
public ContextApplication()
|
|
||||||
{
|
|
||||||
mInstance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a shared, application-wide Random instance.
|
|
||||||
*/
|
|
||||||
public static Random getRandom()
|
|
||||||
{
|
|
||||||
if (mRandom == null)
|
|
||||||
mRandom = new Random();
|
|
||||||
return mRandom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an easy to access Context instance.
|
|
||||||
*/
|
|
||||||
public static Context getContext()
|
|
||||||
{
|
|
||||||
return mInstance;
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
package org.kreed.vanilla;
|
package org.kreed.vanilla;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
@ -66,10 +67,12 @@ public final class CoverBitmap {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the regular text size members.
|
* Initialize the regular text size members.
|
||||||
|
*
|
||||||
|
* @param context A context to use.
|
||||||
*/
|
*/
|
||||||
private static void loadTextSizes()
|
private static void loadTextSizes(Context context)
|
||||||
{
|
{
|
||||||
DisplayMetrics metrics = ContextApplication.getContext().getResources().getDisplayMetrics();
|
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||||
TEXT_SIZE = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, metrics);
|
TEXT_SIZE = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, metrics);
|
||||||
TEXT_SIZE_BIG = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, metrics);
|
TEXT_SIZE_BIG = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, metrics);
|
||||||
PADDING = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, metrics);
|
PADDING = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, metrics);
|
||||||
@ -78,10 +81,12 @@ public final class CoverBitmap {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the icon bitmaps.
|
* Initialize the icon bitmaps.
|
||||||
|
*
|
||||||
|
* @param context A context to use.
|
||||||
*/
|
*/
|
||||||
private static void loadIcons()
|
private static void loadIcons(Context context)
|
||||||
{
|
{
|
||||||
Resources res = ContextApplication.getContext().getResources();
|
Resources res = context.getResources();
|
||||||
Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.ic_tab_songs_selected);
|
Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.ic_tab_songs_selected);
|
||||||
SONG_ICON = Bitmap.createScaledBitmap(bitmap, TEXT_SIZE, TEXT_SIZE, false);
|
SONG_ICON = Bitmap.createScaledBitmap(bitmap, TEXT_SIZE, TEXT_SIZE, false);
|
||||||
bitmap.recycle();
|
bitmap.recycle();
|
||||||
@ -118,6 +123,7 @@ public final class CoverBitmap {
|
|||||||
* Create an image representing the given song. Includes cover art and
|
* Create an image representing the given song. Includes cover art and
|
||||||
* possibly song title/artist/ablum, depending on the given style.
|
* possibly song title/artist/ablum, depending on the given style.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param style One of CoverBitmap.STYLE_*
|
* @param style One of CoverBitmap.STYLE_*
|
||||||
* @param song The song to display information for
|
* @param song The song to display information for
|
||||||
* @param width Maximum width of image
|
* @param width Maximum width of image
|
||||||
@ -128,29 +134,29 @@ public final class CoverBitmap {
|
|||||||
* @return The image, or null if the song was null, or width or height
|
* @return The image, or null if the song was null, or width or height
|
||||||
* were less than 1
|
* were less than 1
|
||||||
*/
|
*/
|
||||||
public static Bitmap createBitmap(int style, Song song, int width, int height, Bitmap bitmap)
|
public static Bitmap createBitmap(Context context, int style, Song song, int width, int height, Bitmap bitmap)
|
||||||
{
|
{
|
||||||
switch (style) {
|
switch (style) {
|
||||||
case STYLE_OVERLAPPING_BOX:
|
case STYLE_OVERLAPPING_BOX:
|
||||||
return createOverlappingBitmap(song, width, height, bitmap);
|
return createOverlappingBitmap(context, song, width, height, bitmap);
|
||||||
case STYLE_INFO_BELOW:
|
case STYLE_INFO_BELOW:
|
||||||
return createSeparatedBitmap(song, width, height, bitmap);
|
return createSeparatedBitmap(context, song, width, height, bitmap);
|
||||||
case STYLE_NO_INFO:
|
case STYLE_NO_INFO:
|
||||||
return createScaledBitmap(song, width, height);
|
return createScaledBitmap(context, song, width, height);
|
||||||
case STYLE_NO_INFO_ZOOMED:
|
case STYLE_NO_INFO_ZOOMED:
|
||||||
return createZoomedBitmap(song, width, height, bitmap);
|
return createZoomedBitmap(context, song, width, height, bitmap);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid bitmap type given: " + style);
|
throw new IllegalArgumentException("Invalid bitmap type given: " + style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Bitmap createOverlappingBitmap(Song song, int width, int height, Bitmap bitmap)
|
private static Bitmap createOverlappingBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (song == null || width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (TEXT_SIZE == -1)
|
if (TEXT_SIZE == -1)
|
||||||
loadTextSizes();
|
loadTextSizes(context);
|
||||||
|
|
||||||
Paint paint = new Paint();
|
Paint paint = new Paint();
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
@ -158,7 +164,7 @@ public final class CoverBitmap {
|
|||||||
String title = song.title == null ? "" : song.title;
|
String title = song.title == null ? "" : song.title;
|
||||||
String album = song.album == null ? "" : song.album;
|
String album = song.album == null ? "" : song.album;
|
||||||
String artist = song.artist == null ? "" : song.artist;
|
String artist = song.artist == null ? "" : song.artist;
|
||||||
Bitmap cover = song.getCover();
|
Bitmap cover = song.getCover(context);
|
||||||
|
|
||||||
int titleSize = TEXT_SIZE_BIG;
|
int titleSize = TEXT_SIZE_BIG;
|
||||||
int subSize = TEXT_SIZE;
|
int subSize = TEXT_SIZE;
|
||||||
@ -238,15 +244,15 @@ public final class CoverBitmap {
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Bitmap createSeparatedBitmap(Song song, int width, int height, Bitmap bitmap)
|
private static Bitmap createSeparatedBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (song == null || width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (TEXT_SIZE == -1)
|
if (TEXT_SIZE == -1)
|
||||||
loadTextSizes();
|
loadTextSizes(context);
|
||||||
if (SONG_ICON == null)
|
if (SONG_ICON == null)
|
||||||
loadIcons();
|
loadIcons(context);
|
||||||
|
|
||||||
boolean horizontal = width > height;
|
boolean horizontal = width > height;
|
||||||
|
|
||||||
@ -256,7 +262,7 @@ public final class CoverBitmap {
|
|||||||
String title = song.title == null ? "" : song.title;
|
String title = song.title == null ? "" : song.title;
|
||||||
String album = song.album == null ? "" : song.album;
|
String album = song.album == null ? "" : song.album;
|
||||||
String artist = song.artist == null ? "" : song.artist;
|
String artist = song.artist == null ? "" : song.artist;
|
||||||
Bitmap cover = song.getCover();
|
Bitmap cover = song.getCover(context);
|
||||||
|
|
||||||
int textSize = TEXT_SIZE;
|
int textSize = TEXT_SIZE;
|
||||||
int padding = PADDING;
|
int padding = PADDING;
|
||||||
@ -340,12 +346,12 @@ public final class CoverBitmap {
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Bitmap createZoomedBitmap(Song song, int width, int height, Bitmap bitmap)
|
private static Bitmap createZoomedBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (song == null || width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Bitmap cover = song.getCover();
|
Bitmap cover = song.getCover(context);
|
||||||
if (cover == null)
|
if (cover == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -379,17 +385,18 @@ public final class CoverBitmap {
|
|||||||
* preserved. At least one dimension of the result will match the provided
|
* preserved. At least one dimension of the result will match the provided
|
||||||
* dimension exactly.
|
* dimension exactly.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param song The song to display information for
|
* @param song The song to display information for
|
||||||
* @param width Maximum width of image
|
* @param width Maximum width of image
|
||||||
* @param height Maximum height of image
|
* @param height Maximum height of image
|
||||||
* @return The scaled Bitmap, or null if a cover could not be found.
|
* @return The scaled Bitmap, or null if a cover could not be found.
|
||||||
*/
|
*/
|
||||||
public static Bitmap createScaledBitmap(Song song, int width, int height)
|
public static Bitmap createScaledBitmap(Context context, Song song, int width, int height)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (song == null || width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Bitmap cover = song.getCover();
|
Bitmap cover = song.getCover(context);
|
||||||
if (cover == null)
|
if (cover == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -326,7 +326,7 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
|
|
||||||
Bitmap bitmap = mBitmapCache.get(song.id);
|
Bitmap bitmap = mBitmapCache.get(song.id);
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
mBitmapCache.put(song.id, CoverBitmap.createBitmap(mCoverStyle, song, getWidth(), getHeight(), mBitmapCache.discardOldest()));
|
mBitmapCache.put(song.id, CoverBitmap.createBitmap(getContext(), mCoverStyle, song, getWidth(), getHeight(), mBitmapCache.discardOldest()));
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
} else {
|
} else {
|
||||||
mBitmapCache.touch(song.id);
|
mBitmapCache.touch(song.id);
|
||||||
|
@ -59,6 +59,8 @@ import java.io.Serializable;
|
|||||||
* See MediaView.getLimiter and setLimiter for details.
|
* See MediaView.getLimiter and setLimiter for details.
|
||||||
*/
|
*/
|
||||||
public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of media represented by this adapter. Must be one of the
|
* The type of media represented by this adapter. Must be one of the
|
||||||
* MediaUtils.FIELD_* constants. Determines which content provider to query for
|
* MediaUtils.FIELD_* constants. Determines which content provider to query for
|
||||||
@ -113,6 +115,7 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
{
|
{
|
||||||
super(context, null, requery);
|
super(context, null, requery);
|
||||||
|
|
||||||
|
mContext = context;
|
||||||
mType = type;
|
mType = type;
|
||||||
mExpandable = expandable;
|
mExpandable = expandable;
|
||||||
mLimiter = limiter;
|
mLimiter = limiter;
|
||||||
@ -225,7 +228,7 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
*/
|
*/
|
||||||
public Cursor runQuery(CharSequence constraint)
|
public Cursor runQuery(CharSequence constraint)
|
||||||
{
|
{
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = mContext.getContentResolver();
|
||||||
|
|
||||||
String[] projection;
|
String[] projection;
|
||||||
if (mFields.length == 1)
|
if (mFields.length == 1)
|
||||||
@ -279,7 +282,7 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
if (mLimiter.type == MediaUtils.TYPE_GENRE) {
|
if (mLimiter.type == MediaUtils.TYPE_GENRE) {
|
||||||
// Genre is not standard metadata for MediaStore.Audio.Media.
|
// Genre is not standard metadata for MediaStore.Audio.Media.
|
||||||
// We have to query it through a separate provider. : /
|
// We have to query it through a separate provider. : /
|
||||||
return MediaUtils.queryGenre(mLimiter.id, projection, selection.toString(), selectionArgs);
|
return MediaUtils.queryGenre(mContext, mLimiter.id, projection, selection.toString(), selectionArgs);
|
||||||
} else {
|
} else {
|
||||||
if (selection.length() != 0)
|
if (selection.length() != 0)
|
||||||
selection.append(" AND ");
|
selection.append(" AND ");
|
||||||
|
@ -56,6 +56,8 @@ public class MediaButtonHandler {
|
|||||||
* uninitialized.
|
* uninitialized.
|
||||||
*/
|
*/
|
||||||
private static int mUseControls = -1;
|
private static int mUseControls = -1;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
/**
|
/**
|
||||||
* Whether the phone is currently in a call. 1 for yes, 0 for no, -1 for
|
* Whether the phone is currently in a call. 1 for yes, 0 for no, -1 for
|
||||||
* uninitialized.
|
* uninitialized.
|
||||||
@ -75,11 +77,11 @@ public class MediaButtonHandler {
|
|||||||
* Retrieve the MediaButtonHandler singleton, creating it if necessary.
|
* Retrieve the MediaButtonHandler singleton, creating it if necessary.
|
||||||
* Returns null if headset controls are not enabled.
|
* Returns null if headset controls are not enabled.
|
||||||
*/
|
*/
|
||||||
public static MediaButtonHandler getInstance()
|
public static MediaButtonHandler getInstance(Context context)
|
||||||
{
|
{
|
||||||
if (useHeadsetControls()) {
|
if (useHeadsetControls(context)) {
|
||||||
if (mInstance == null)
|
if (mInstance == null)
|
||||||
mInstance = new MediaButtonHandler();
|
mInstance = new MediaButtonHandler(context.getApplicationContext());
|
||||||
return mInstance;
|
return mInstance;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -88,10 +90,9 @@ public class MediaButtonHandler {
|
|||||||
/**
|
/**
|
||||||
* Construct a MediaButtonHandler.
|
* Construct a MediaButtonHandler.
|
||||||
*/
|
*/
|
||||||
private MediaButtonHandler()
|
private MediaButtonHandler(Context context)
|
||||||
{
|
{
|
||||||
Context context = ContextApplication.getContext();
|
mContext = context;
|
||||||
|
|
||||||
mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
||||||
mButtonReceiver = new ComponentName(context.getPackageName(), MediaButtonReceiver.class.getName());
|
mButtonReceiver = new ComponentName(context.getPackageName(), MediaButtonReceiver.class.getName());
|
||||||
try {
|
try {
|
||||||
@ -102,17 +103,16 @@ public class MediaButtonHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadPreference()
|
/**
|
||||||
|
* Reload the preference and enable/disable buttons as appropriate.
|
||||||
|
*
|
||||||
|
* @param context A context to use.
|
||||||
|
*/
|
||||||
|
public static void reloadPreference(Context context)
|
||||||
{
|
{
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(ContextApplication.getContext());
|
mUseControls = -1;
|
||||||
mUseControls = settings.getBoolean("media_button", true) ? 1 : 0;
|
if (useHeadsetControls(context)) {
|
||||||
}
|
getInstance(context).registerMediaButton();
|
||||||
|
|
||||||
public static void reloadPreference()
|
|
||||||
{
|
|
||||||
loadPreference();
|
|
||||||
if (useHeadsetControls()) {
|
|
||||||
getInstance().registerMediaButton();
|
|
||||||
} else {
|
} else {
|
||||||
unregisterMediaButton();
|
unregisterMediaButton();
|
||||||
}
|
}
|
||||||
@ -121,11 +121,16 @@ public class MediaButtonHandler {
|
|||||||
/**
|
/**
|
||||||
* Return whether headset controls should be used, loading the preference
|
* Return whether headset controls should be used, loading the preference
|
||||||
* if necessary.
|
* if necessary.
|
||||||
|
*
|
||||||
|
* @param context A context to use.
|
||||||
*/
|
*/
|
||||||
public static boolean useHeadsetControls()
|
public static boolean useHeadsetControls(Context context)
|
||||||
{
|
{
|
||||||
if (mUseControls == -1)
|
if (mUseControls == -1) {
|
||||||
loadPreference();
|
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
mUseControls = settings.getBoolean("media_button", true) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
return mUseControls == 1;
|
return mUseControls == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,8 +140,7 @@ public class MediaButtonHandler {
|
|||||||
private boolean isInCall()
|
private boolean isInCall()
|
||||||
{
|
{
|
||||||
if (mInCall == -1) {
|
if (mInCall == -1) {
|
||||||
Context context = ContextApplication.getContext();
|
TelephonyManager manager = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
|
|
||||||
mInCall = (byte)(manager.getCallState() == TelephonyManager.CALL_STATE_IDLE ? 0 : 1);
|
mInCall = (byte)(manager.getCallState() == TelephonyManager.CALL_STATE_IDLE ? 0 : 1);
|
||||||
}
|
}
|
||||||
return mInCall == 1;
|
return mInCall == 1;
|
||||||
@ -157,12 +161,11 @@ public class MediaButtonHandler {
|
|||||||
*
|
*
|
||||||
* @param action One of the PlaybackService.ACTION_* actions.
|
* @param action One of the PlaybackService.ACTION_* actions.
|
||||||
*/
|
*/
|
||||||
private static void act(String action)
|
private void act(String action)
|
||||||
{
|
{
|
||||||
Context context = ContextApplication.getContext();
|
Intent intent = new Intent(mContext, PlaybackService.class);
|
||||||
Intent intent = new Intent(context, PlaybackService.class);
|
|
||||||
intent.setAction(action);
|
intent.setAction(action);
|
||||||
context.startService(intent);
|
mContext.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,7 +173,7 @@ public class MediaButtonHandler {
|
|||||||
*/
|
*/
|
||||||
public boolean processKey(KeyEvent event)
|
public boolean processKey(KeyEvent event)
|
||||||
{
|
{
|
||||||
if (event == null || isInCall() || !useHeadsetControls())
|
if (event == null || isInCall() || !useHeadsetControls(mContext))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int action = event.getAction();
|
int action = event.getAction();
|
||||||
|
@ -31,7 +31,7 @@ public class MediaButtonReceiver extends BroadcastReceiver {
|
|||||||
public void onReceive(Context context, Intent intent)
|
public void onReceive(Context context, Intent intent)
|
||||||
{
|
{
|
||||||
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
|
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
|
||||||
boolean handled = MediaButtonHandler.getInstance().process(intent);
|
boolean handled = MediaButtonHandler.getInstance(context).process(intent);
|
||||||
if (handled && isOrderedBroadcast())
|
if (handled && isOrderedBroadcast())
|
||||||
abortBroadcast();
|
abortBroadcast();
|
||||||
}
|
}
|
||||||
|
@ -53,18 +53,34 @@ public class MediaUtils {
|
|||||||
*/
|
*/
|
||||||
public static final int TYPE_GENRE = 5;
|
public static final int TYPE_GENRE = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached random instance.
|
||||||
|
*/
|
||||||
|
private static Random sRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a cached random instanced, creating it if necessary.
|
||||||
|
*/
|
||||||
|
public static Random getRandom()
|
||||||
|
{
|
||||||
|
if (sRandom == null)
|
||||||
|
sRandom = new Random();
|
||||||
|
return sRandom;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a cursor containing the ids of all the songs with artist or
|
* Return a cursor containing the ids of all the songs with artist or
|
||||||
* album of the specified id.
|
* album of the specified id.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param type One of the TYPE_* constants, excluding playlists.
|
* @param type One of the TYPE_* constants, excluding playlists.
|
||||||
* @param id The MediaStore id of the artist or album.
|
* @param id The MediaStore id of the artist or album.
|
||||||
* @param projection The columns to query.
|
* @param projection The columns to query.
|
||||||
* @param select An extra selection to pass to the query, or null.
|
* @param select An extra selection to pass to the query, or null.
|
||||||
*/
|
*/
|
||||||
private static Cursor getMediaCursor(int type, long id, String[] projection, String select)
|
private static Cursor getMediaCursor(Context context, int type, long id, String[] projection, String select)
|
||||||
{
|
{
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
StringBuilder selection = new StringBuilder();
|
StringBuilder selection = new StringBuilder();
|
||||||
|
|
||||||
@ -99,12 +115,13 @@ public class MediaUtils {
|
|||||||
* Return a cursor containing the ids of all the songs in the playlist
|
* Return a cursor containing the ids of all the songs in the playlist
|
||||||
* with the given id.
|
* with the given id.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param id The id of the playlist in MediaStore.Audio.Playlists.
|
* @param id The id of the playlist in MediaStore.Audio.Playlists.
|
||||||
* @param projection The columns to query.
|
* @param projection The columns to query.
|
||||||
*/
|
*/
|
||||||
private static Cursor getPlaylistCursor(long id, String[] projection)
|
private static Cursor getPlaylistCursor(Context context, long id, String[] projection)
|
||||||
{
|
{
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", id);
|
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", id);
|
||||||
String sort = MediaStore.Audio.Playlists.Members.PLAY_ORDER;
|
String sort = MediaStore.Audio.Playlists.Members.PLAY_ORDER;
|
||||||
return resolver.query(uri, projection, null, null, sort);
|
return resolver.query(uri, projection, null, null, sort);
|
||||||
@ -114,14 +131,15 @@ public class MediaUtils {
|
|||||||
* Return a cursor containing the ids of all the songs in the genre
|
* Return a cursor containing the ids of all the songs in the genre
|
||||||
* with the given id.
|
* with the given id.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param id The id of the genre in MediaStore.Audio.Genres.
|
* @param id The id of the genre in MediaStore.Audio.Genres.
|
||||||
* @param projection The columns to query.
|
* @param projection The columns to query.
|
||||||
* @param selection The selection to pass to the query, or null.
|
* @param selection The selection to pass to the query, or null.
|
||||||
* @param selectionArgs The arguments to substitute into the selection.
|
* @param selectionArgs The arguments to substitute into the selection.
|
||||||
*/
|
*/
|
||||||
public static Cursor queryGenre(long id, String[] projection, String selection, String[] selectionArgs)
|
public static Cursor queryGenre(Context context, long id, String[] projection, String selection, String[] selectionArgs)
|
||||||
{
|
{
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", id);
|
Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", id);
|
||||||
String sort = MediaStore.Audio.Genres.Members.TITLE_KEY;
|
String sort = MediaStore.Audio.Genres.Members.TITLE_KEY;
|
||||||
return resolver.query(uri, projection, selection, selectionArgs, sort);
|
return resolver.query(uri, projection, selection, selectionArgs, sort);
|
||||||
@ -130,6 +148,7 @@ public class MediaUtils {
|
|||||||
/**
|
/**
|
||||||
* Returns a Cursor queried with the given information.
|
* Returns a Cursor queried with the given information.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param type Type the id represents. Must be one of the Song.TYPE_*
|
* @param type Type the id represents. Must be one of the Song.TYPE_*
|
||||||
* constants.
|
* constants.
|
||||||
* @param id The id of the element in the MediaStore content provider for
|
* @param id The id of the element in the MediaStore content provider for
|
||||||
@ -137,18 +156,18 @@ public class MediaUtils {
|
|||||||
* @param selection An extra selection to be passed to the query. May be
|
* @param selection An extra selection to be passed to the query. May be
|
||||||
* null. Must not be used with type == TYPE_SONG or type == TYPE_PLAYLIST
|
* null. Must not be used with type == TYPE_SONG or type == TYPE_PLAYLIST
|
||||||
*/
|
*/
|
||||||
public static Cursor query(int type, long id, String[] projection, String selection)
|
public static Cursor query(Context context, int type, long id, String[] projection, String selection)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_ARTIST:
|
case TYPE_ARTIST:
|
||||||
case TYPE_ALBUM:
|
case TYPE_ALBUM:
|
||||||
case TYPE_SONG:
|
case TYPE_SONG:
|
||||||
return getMediaCursor(type, id, projection, selection);
|
return getMediaCursor(context, type, id, projection, selection);
|
||||||
case TYPE_PLAYLIST:
|
case TYPE_PLAYLIST:
|
||||||
assert(selection == null);
|
assert(selection == null);
|
||||||
return getPlaylistCursor(id, projection);
|
return getPlaylistCursor(context, id, projection);
|
||||||
case TYPE_GENRE:
|
case TYPE_GENRE:
|
||||||
return queryGenre(id, projection, selection, null);
|
return queryGenre(context, id, projection, selection, null);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Specified type not valid: " + type);
|
throw new IllegalArgumentException("Specified type not valid: " + type);
|
||||||
}
|
}
|
||||||
@ -157,21 +176,22 @@ public class MediaUtils {
|
|||||||
/**
|
/**
|
||||||
* Return an array containing all the song ids that match the specified parameters
|
* Return an array containing all the song ids that match the specified parameters
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param type Type the id represents. Must be one of the Song.TYPE_*
|
* @param type Type the id represents. Must be one of the Song.TYPE_*
|
||||||
* constants.
|
* constants.
|
||||||
* @param id The id of the element in the MediaStore content provider for
|
* @param id The id of the element in the MediaStore content provider for
|
||||||
* the given type.
|
* the given type.
|
||||||
*/
|
*/
|
||||||
public static long[] getAllSongIdsWith(int type, long id)
|
public static long[] getAllSongIdsWith(Context context, int type, long id)
|
||||||
{
|
{
|
||||||
if (type == TYPE_SONG)
|
if (type == TYPE_SONG)
|
||||||
return new long[] { id };
|
return new long[] { id };
|
||||||
|
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
if (type == MediaUtils.TYPE_PLAYLIST)
|
if (type == MediaUtils.TYPE_PLAYLIST)
|
||||||
cursor = query(type, id, Song.EMPTY_PLAYLIST_PROJECTION, null);
|
cursor = query(context, type, id, Song.EMPTY_PLAYLIST_PROJECTION, null);
|
||||||
else
|
else
|
||||||
cursor = query(type, id, Song.EMPTY_PROJECTION, null);
|
cursor = query(context, type, id, Song.EMPTY_PROJECTION, null);
|
||||||
if (cursor == null)
|
if (cursor == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -204,7 +224,7 @@ public class MediaUtils {
|
|||||||
|
|
||||||
ContentResolver resolver = context.getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
String[] projection = new String [] { MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA };
|
String[] projection = new String [] { MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA };
|
||||||
Cursor cursor = getMediaCursor(type, id, projection, null);
|
Cursor cursor = getMediaCursor(context, type, id, projection, null);
|
||||||
|
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
PlaybackService service = PlaybackService.hasInstance() ? PlaybackService.get(context) : null;
|
PlaybackService service = PlaybackService.hasInstance() ? PlaybackService.get(context) : null;
|
||||||
@ -230,13 +250,13 @@ public class MediaUtils {
|
|||||||
* Query the MediaStore to determine the id of the genre the song belongs
|
* Query the MediaStore to determine the id of the genre the song belongs
|
||||||
* to.
|
* to.
|
||||||
*/
|
*/
|
||||||
public static long queryGenreForSong(long id)
|
public static long queryGenreForSong(Context context, long id)
|
||||||
{
|
{
|
||||||
// This is terribly inefficient, but it seems to be the only way to do
|
// This is terribly inefficient, but it seems to be the only way to do
|
||||||
// this. Honeycomb introduced an API to query the genre of the song.
|
// this. Honeycomb introduced an API to query the genre of the song.
|
||||||
// We should look into it when ICS is released.
|
// We should look into it when ICS is released.
|
||||||
|
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
|
|
||||||
// query ids of all the genres
|
// query ids of all the genres
|
||||||
Uri uri = MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI;
|
Uri uri = MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI;
|
||||||
@ -269,7 +289,7 @@ public class MediaUtils {
|
|||||||
*/
|
*/
|
||||||
public static void shuffle(long[] list)
|
public static void shuffle(long[] list)
|
||||||
{
|
{
|
||||||
Random random = ContextApplication.getRandom();
|
Random random = getRandom();
|
||||||
for (int i = list.length; --i != -1; ) {
|
for (int i = list.length; --i != -1; ) {
|
||||||
int j = random.nextInt(i + 1);
|
int j = random.nextInt(i + 1);
|
||||||
long tmp = list[j];
|
long tmp = list[j];
|
||||||
@ -287,7 +307,7 @@ public class MediaUtils {
|
|||||||
public static void shuffle(Song[] list, int end)
|
public static void shuffle(Song[] list, int end)
|
||||||
{
|
{
|
||||||
assert(end <= list.length && end >= 0);
|
assert(end <= list.length && end >= 0);
|
||||||
Random random = ContextApplication.getRandom();
|
Random random = getRandom();
|
||||||
for (int i = end; --i != -1; ) {
|
for (int i = end; --i != -1; ) {
|
||||||
int j = random.nextInt(i + 1);
|
int j = random.nextInt(i + 1);
|
||||||
Song tmp = list[j];
|
Song tmp = list[j];
|
||||||
|
@ -125,7 +125,7 @@ public class NewPlaylistDialog extends Dialog implements TextWatcher, View.OnCli
|
|||||||
mPositiveButton.setEnabled(true);
|
mPositiveButton.setEnabled(true);
|
||||||
// Update the action button based on whether there is an
|
// Update the action button based on whether there is an
|
||||||
// existing playlist with the given name.
|
// existing playlist with the given name.
|
||||||
int res = Playlist.getPlaylist(string) == -1 ? mActionRes : R.string.overwrite;
|
int res = Playlist.getPlaylist(getContext(), string) == -1 ? mActionRes : R.string.overwrite;
|
||||||
mPositiveButton.setText(res);
|
mPositiveButton.setText(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
PlaybackService service = PlaybackService.get(this);
|
PlaybackService service = PlaybackService.get(this);
|
||||||
service.userActionTriggered();
|
service.userActionTriggered();
|
||||||
|
|
||||||
MediaButtonHandler buttons = MediaButtonHandler.getInstance();
|
MediaButtonHandler buttons = MediaButtonHandler.getInstance(this);
|
||||||
if (buttons != null)
|
if (buttons != null)
|
||||||
buttons.setInCall(false);
|
buttons.setInCall(false);
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
return MediaButtonHandler.getInstance().processKey(event);
|
return MediaButtonHandler.getInstance(this).processKey(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onKeyDown(keyCode, event);
|
return super.onKeyDown(keyCode, event);
|
||||||
@ -141,7 +141,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
return MediaButtonHandler.getInstance().processKey(event);
|
return MediaButtonHandler.getInstance(this).processKey(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onKeyUp(keyCode, event);
|
return super.onKeyUp(keyCode, event);
|
||||||
|
@ -184,9 +184,9 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
HandlerThread thread = new HandlerThread("PlaybackService");
|
HandlerThread thread = new HandlerThread("PlaybackService");
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
||||||
mTimeline = new SongTimeline();
|
mTimeline = new SongTimeline(this);
|
||||||
mTimeline.setCallback(this);
|
mTimeline.setCallback(this);
|
||||||
mPendingSeek = mTimeline.loadState(this);
|
mPendingSeek = mTimeline.loadState();
|
||||||
|
|
||||||
mMediaPlayer = new MediaPlayer();
|
mMediaPlayer = new MediaPlayer();
|
||||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||||
@ -268,7 +268,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
userActionTriggered();
|
userActionTriggered();
|
||||||
MediaButtonHandler buttons = MediaButtonHandler.getInstance();
|
MediaButtonHandler buttons = MediaButtonHandler.getInstance(this);
|
||||||
if (buttons != null)
|
if (buttons != null)
|
||||||
buttons.registerMediaButton();
|
buttons.registerMediaButton();
|
||||||
}
|
}
|
||||||
@ -285,7 +285,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
|
||||||
if (mMediaPlayer != null) {
|
if (mMediaPlayer != null) {
|
||||||
mTimeline.saveState(this, mMediaPlayer.getCurrentPosition());
|
mTimeline.saveState(mMediaPlayer.getCurrentPosition());
|
||||||
mMediaPlayer.release();
|
mMediaPlayer.release();
|
||||||
mMediaPlayer = null;
|
mMediaPlayer = null;
|
||||||
}
|
}
|
||||||
@ -338,7 +338,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
if (mMediaPlayer != null)
|
if (mMediaPlayer != null)
|
||||||
mMediaPlayer.setVolume(volume, volume);
|
mMediaPlayer.setVolume(volume, volume);
|
||||||
} else if ("media_button".equals(key)) {
|
} else if ("media_button".equals(key)) {
|
||||||
MediaButtonHandler.reloadPreference();
|
MediaButtonHandler.reloadPreference(this);
|
||||||
} else if ("use_idle_timeout".equals(key) || "idle_timeout".equals(key)) {
|
} else if ("use_idle_timeout".equals(key) || "idle_timeout".equals(key)) {
|
||||||
mIdleTimeout = settings.getBoolean("use_idle_timeout", false) ? settings.getInt("idle_timeout", 3600) : 0;
|
mIdleTimeout = settings.getBoolean("use_idle_timeout", false) ? settings.getInt("idle_timeout", 3600) : 0;
|
||||||
userActionTriggered();
|
userActionTriggered();
|
||||||
@ -417,7 +417,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
mMediaPlayer.start();
|
mMediaPlayer.start();
|
||||||
|
|
||||||
if (mNotificationMode != NEVER)
|
if (mNotificationMode != NEVER)
|
||||||
startForeground(NOTIFICATION_ID, new SongNotification(mCurrentSong, true));
|
startForeground(NOTIFICATION_ID, new SongNotification(this, mCurrentSong, true));
|
||||||
|
|
||||||
if (mWakeLock != null)
|
if (mWakeLock != null)
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
@ -427,7 +427,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
|
|
||||||
if (mNotificationMode == ALWAYS) {
|
if (mNotificationMode == ALWAYS) {
|
||||||
stopForeground(false);
|
stopForeground(false);
|
||||||
mNotificationManager.notify(NOTIFICATION_ID, new SongNotification(mCurrentSong, false));
|
mNotificationManager.notify(NOTIFICATION_ID, new SongNotification(this, mCurrentSong, false));
|
||||||
} else {
|
} else {
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
}
|
}
|
||||||
@ -512,7 +512,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
private void updateNotification()
|
private void updateNotification()
|
||||||
{
|
{
|
||||||
if ((mNotificationMode == ALWAYS || mNotificationMode == WHEN_PLAYING && (mState & FLAG_PLAYING) != 0) && mCurrentSong != null)
|
if ((mNotificationMode == ALWAYS || mNotificationMode == WHEN_PLAYING && (mState & FLAG_PLAYING) != 0) && mCurrentSong != null)
|
||||||
mNotificationManager.notify(NOTIFICATION_ID, new SongNotification(mCurrentSong, (mState & FLAG_PLAYING) != 0));
|
mNotificationManager.notify(NOTIFICATION_ID, new SongNotification(this, mCurrentSong, (mState & FLAG_PLAYING) != 0));
|
||||||
else
|
else
|
||||||
mNotificationManager.cancel(NOTIFICATION_ID);
|
mNotificationManager.cancel(NOTIFICATION_ID);
|
||||||
}
|
}
|
||||||
@ -587,7 +587,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
Song song = mTimeline.shiftCurrentSong(delta);
|
Song song = mTimeline.shiftCurrentSong(delta);
|
||||||
mCurrentSong = song;
|
mCurrentSong = song;
|
||||||
if (song == null || song.id == -1 || song.path == null) {
|
if (song == null || song.id == -1 || song.path == null) {
|
||||||
if (Song.isSongAvailable()) {
|
if (Song.isSongAvailable(this)) {
|
||||||
int flag = (mState & FLAG_RANDOM) == 0 ? FLAG_EMPTY_QUEUE : FLAG_ERROR;
|
int flag = (mState & FLAG_RANDOM) == 0 ? FLAG_EMPTY_QUEUE : FLAG_ERROR;
|
||||||
synchronized (mStateLock) {
|
synchronized (mStateLock) {
|
||||||
updateState((mState | flag) & ~FLAG_NO_MEDIA);
|
updateState((mState | flag) & ~FLAG_NO_MEDIA);
|
||||||
@ -713,7 +713,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case TelephonyManager.CALL_STATE_RINGING:
|
case TelephonyManager.CALL_STATE_RINGING:
|
||||||
case TelephonyManager.CALL_STATE_OFFHOOK: {
|
case TelephonyManager.CALL_STATE_OFFHOOK: {
|
||||||
MediaButtonHandler buttons = MediaButtonHandler.getInstance();
|
MediaButtonHandler buttons = MediaButtonHandler.getInstance(PlaybackService.this);
|
||||||
if (buttons != null)
|
if (buttons != null)
|
||||||
buttons.setInCall(true);
|
buttons.setInCall(true);
|
||||||
|
|
||||||
@ -726,7 +726,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TelephonyManager.CALL_STATE_IDLE: {
|
case TelephonyManager.CALL_STATE_IDLE: {
|
||||||
MediaButtonHandler buttons = MediaButtonHandler.getInstance();
|
MediaButtonHandler buttons = MediaButtonHandler.getInstance(PlaybackService.this);
|
||||||
if (buttons != null)
|
if (buttons != null)
|
||||||
buttons.setInCall(false);
|
buttons.setInCall(false);
|
||||||
|
|
||||||
@ -742,7 +742,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
|
|
||||||
public void onMediaChange()
|
public void onMediaChange()
|
||||||
{
|
{
|
||||||
if (Song.isSongAvailable()) {
|
if (Song.isSongAvailable(this)) {
|
||||||
if ((mState & FLAG_NO_MEDIA) != 0)
|
if ((mState & FLAG_NO_MEDIA) != 0)
|
||||||
setCurrentSong(0);
|
setCurrentSong(0);
|
||||||
} else {
|
} else {
|
||||||
@ -804,7 +804,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
case SAVE_STATE:
|
case SAVE_STATE:
|
||||||
// For unexpected terminations: crashes, task killers, etc.
|
// For unexpected terminations: crashes, task killers, etc.
|
||||||
// In most cases onDestroy will handle this
|
// In most cases onDestroy will handle this
|
||||||
mTimeline.saveState(this, 0);
|
mTimeline.saveState(0);
|
||||||
break;
|
break;
|
||||||
case PROCESS_SONG:
|
case PROCESS_SONG:
|
||||||
processSong((Song)message.obj);
|
processSong((Song)message.obj);
|
||||||
@ -994,7 +994,7 @@ public final class PlaybackService extends Service implements Handler.Callback,
|
|||||||
id = current.albumId;
|
id = current.albumId;
|
||||||
break;
|
break;
|
||||||
case MediaUtils.TYPE_GENRE:
|
case MediaUtils.TYPE_GENRE:
|
||||||
id = MediaUtils.queryGenreForSong(current.id);
|
id = MediaUtils.queryGenreForSong(this, current.id);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unsupported media type: " + type);
|
throw new IllegalArgumentException("Unsupported media type: " + type);
|
||||||
|
@ -25,6 +25,7 @@ package org.kreed.vanilla;
|
|||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
@ -56,11 +57,12 @@ public class Playlist {
|
|||||||
/**
|
/**
|
||||||
* Queries all the playlists known to the MediaStore.
|
* Queries all the playlists known to the MediaStore.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @return An array of Playlists
|
* @return An array of Playlists
|
||||||
*/
|
*/
|
||||||
public static Playlist[] getPlaylists()
|
public static Playlist[] getPlaylists(Context context)
|
||||||
{
|
{
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri media = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
Uri media = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
||||||
String[] projection = { MediaStore.Audio.Playlists._ID, MediaStore.Audio.Playlists.NAME };
|
String[] projection = { MediaStore.Audio.Playlists._ID, MediaStore.Audio.Playlists.NAME };
|
||||||
String sort = MediaStore.Audio.Playlists.NAME;
|
String sort = MediaStore.Audio.Playlists.NAME;
|
||||||
@ -87,15 +89,16 @@ public class Playlist {
|
|||||||
/**
|
/**
|
||||||
* Retrieves the id for a playlist with the given name.
|
* Retrieves the id for a playlist with the given name.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param name The name of the playlist.
|
* @param name The name of the playlist.
|
||||||
* @return The id of the playlist, or -1 if there is no playlist with the
|
* @return The id of the playlist, or -1 if there is no playlist with the
|
||||||
* given name.
|
* given name.
|
||||||
*/
|
*/
|
||||||
public static long getPlaylist(String name)
|
public static long getPlaylist(Context context, String name)
|
||||||
{
|
{
|
||||||
long id = -1;
|
long id = -1;
|
||||||
|
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Cursor cursor = resolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
Cursor cursor = resolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
new String[] { MediaStore.Audio.Playlists._ID },
|
new String[] { MediaStore.Audio.Playlists._ID },
|
||||||
MediaStore.Audio.Playlists.NAME + "=?",
|
MediaStore.Audio.Playlists.NAME + "=?",
|
||||||
@ -114,13 +117,14 @@ public class Playlist {
|
|||||||
* Create a new playlist with the given name. If a playlist with the given
|
* Create a new playlist with the given name. If a playlist with the given
|
||||||
* name already exists, it will be overwritten.
|
* name already exists, it will be overwritten.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param name The name of the playlist.
|
* @param name The name of the playlist.
|
||||||
* @return The id of the new playlist.
|
* @return The id of the new playlist.
|
||||||
*/
|
*/
|
||||||
public static long createPlaylist(String name)
|
public static long createPlaylist(Context context, String name)
|
||||||
{
|
{
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
long id = getPlaylist(name);
|
long id = getPlaylist(context, name);
|
||||||
|
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
// We need to create a new playlist.
|
// We need to create a new playlist.
|
||||||
@ -140,14 +144,15 @@ public class Playlist {
|
|||||||
/**
|
/**
|
||||||
* Add the given set of song ids to the playlist with the given id.
|
* Add the given set of song ids to the playlist with the given id.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param playlistId The MediaStore.Audio.Playlist id of the playlist to
|
* @param playlistId The MediaStore.Audio.Playlist id of the playlist to
|
||||||
* modify.
|
* modify.
|
||||||
* @param toAdd The MediaStore ids of all the songs to be added to the
|
* @param toAdd The MediaStore ids of all the songs to be added to the
|
||||||
* playlist.
|
* playlist.
|
||||||
*/
|
*/
|
||||||
public static void addToPlaylist(long playlistId, long[] toAdd)
|
public static void addToPlaylist(Context context, long playlistId, long[] toAdd)
|
||||||
{
|
{
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
||||||
String[] projection = new String[] { MediaStore.Audio.Playlists.Members.PLAY_ORDER };
|
String[] projection = new String[] { MediaStore.Audio.Playlists.Members.PLAY_ORDER };
|
||||||
Cursor cursor = resolver.query(uri, projection, null, null, null);
|
Cursor cursor = resolver.query(uri, projection, null, null, null);
|
||||||
@ -168,31 +173,33 @@ public class Playlist {
|
|||||||
/**
|
/**
|
||||||
* Delete the playlist with the given id.
|
* Delete the playlist with the given id.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param id The Media.Audio.Playlists id of the playlist.
|
* @param id The Media.Audio.Playlists id of the playlist.
|
||||||
*/
|
*/
|
||||||
public static void deletePlaylist(long id)
|
public static void deletePlaylist(Context context, long id)
|
||||||
{
|
{
|
||||||
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, id);
|
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, id);
|
||||||
ContextApplication.getContext().getContentResolver().delete(uri, null, null);
|
context.getContentResolver().delete(uri, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rename the playlist with the given id.
|
* Rename the playlist with the given id.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @param id The Media.Audio.Playlists id of the playlist.
|
* @param id The Media.Audio.Playlists id of the playlist.
|
||||||
* @param newName The new name for the playlist.
|
* @param newName The new name for the playlist.
|
||||||
*/
|
*/
|
||||||
public static void renamePlaylist(long id, String newName)
|
public static void renamePlaylist(Context context, long id, String newName)
|
||||||
{
|
{
|
||||||
long existingId = getPlaylist(newName);
|
long existingId = getPlaylist(context, newName);
|
||||||
// We are already called the requested name; nothing to do.
|
// We are already called the requested name; nothing to do.
|
||||||
if (existingId == id)
|
if (existingId == id)
|
||||||
return;
|
return;
|
||||||
// There is already a playlist with this name. Kill it.
|
// There is already a playlist with this name. Kill it.
|
||||||
if (existingId != -1)
|
if (existingId != -1)
|
||||||
deletePlaylist(existingId);
|
deletePlaylist(context, existingId);
|
||||||
|
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
ContentValues values = new ContentValues(1);
|
ContentValues values = new ContentValues(1);
|
||||||
values.put(MediaStore.Audio.Playlists.NAME, newName);
|
values.put(MediaStore.Audio.Playlists.NAME, newName);
|
||||||
resolver.update(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, values, MediaStore.Audio.Playlists._ID + "=" + id, null);
|
resolver.update(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, values, MediaStore.Audio.Playlists._ID + "=" + id, null);
|
||||||
|
@ -146,13 +146,16 @@ public class Song {
|
|||||||
public int flags;
|
public int flags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if it's possible to retrieve any songs, otherwise false. For example, false
|
* Determine if any songs are available from the library.
|
||||||
* could be returned if there are no songs in the library.
|
*
|
||||||
|
* @param context A context to use.
|
||||||
|
* @return True if it's possible to retrieve any songs, false otherwise. For
|
||||||
|
* example, false could be returned if there are no songs in the library.
|
||||||
*/
|
*/
|
||||||
public static boolean isSongAvailable()
|
public static boolean isSongAvailable(Context context)
|
||||||
{
|
{
|
||||||
if (mSongCount == -1) {
|
if (mSongCount == -1) {
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
||||||
Cursor cursor = resolver.query(media, new String[]{"count(_id)"}, selection, null, null);
|
Cursor cursor = resolver.query(media, new String[]{"count(_id)"}, selection, null, null);
|
||||||
@ -169,13 +172,15 @@ public class Song {
|
|||||||
/**
|
/**
|
||||||
* Returns a shuffled array contaning the ids of all the songs on the
|
* Returns a shuffled array contaning the ids of all the songs on the
|
||||||
* device's library.
|
* device's library.
|
||||||
|
*
|
||||||
|
* @param context A context to use.
|
||||||
*/
|
*/
|
||||||
public static long[] loadAllSongs()
|
public static long[] loadAllSongs(Context context)
|
||||||
{
|
{
|
||||||
mAllSongsIdx = 0;
|
mAllSongsIdx = 0;
|
||||||
mRandomCacheEnd = -1;
|
mRandomCacheEnd = -1;
|
||||||
|
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
||||||
Cursor cursor = resolver.query(media, EMPTY_PROJECTION, selection, null, null);
|
Cursor cursor = resolver.query(media, EMPTY_PROJECTION, selection, null, null);
|
||||||
@ -208,13 +213,15 @@ public class Song {
|
|||||||
/**
|
/**
|
||||||
* Returns a song randomly selected from all the songs in the Android
|
* Returns a song randomly selected from all the songs in the Android
|
||||||
* MediaStore.
|
* MediaStore.
|
||||||
|
*
|
||||||
|
* @param context A context to use.
|
||||||
*/
|
*/
|
||||||
public static Song randomSong()
|
public static Song randomSong(Context context)
|
||||||
{
|
{
|
||||||
long[] songs = mAllSongs;
|
long[] songs = mAllSongs;
|
||||||
|
|
||||||
if (songs == null) {
|
if (songs == null) {
|
||||||
songs = loadAllSongs();
|
songs = loadAllSongs(context);
|
||||||
if (songs == null)
|
if (songs == null)
|
||||||
return null;
|
return null;
|
||||||
mAllSongs = songs;
|
mAllSongs = songs;
|
||||||
@ -225,7 +232,7 @@ public class Song {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mAllSongsIdx >= mRandomCacheEnd) {
|
if (mAllSongsIdx >= mRandomCacheEnd) {
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
|
||||||
StringBuilder selection = new StringBuilder("_ID IN (");
|
StringBuilder selection = new StringBuilder("_ID IN (");
|
||||||
@ -346,9 +353,10 @@ public class Song {
|
|||||||
/**
|
/**
|
||||||
* Query the album art for this song.
|
* Query the album art for this song.
|
||||||
*
|
*
|
||||||
|
* @param context A context to use.
|
||||||
* @return The album art or null if no album art could be found
|
* @return The album art or null if no album art could be found
|
||||||
*/
|
*/
|
||||||
public Bitmap getCover()
|
public Bitmap getCover(Context context)
|
||||||
{
|
{
|
||||||
if (id == -1 || mDisableCoverArt)
|
if (id == -1 || mDisableCoverArt)
|
||||||
return null;
|
return null;
|
||||||
@ -358,10 +366,17 @@ public class Song {
|
|||||||
if (cover != null)
|
if (cover != null)
|
||||||
return cover;
|
return cover;
|
||||||
|
|
||||||
Context context = ContextApplication.getContext();
|
|
||||||
ContentResolver res = context.getContentResolver();
|
ContentResolver res = context.getContentResolver();
|
||||||
|
|
||||||
cover = getCoverFromMediaFile(res);
|
try {
|
||||||
|
ParcelFileDescriptor parcelFileDescriptor = res.openFileDescriptor(getCoverUri(), "r");
|
||||||
|
if (parcelFileDescriptor != null) {
|
||||||
|
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
|
||||||
|
cover = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, BITMAP_OPTIONS);
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
}
|
||||||
|
|
||||||
Bitmap deletedCover = mCoverCache.put(id, cover);
|
Bitmap deletedCover = mCoverCache.put(id, cover);
|
||||||
if (deletedCover != null)
|
if (deletedCover != null)
|
||||||
@ -384,30 +399,6 @@ public class Song {
|
|||||||
return Uri.parse("content://media/external/audio/media/" + id + "/albumart");
|
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.
|
|
||||||
*
|
|
||||||
* @param resolver A ContentResolver to use.
|
|
||||||
* @return The album art or null if no album art could be found.
|
|
||||||
*/
|
|
||||||
private Bitmap getCoverFromMediaFile(ContentResolver resolver)
|
|
||||||
{
|
|
||||||
Bitmap cover = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
ParcelFileDescriptor parcelFileDescriptor = resolver.openFileDescriptor(getCoverUri(), "r");
|
|
||||||
if (parcelFileDescriptor != null) {
|
|
||||||
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
|
|
||||||
cover = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, BITMAP_OPTIONS);
|
|
||||||
}
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
@ -62,9 +62,8 @@ public class SongNotification extends Notification {
|
|||||||
* @param song The Song to display information about.
|
* @param song The Song to display information about.
|
||||||
* @param playing True if music is playing.
|
* @param playing True if music is playing.
|
||||||
*/
|
*/
|
||||||
public SongNotification(Song song, boolean playing)
|
public SongNotification(Context context, Song song, boolean playing)
|
||||||
{
|
{
|
||||||
Context context = ContextApplication.getContext();
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
int action = Integer.parseInt(prefs.getString("notification_action", "0"));
|
int action = Integer.parseInt(prefs.getString("notification_action", "0"));
|
||||||
int statusIcon = playing ? R.drawable.status_icon : R.drawable.status_icon_paused;
|
int statusIcon = playing ? R.drawable.status_icon : R.drawable.status_icon_paused;
|
||||||
|
@ -448,7 +448,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
menu.add(0, MENU_DELETE, 0, R.string.delete);
|
menu.add(0, MENU_DELETE, 0, R.string.delete);
|
||||||
|
|
||||||
playlistMenu.add(type, MENU_NEW_PLAYLIST, id, R.string.new_playlist);
|
playlistMenu.add(type, MENU_NEW_PLAYLIST, id, R.string.new_playlist);
|
||||||
Playlist[] playlists = Playlist.getPlaylists();
|
Playlist[] playlists = Playlist.getPlaylists(this);
|
||||||
if (playlists != null) {
|
if (playlists != null) {
|
||||||
for (int i = 0; i != playlists.length; ++i)
|
for (int i = 0; i != playlists.length; ++i)
|
||||||
playlistMenu.add(type, (int)playlists[i].id + 100, id, playlists[i].name);
|
playlistMenu.add(type, (int)playlists[i].id + 100, id, playlists[i].name);
|
||||||
@ -470,8 +470,8 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
*/
|
*/
|
||||||
private void addToPlaylist(long playlistId, int type, long mediaId, CharSequence title)
|
private void addToPlaylist(long playlistId, int type, long mediaId, CharSequence title)
|
||||||
{
|
{
|
||||||
long[] ids = MediaUtils.getAllSongIdsWith(type, mediaId);
|
long[] ids = MediaUtils.getAllSongIdsWith(this, type, mediaId);
|
||||||
Playlist.addToPlaylist(playlistId, ids);
|
Playlist.addToPlaylist(this, playlistId, ids);
|
||||||
|
|
||||||
String message = getResources().getQuantityString(R.plurals.added_to_playlist, ids.length, ids.length, title);
|
String message = getResources().getQuantityString(R.plurals.added_to_playlist, ids.length, ids.length, title);
|
||||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||||
@ -489,7 +489,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
private void delete(int type, long id, String title)
|
private void delete(int type, long id, String title)
|
||||||
{
|
{
|
||||||
if (type == MediaUtils.TYPE_PLAYLIST) {
|
if (type == MediaUtils.TYPE_PLAYLIST) {
|
||||||
Playlist.deletePlaylist(id);
|
Playlist.deletePlaylist(this, id);
|
||||||
String message = getResources().getString(R.string.playlist_deleted, title);
|
String message = getResources().getString(R.string.playlist_deleted, title);
|
||||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
@ -635,7 +635,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
NewPlaylistDialog dialog = (NewPlaylistDialog)message.obj;
|
NewPlaylistDialog dialog = (NewPlaylistDialog)message.obj;
|
||||||
if (dialog.isAccepted()) {
|
if (dialog.isAccepted()) {
|
||||||
String name = dialog.getText();
|
String name = dialog.getText();
|
||||||
long playlistId = Playlist.createPlaylist(name);
|
long playlistId = Playlist.createPlaylist(this, name);
|
||||||
addToPlaylist(playlistId, message.arg1, message.arg2, name);
|
addToPlaylist(playlistId, message.arg1, message.arg2, name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -646,7 +646,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
case MSG_RENAME_PLAYLIST: {
|
case MSG_RENAME_PLAYLIST: {
|
||||||
NewPlaylistDialog dialog = (NewPlaylistDialog)message.obj;
|
NewPlaylistDialog dialog = (NewPlaylistDialog)message.obj;
|
||||||
if (dialog.isAccepted())
|
if (dialog.isAccepted())
|
||||||
Playlist.renamePlaylist(message.arg2, dialog.getText());
|
Playlist.renamePlaylist(this, message.arg2, dialog.getText());
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return super.handleMessage(message);
|
return super.handleMessage(message);
|
||||||
@ -700,11 +700,11 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
mStatusText.setText(text);
|
mStatusText.setText(text);
|
||||||
|
|
||||||
if (mCoverSize == -1) {
|
if (mCoverSize == -1) {
|
||||||
DisplayMetrics metrics = ContextApplication.getContext().getResources().getDisplayMetrics();
|
DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||||
mCoverSize = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 64, metrics);
|
mCoverSize = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 64, metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap cover = CoverBitmap.createScaledBitmap(song, mCoverSize, mCoverSize);
|
Bitmap cover = CoverBitmap.createScaledBitmap(this, song, mCoverSize, mCoverSize);
|
||||||
mCover.setImageBitmap(cover);
|
mCover.setImageBitmap(cover);
|
||||||
mCover.setVisibility(cover == null ? View.GONE : View.VISIBLE);
|
mCover.setVisibility(cover == null ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,8 @@ public final class SongTimeline {
|
|||||||
*/
|
*/
|
||||||
private static final long STATE_FILE_MAGIC = 0xf89daa2fac33L;
|
private static final long STATE_FILE_MAGIC = 0xf89daa2fac33L;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the songs currently contained in the timeline. Each Song object
|
* All the songs currently contained in the timeline. Each Song object
|
||||||
* should be unique, even if it refers to the same media.
|
* should be unique, even if it refers to the same media.
|
||||||
@ -142,6 +144,11 @@ public final class SongTimeline {
|
|||||||
*/
|
*/
|
||||||
private Callback mCallback;
|
private Callback mCallback;
|
||||||
|
|
||||||
|
public SongTimeline(Context context)
|
||||||
|
{
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares the ids of songs.
|
* Compares the ids of songs.
|
||||||
*/
|
*/
|
||||||
@ -172,16 +179,15 @@ public final class SongTimeline {
|
|||||||
* Initializes the timeline with the state stored in the state file created
|
* Initializes the timeline with the state stored in the state file created
|
||||||
* by a call to save state.
|
* by a call to save state.
|
||||||
*
|
*
|
||||||
* @param context The Context to open the state file with
|
|
||||||
* @return The optional extra data, or -1 if loading failed
|
* @return The optional extra data, or -1 if loading failed
|
||||||
*/
|
*/
|
||||||
public int loadState(Context context)
|
public int loadState()
|
||||||
{
|
{
|
||||||
int extra = -1;
|
int extra = -1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
DataInputStream in = new DataInputStream(context.openFileInput(STATE_FILE));
|
DataInputStream in = new DataInputStream(mContext.openFileInput(STATE_FILE));
|
||||||
if (in.readLong() == STATE_FILE_MAGIC) {
|
if (in.readLong() == STATE_FILE_MAGIC) {
|
||||||
int n = in.readInt();
|
int n = in.readInt();
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
@ -207,7 +213,7 @@ public final class SongTimeline {
|
|||||||
// return its results in.
|
// return its results in.
|
||||||
Collections.sort(songs, new IdComparator());
|
Collections.sort(songs, new IdComparator());
|
||||||
|
|
||||||
ContentResolver resolver = context.getContentResolver();
|
ContentResolver resolver = mContext.getContentResolver();
|
||||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
|
||||||
Cursor cursor = resolver.query(media, Song.FILLED_PROJECTION, selection.toString(), null, "_id");
|
Cursor cursor = resolver.query(media, Song.FILLED_PROJECTION, selection.toString(), null, "_id");
|
||||||
@ -263,13 +269,12 @@ public final class SongTimeline {
|
|||||||
* This can be passed to the appropriate constructor to initialize the
|
* This can be passed to the appropriate constructor to initialize the
|
||||||
* timeline with this state.
|
* timeline with this state.
|
||||||
*
|
*
|
||||||
* @param context The Context to open the state file with
|
|
||||||
* @param extra Optional extra data to be included. Should not be -1.
|
* @param extra Optional extra data to be included. Should not be -1.
|
||||||
*/
|
*/
|
||||||
public void saveState(Context context, int extra)
|
public void saveState(int extra)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
DataOutputStream out = new DataOutputStream(context.openFileOutput(STATE_FILE, 0));
|
DataOutputStream out = new DataOutputStream(mContext.openFileOutput(STATE_FILE, 0));
|
||||||
out.writeLong(STATE_FILE_MAGIC);
|
out.writeLong(STATE_FILE_MAGIC);
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
@ -360,7 +365,7 @@ public final class SongTimeline {
|
|||||||
private Song shuffleAll()
|
private Song shuffleAll()
|
||||||
{
|
{
|
||||||
ArrayList<Song> songs = new ArrayList<Song>(mSongs);
|
ArrayList<Song> songs = new ArrayList<Song>(mSongs);
|
||||||
Collections.shuffle(songs, ContextApplication.getRandom());
|
Collections.shuffle(songs, MediaUtils.getRandom());
|
||||||
mShuffledSongs = songs;
|
mShuffledSongs = songs;
|
||||||
return songs.get(0);
|
return songs.get(0);
|
||||||
}
|
}
|
||||||
@ -401,7 +406,7 @@ public final class SongTimeline {
|
|||||||
song = timeline.get(0);
|
song = timeline.get(0);
|
||||||
break;
|
break;
|
||||||
case FINISH_RANDOM:
|
case FINISH_RANDOM:
|
||||||
song = Song.randomSong();
|
song = Song.randomSong(mContext);
|
||||||
timeline.add(song);
|
timeline.add(song);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -473,9 +478,9 @@ public final class SongTimeline {
|
|||||||
{
|
{
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
if (type == MediaUtils.TYPE_PLAYLIST)
|
if (type == MediaUtils.TYPE_PLAYLIST)
|
||||||
cursor = MediaUtils.query(type, id, Song.FILLED_PLAYLIST_PROJECTION, selection);
|
cursor = MediaUtils.query(mContext, type, id, Song.FILLED_PLAYLIST_PROJECTION, selection);
|
||||||
else
|
else
|
||||||
cursor = MediaUtils.query(type, id, Song.FILLED_PROJECTION, selection);
|
cursor = MediaUtils.query(mContext, type, id, Song.FILLED_PROJECTION, selection);
|
||||||
if (cursor == null)
|
if (cursor == null)
|
||||||
return 0;
|
return 0;
|
||||||
int count = cursor.getCount();
|
int count = cursor.getCount();
|
||||||
@ -516,7 +521,7 @@ public final class SongTimeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mShuffle)
|
if (mShuffle)
|
||||||
Collections.shuffle(timeline.subList(start, timeline.size()), ContextApplication.getRandom());
|
Collections.shuffle(timeline.subList(start, timeline.size()), MediaUtils.getRandom());
|
||||||
|
|
||||||
broadcastChangedSongs();
|
broadcastChangedSongs();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user