from Music2, to make it easier to share code between the two.
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.AsyncQueryHandler;
private final static int SEARCH = CHILD_MENU_BASE;
private static int mLastListPosCourse = -1;
private static int mLastListPosFine = -1;
+ private ServiceToken mToken;
public AlbumBrowserActivity()
{
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
- MusicUtils.bindToService(this, this);
+ mToken = MusicUtils.bindToService(this, this);
IntentFilter f = new IntentFilter();
f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
mLastListPosFine = cv.getTop();
}
}
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
// If we have an adapter and didn't send it off to another activity yet, we should
// close its cursor, which we do by assigning a null cursor to it. Doing this
// instead of closing the cursor directly keeps the framework from accessing
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
import com.android.music.QueryBrowserActivity.QueryListAdapter.QueryHandler;
import android.app.ExpandableListActivity;
private final static int SEARCH = CHILD_MENU_BASE;
private static int mLastListPosCourse = -1;
private static int mLastListPosFine = -1;
+ private ServiceToken mToken;
/** Called when the activity is first created. */
@Override
mCurrentArtistId = icicle.getString("selectedartist");
mCurrentArtistName = icicle.getString("selectedartistname");
}
- MusicUtils.bindToService(this, this);
+ mToken = MusicUtils.bindToService(this, this);
IntentFilter f = new IntentFilter();
f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
}
}
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
// If we have an adapter and didn't send it off to another activity yet, we should
// close its cursor, which we do by assigning a null cursor to it. Doing this
// instead of closing the cursor directly keeps the framework from accessing
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
public class MediaPickerActivity extends ListActivity implements MusicUtils.Defs
{
+ private ServiceToken mToken;
public MediaPickerActivity()
{
} else {
setTitle(mFirstYear + "-" + mLastYear);
}
- MusicUtils.bindToService(this);
+ mToken = MusicUtils.bindToService(this);
init();
}
@Override
public void onDestroy() {
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
super.onDestroy();
if (mCursor != null) {
mCursor.close();
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.KeyguardManager;
private AlbumArtHandler mAlbumArtHandler;
private Toast mToast;
private int mTouchSlop;
+ private ServiceToken mToken;
public MediaPlaybackActivity()
{
}
mHandler.removeMessages(REFRESH);
unregisterReceiver(mStatusListener);
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
mService = null;
super.onStop();
}
super.onStart();
paused = false;
- if (false == MusicUtils.bindToService(this, osc)) {
+ mToken = MusicUtils.bindToService(this, osc);
+ if (mToken == null) {
// something went wrong
mHandler.sendEmptyMessage(QUIT);
}
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
public class MusicBrowserActivity extends Activity
implements MusicUtils.Defs {
+ private ServiceToken mToken;
+
public MusicBrowserActivity() {
}
String shuf = getIntent().getStringExtra("autoshuffle");
if ("true".equals(shuf)) {
- bindService((new Intent()).setClass(this, MediaPlaybackService.class), autoshuffle, 0);
+ mToken = MusicUtils.bindToService(this, autoshuffle);
}
}
@Override
public void onDestroy() {
- MusicUtils.unbindFromService(this);
+ if (mToken != null) {
+ MusicUtils.unbindFromService(mToken);
+ }
super.onDestroy();
}
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.view.MenuItem.OnMenuItemClickListener;
import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.Toast;
public static IMediaPlaybackService sService = null;
private static HashMap<Context, ServiceBinder> sConnectionMap = new HashMap<Context, ServiceBinder>();
- public static boolean bindToService(Context context) {
+ public static class ServiceToken {
+ ContextWrapper mWrappedContext;
+ ServiceToken(ContextWrapper context) {
+ mWrappedContext = context;
+ }
+ }
+
+ public static ServiceToken bindToService(Context context) {
return bindToService(context, null);
}
- public static boolean bindToService(Context context, ServiceConnection callback) {
- context.startService(new Intent(context, MediaPlaybackService.class));
+ public static ServiceToken bindToService(Context context, ServiceConnection callback) {
+ ContextWrapper cw = new ContextWrapper(context);
+ cw.startService(new Intent(cw, MediaPlaybackService.class));
ServiceBinder sb = new ServiceBinder(callback);
- sConnectionMap.put(context, sb);
- return context.bindService((new Intent()).setClass(context,
- MediaPlaybackService.class), sb, 0);
+ if (cw.bindService((new Intent()).setClass(cw, MediaPlaybackService.class), sb, 0)) {
+ sConnectionMap.put(cw, sb);
+ return new ServiceToken(cw);
+ }
+ return null;
}
-
- public static void unbindFromService(Context context) {
- ServiceBinder sb = (ServiceBinder) sConnectionMap.remove(context);
+
+ public static void unbindFromService(ServiceToken token) {
+ ContextWrapper cw = token.mWrappedContext;
+ ServiceBinder sb = sConnectionMap.remove(cw);
if (sb == null) {
Log.e("MusicUtils", "Trying to unbind for unknown Context");
return;
}
- context.unbindService(sb);
+ cw.unbindService(sb);
if (sConnectionMap.isEmpty()) {
// presumably there is nobody interested in the service at this point,
// so don't hang on to the ServiceConnection
}
private final static long [] sEmptyList = new long[0];
-
+
public static long [] getSongListForCursor(Cursor cursor) {
if (cursor == null) {
return sEmptyList;
} catch (RemoteException ex) {
}
}
+
+ private static ContentValues[] sContentValuesCache = null;
+
+ /**
+ * @param ids The source array containing all the ids to be added to the playlist
+ * @param offset Where in the 'ids' array we start reading
+ * @param len How many items to copy during this pass
+ * @param base The play order offset to use for this pass
+ */
+ private static void makeInsertItems(long[] ids, int offset, int len, int base) {
+ // adjust 'len' if would extend beyond the end of the source array
+ if (offset + len > ids.length) {
+ len = ids.length - offset;
+ }
+ // allocate the ContentValues array, or reallocate if it is the wrong size
+ if (sContentValuesCache == null || sContentValuesCache.length != len) {
+ sContentValuesCache = new ContentValues[len];
+ }
+ // fill in the ContentValues array with the right values for this pass
+ for (int i = 0; i < len; i++) {
+ if (sContentValuesCache[i] == null) {
+ sContentValuesCache[i] = new ContentValues();
+ }
+
+ sContentValuesCache[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, base + offset + i);
+ sContentValuesCache[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, ids[offset + i]);
+ }
+ }
public static void addToPlaylist(Context context, long [] ids, long playlistid) {
if (ids == null) {
Log.e("MusicBase", "ListSelection null");
} else {
int size = ids.length;
- ContentValues values [] = new ContentValues[size];
ContentResolver resolver = context.getContentResolver();
// need to determine the number of items currently in the playlist,
// so the play_order field can be maintained.
cur.moveToFirst();
int base = cur.getInt(0);
cur.close();
-
- for (int i = 0; i < size; i++) {
- values[i] = new ContentValues();
- values[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + i));
- values[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, ids[i]);
+ int numinserted = 0;
+ for (int i = 0; i < size; i += 1000) {
+ makeInsertItems(ids, i, 1000, base);
+ numinserted += resolver.bulkInsert(uri, sContentValuesCache);
}
- resolver.bulkInsert(uri, values);
String message = context.getResources().getQuantityString(
- R.plurals.NNNtrackstoplaylist, size, Integer.valueOf(size));
+ R.plurals.NNNtrackstoplaylist, numinserted, numinserted);
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
//mLastPlaylistSelected = playlistid;
}
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.ListActivity;
import android.content.AsyncQueryHandler;
import android.content.BroadcastReceiver;
private static int mLastListPosFine = -1;
private boolean mCreateShortcut;
+ private ServiceToken mToken;
public PlaylistBrowserActivity()
{
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
- MusicUtils.bindToService(this, new ServiceConnection() {
+ mToken = MusicUtils.bindToService(this, new ServiceConnection() {
public void onServiceConnected(ComponentName classname, IBinder obj) {
if (Intent.ACTION_VIEW.equals(action)) {
long id = Long.parseLong(intent.getExtras().getString("playlist"));
mLastListPosFine = cv.getTop();
}
}
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
// If we have an adapter and didn't send it off to another activity yet, we should
// close its cursor, which we do by assigning a null cursor to it. Doing this
// instead of closing the cursor directly keeps the framework from accessing
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.AsyncQueryHandler;
private QueryListAdapter mAdapter;
private boolean mAdapterSent;
private String mFilterString = "";
+ private ServiceToken mToken;
public QueryBrowserActivity()
{
super.onCreate(icicle);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mAdapter = (QueryListAdapter) getLastNonConfigurationInstance();
- MusicUtils.bindToService(this, this);
+ mToken = MusicUtils.bindToService(this, this);
// defer the real work until we're bound to the service
}
@Override
public void onDestroy() {
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
unregisterReceiver(mScanListener);
// If we have an adapter and didn't send it off to another activity yet, we should
// close its cursor, which we do by assigning a null cursor to it. Doing this
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
public class StreamStarter extends Activity
{
+ private ServiceToken mToken;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
public void onResume() {
super.onResume();
- MusicUtils.bindToService(this, new ServiceConnection() {
+ mToken = MusicUtils.bindToService(this, new ServiceConnection() {
public void onServiceConnected(ComponentName classname, IBinder obj) {
try {
IntentFilter f = new IntentFilter();
}
}
unregisterReceiver(mStatusListener);
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
super.onPause();
}
}
package com.android.music;
+import com.android.music.MusicUtils.ServiceToken;
+
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.AsyncQueryHandler;
private static int mLastListPosCourse = -1;
private static int mLastListPosFine = -1;
private boolean mUseLastListPos = false;
+ private ServiceToken mToken;
public TrackBrowserActivity()
{
mAdapter.setActivity(this);
setListAdapter(mAdapter);
}
- MusicUtils.bindToService(this, this);
+ mToken = MusicUtils.bindToService(this, this);
// don't set the album art until after the view has been layed out
mTrackList.post(new Runnable() {
mLastListPosFine = cv.getTop();
}
}
- MusicUtils.unbindFromService(this);
+ MusicUtils.unbindFromService(mToken);
try {
if ("nowplaying".equals(mPlaylist)) {
unregisterReceiverSafe(mNowPlayingListener);