Как разрешить пользователям просматривать и воспроизводить песни на Android, к которым у них уже есть доступ (например, через Google Play)?

Я столкнулся с препятствием при интеграции музыки в свое приложение для Android. Цель состоит в том, чтобы позволить пользователям просматривать и воспроизводить песни, к которым у них уже есть доступ, через Google Play Music (или любой другой проигрыватель, такой как Winamp, Poweramp, doubleTwist и т. д.).

До сих пор я пробовал несколько подходов, но у каждого есть проблемы.

Подход 1. Используйте запрос ContentResolver, чтобы получить плейлисты и песни из Google Play Музыки, а затем воспроизвести их с помощью MediaPlayer

Сначала наведите курсор на списки воспроизведения:

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);

Затем повторите, чтобы получить песни в каждом плейлисте, и прочитайте их следующим образом:

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);

Это работает для получения списков воспроизведения и песен, но тогда вы не можете их воспроизвести (даже если вы скажете Google Play Music «Сохранить на устройстве»). В частности, следующий код не воспроизводит указанную выше песню:

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

На самом деле, я просканировал устройство и нигде не смог найти файлы (хотя я подтвердил, что они локальные, полностью отключив сеть — как на Galaxy Nexus, так и на Galaxy S3).

Подход 2. Вызов Google Play Музыки или другого проигрывателя с помощью намерения

Согласно этой публикации, вы можете просто вызвать проигрыватель с помощью намерений, например :

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);

Но я не думаю, что этот подход допускает какой-либо контроль — например, передачу конкретной песни для воспроизведения или уведомление о завершении воспроизведения песни. Кроме того, @CommonWares указывает, что музыкальное приложение и его намерения не являются частью общедоступного API Android SDK и могут быть изменены без предупреждения.

Основная функциональность, которую я пытаюсь реализовать, существует в iOS благодаря тесной интеграции с iTunes. Я думаю, что Google захочет добиться такой же интеграции, поскольку это может означать продажу гораздо большего количества музыки в магазине Play.

Вкратце: можно ли позволить пользователям просматривать и воспроизводить песни, к которым у них уже есть доступ на Android? Как лучше всего это сделать с помощью Google Play Music или любого другого приложения? Спасибо.


comment
ОБНОВЛЕНИЕ: пока я не найду хороший ответ для интеграции с Google Play Music или другим музыкальным проигрывателем, я только что разработал интерфейс, который читает и воспроизводит музыкальные файлы, хранящиеся локально на устройстве (используя запрос ContentResolver для поиска песен и MediaPlayer для играть в них). Кажется, это работает нормально, но пользователь может перемещать mp3 и другие музыкальные файлы на устройство. Я все же предпочел бы найти решение, которое упростило бы задачу для всех, обеспечивая хорошую интеграцию с популярным музыкальным проигрывателем.... Кому-нибудь?   -  person gcl1    schedule 26.12.2012
comment
Я думаю, что ваш подход № 1 должен работать, если вы получите URL-адрес потоковой передачи, соответствующий выбранной дорожке, и передадите его в MediaPlayer.   -  person Draško Kokić    schedule 25.04.2013
comment
Когда я в последний раз пытался в декабре, мне не удалось заставить работать подход №1. Но мне было бы очень интересно узнать, действительно ли вы это сделали. А пока, как я сказал в комментарии UPDATE, я просто позволяю пользователям воспроизводить музыку, которая хранится локально на устройстве. Спасибо.   -  person gcl1    schedule 25.04.2013
comment
здравствуйте, вам удалось запросить и воспроизвести музыку, которую пользователь уже купил в Google Play?   -  person vinnybad    schedule 01.06.2013


Ответы (1)


Подход № 1 вроде работает (проверено с местной музыкой на устройстве), спасибо ОП за направление.

Примечания:

  • Здесь мы играем с недокументированным внутренним API — это ненадежно.
  • У меня нет доступа к онлайн-/покупной музыке в Google Play Music, поэтому ответ относится только к музыке, хранящейся локально.

Приведенный ниже код будет перебирать все песни в списке воспроизведения и воспроизводить последнюю.

Обратите внимание на столбец SourceId — это идентификатор аудио, который вы должны использовать в соответствии с документация. Я нашел его, перебирая все столбцы, возвращаемые курсором. Там есть еще несколько интересных столбцов, таких как «hasLocal», «hasRemote», которые могут (или не) относиться к тому, где хранится музыка.

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();
}
person Toren    schedule 19.07.2013