7

I'm running into a roadblock integrating music into my Android app. The goal is just to let users see & play songs to which they already have access, via Google Play Music (or any other player such as Winamp, Poweramp, doubleTwist, etc.).

So far, I've tried a couple of approaches, but each has problems.

Approach #1: Use a ContentResolver query to get playlists & songs from Google Play music, then play using MediaPlayer

First, get a cursor on the play lists:

String[] proj = { MediaStore.Audio.Playlists.NAME,
                  MediaStore.Audio.Playlists._ID };
Uri playlistUri = Uri.parse("content://com.google.android.music.MusicContent/playlists");
Cursor playlistCursor = getContentResolver().query(playlistUri, proj, null, null, null);

Then iterate to get the songs in each playlist, and read them like this:

String[] proj2 = { MediaStore.Audio.Playlists.Members.TITLE,
                   MediaStore.Audio.Playlists.Members._ID };
String playListRef = "content://com.google.android.music.MusicContent/playlists/" + playListId + "/members";
Uri songUri = Uri.parse(playListRef);
Cursor songCursor = getContentResolver().query(songUri, proj2, null, null, null);

This works to get the playlists and songs, but then you can't actually play them (even if you tell Google Play Music to "Keep on device"). Specifically, the following code does not play a given song found as above:

mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
    mediaPlayer.setDataSource(dataPath);
    mediaPlayer.prepare();
    mediaPlayer.start();
} catch (Exception e) {}

In fact, I've scanned the device, and have not been able to find the files anywhere (even though I've confirmed they are local by fully disabling the network -- on both Galaxy Nexus and Galaxy S3).

Approach #2: Invoke Google Play Music, or other player, using an Intent

According to this post, you can simply invoke the player using Intents, like this:

Intent intent = new Intent();  
intent.setAction(android.content.Intent.ACTION_VIEW);  
File file = new File(YOUR_SONG_URI);  
intent.setDataAndType(Uri.fromFile(file), "audio/*");  
startActivity(intent);

But I don't think this approach allows for any kind of control -- for example, passing a specific song to be played, or being notified when a song is done being played. Furthermore, @CommonWares points out that the music app and its Intents are not part of the Android SDK's public API, and could change without warning.

The basic functionality I'm trying to achieve exists in iOS, thanks to tight integration with iTunes. I would think that Google would want to achieve the same kind of integration, since it could mean selling a lot more music in the Play store.

In Summary: Is it possible to let users see & play songs to which they already have access on Android? What's the best way to do this with Google Play Music, or any other app? Thanks.

Community
  • 1
  • 1
gcl1
  • 4,070
  • 11
  • 38
  • 55
  • 1
    UPDATE: until I find a good answer for integrating with Google Play Music or another music player, I've just developed an interface that reads and plays music files stored locally on the device (using a ContentResolver query to find the songs, and MediaPlayer to play them). This seems to work fine, but it leaves it up to the user to move mp3 and other music files onto the device. I'd still prefer to find a solution that makes it easy for everyone by providing good integration with a popular music player .... Anyone? – gcl1 Dec 26 '12 at 13:10
  • I think your approach #1 should work if you obtain the streaming url corresponding to the selected track and pass it to the MediaPlayer. – Draško Kokić Apr 24 '13 at 23:02
  • When I last tried back in December, I was unable to make approach #1 work. But I would be very interested to know if you have actually done it. In the meantime, as I said in the UPDATE comment, I am just letting users play music that is stored locally on the device. Thanks. – gcl1 Apr 25 '13 at 01:41
  • hey there, were you able to query and play music a user has already bought on Google Play? – vinnybad Jun 01 '13 at 06:03

1 Answers1

1

Approach #1 kinda works (tested with local music on device), thanks OP for the direction.

Notes:

  • We're playing with an undocumented internal API here - it's not reliable.
  • I don't have access to online/purchased music in Google Play Music, so the answer refers to locally stored music only.

The code below will iterate on all songs in a playlist and play the last one.

Note the "SourceId" column - it's the audio id you'd use as per documentation. I found it by iterating on all columns returned by the cursor. There are several more interesting columns there, like "hasLocal", "hasRemote" which might (or not) refer to where the music is stored.

String[] proj2 = { "SourceId", MediaStore.Audio.Playlists.Members.TITLE, MediaStore.Audio.Playlists.Members._ID };
String playListRef = "content://com.google.android.music.MusicContent/playlists/" + playListId + "/members";
Uri songUri = Uri.parse(playListRef);
Cursor songCursor = getContentResolver().query(songUri, proj2, null, null, null);

long audioId = -1;
while (songCursor.moveToNext()) {
    audioId = songCursor.getLong(songCursor.getColumnIndex("SourceId"));
    String title = songCursor.getString(songCursor.getColumnIndex(MediaStore.Audio.Playlists.Members.TITLE));
    Log.v("", "audioId: " + audioId + ", title: " + title);
}
songCursor.close();

MediaPlayer mpObject = new MediaPlayer();
try {
    if (audioId > 0) {
        Uri contentUri = ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, Long.valueOf(audioId));
        mpObject.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mpObject.setDataSource(this, contentUri);
        mpObject.prepare();
        mpObject.start();

    }
} catch (Exception e) {
    e.printStackTrace();
}
Toren
  • 11
  • 1