Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to let users see & play songs on Android to which they already have access (e.g., via Google Play)?

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.

like image 394
gcl1 Avatar asked Dec 17 '12 22:12

gcl1


1 Answers

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();
}
like image 185
Toren Avatar answered Nov 01 '22 20:11

Toren