Как использовать API MediaStore для восстановления песни и ее воспроизведения? Кроме того, получить его обложку и, если возможно, прочитать поток ввода? - PullRequest
0 голосов
/ 07 февраля 2020
package com.devrj.helium.data_model

import android.content.ContentUris.withAppendedId
import android.content.Context
import android.net.Uri
import android.os.CancellationSignal
import android.provider.MediaStore.Audio.Media.*
import com.devrj.helium.model.entity.TrackEntity

class MediaStoreDataStream(streamInfo: () -> Context) :
    DataStream<Context, TrackEntity>(streamInfo) {

    private var cancellationSignal: CancellationSignal? = null

    companion object {
        private const val COL_ID = 0
        private const val COL_TITLE = 1
        private const val COL_SIZE = 2
        private const val COL_ARTIST = 3
        private const val COL_ALBUM = 4
        private const val COL_YEAR = 5
        private const val COL_TRACK = 6
        private const val COL_DATE_MODIFIED = 7
        private const val COL_DATE_ADDED = 8
        private const val COL_DISPLAY_NAME = 9
        private const val COL_DATA = 10

        val projection = arrayOf(
            _ID,
            TITLE,
            SIZE,
            ARTIST,
            ALBUM,
            YEAR,
            TRACK,
            DATE_MODIFIED,
            DATE_ADDED,
            DISPLAY_NAME,
            DATA
        )
    }

    override fun stopStream() {
        super.stopStream()
        cancellationSignal?.cancel()
    }


    override fun onStreamStarted() {
        val context = streamInfo()


        val contentResolver = context.contentResolver

        cancellationSignal = CancellationSignal()

        val trackQuery = contentResolver.query(
            EXTERNAL_CONTENT_URI,
            projection,
            null,
            null,
            null,
            cancellationSignal
        )
        trackQuery?.use { cursor ->
            /*
            Cache column indices
             */
            val columns = Array(projection.size) { i ->
                cursor.getColumnIndex(projection[i])
            }
            /*
            Per entity
             */
            while (cursor.moveToNext()) {

                val columnId = cursor.getLong(columns[COL_ID])

                val locationURI: Uri = withAppendedId(INTERNAL_CONTENT_URI, columnId)


                ////////////////////////////////////////////////////
                //////////////////CREATE NEW ENTITY/////////////////
                ////////////////////////////////////////////////////

                val newTrack = TrackEntity(columnId)

                newTrack.apply {
                    uri = locationURI.path.toString()
                    size = cursor.getLong(columns[COL_SIZE])
                    title = cursor.getString(columns[COL_TITLE])
                    artist = cursor.getString(columns[COL_ARTIST])
                    album = cursor.getString(columns[COL_ALBUM])
                    track = cursor.getInt(columns[COL_TRACK])
                    dateModified = cursor.getLong(columns[COL_DATE_MODIFIED])
                    dateAdded = cursor.getLong(columns[COL_DATE_ADDED])
                    dateAccessed = cursor.getLong(columns[COL_DATE_ADDED])
                    year = cursor.getLong(columns[COL_YEAR])
                    displayName = cursor.getString(columns[COL_DISPLAY_NAME])
                    filePath = cursor.getString(columns[COL_DATA])
                }

                send(newTrack)

                newTrack.deb()

            }
        }

    }


}

Недавно я начал изучать API MediaStore, и, поскольку я создаю приложение проигрывателя musi c, я подумал, что было бы полезно перейти на него из-за всех преимуществ производительности.
Однако, Я не могу сыграть ни одной песни или восстановить ее обложку. Как мне этого добиться?

Вот как я пытаюсь воспроизвести песню

            val resolver: ContentResolver = onContextRequest!!.onRequest().contentResolver
            val mode = "rw"

            try {

                val uri = Uri.parse(Stem.get().loadedTrack.data!!.uri)

                uri.toast(onContextRequest!!.onRequest())

                resolver.openFileDescriptor(uri, mode).use {

                    player!!.setDataSource(it!!.fileDescriptor)
                }

            } catch (e: IOException) {
                e.printStackTrace()
                "ERROR $e".longToast(onContextRequest!!.onRequest())
            }

И я получаю исключение FileNotFoundException

ERROR java.io.FileNotFoundException: No content provider: /internal/audio/<some_id>

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

В официальной документации android указано, как это сделать. Что я и делаю

https://developer.android.com/training/data-storage/shared/media#open -файл

Это все разрешения, которые я объявил (да, они предоставляются во время выполнения)

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

1 Ответ

0 голосов
/ 08 февраля 2020

Я не вижу, что такое EXTERNAL_CONTENT_URI. Если вы используете Android Q, тогда используйте

Uri mediaUri = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);

Затем создайте файл ContentUri как

contentUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, _id);

Используйте этот URI для запуска MediaMetaRetriever, чтобы получить albumart

MediaMetadataRetriever mmr = new MediaMetadataRetriever();
byte[] img = mmr.getEmbeddedPicture();

Вы можете играть в этот URI как

mMediaplayer.setDataSource(mContext, uri);

Надеюсь, что это поможет. Не забудьте установить разрешения на запуск.

GGK

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...