Подавать mp3-поток для Android с Laravel

Вот моя проблема: я пишу laravel backend, который должен служить mp3-файлу, который должен был быть воспроизведен с использованием стандартного медиаплеера Android.

Для брандмауэра laravel мне нужно использовать JWT для проверки подлинности, поэтому в каждом заголовке запроса я должен установить поле «Авторизация» в « Bearer {token} ».
Маршрут laravel - « / songs / {id} » и обрабатывается таким образом:

public function getSong(Song $song) {
    $file = new File(storage_path()."/songs/".$song->path.".mp3");

    $headers = array();
    $headers['Content-Type'] = 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3';
    $headers['Content-Length'] = $file->getSize();
    $headers['Content-Transfer-Encoding'] = 'binary';
    $headers['Accept-Range'] = 'bytes';
    $headers['Cache-Control'] = 'must-revalidate, post-check=0, pre-check=0';
    $headers['Connection'] = 'Keep-Alive';
    $headers['Content-Disposition'] = 'attachment; filename="'.$song->path.'.mp3"';

    $user = Auth::user();
    if($user->activated_at) {
        return Response::download($file, $song->path, $headers);
    }
    App::abort(400);
}

На стороне Android я использую MediaPlayer для потоковой передачи mp3-файла таким образом:

media_player = new MediaPlayer();
    try {
        media_player.setAudioStreamType(AudioManager.STREAM_MUSIC);

        String token = getSharedPreferences("p_shared", MODE_PRIVATE).getString("token", null);
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + token);

        media_player.setDataSource(
            getApplicationContext(),
            Uri.parse(ConnectionHelper.SERVER + "/songs/" + song.getId()),
            headers
        );
    } catch (IOException e) {
        finish();
        Toast.makeText(
                Round.this,
                "Some error occurred. Retry in some minutes.",
                Toast.LENGTH_SHORT
        ).show();
    }
    media_player.setOnCompletionListener(this);
    media_player.setOnErrorListener(this);
    media_player.setOnPreparedListener(this);

Но каждый раз, когда я выполняю код, я получаю дополнительный код -1005 на прослушивателе ошибок, что означает ERROR_CONNECTION_LOST .

android,laravel,streaming,mp3,android-mediaplayer,

2

Ответов: 1


3 принят

Проблема : Response :: download (...) не создает поток, поэтому я не могу обслуживать файл .mp3.

Решение : как документ Symfony HttpFoundation . говорит в пункте обслуживающего файла:

"if you are serving a static file, you can use a BinaryFileResponse"

Файлы .mp3, которые мне нужно обслуживать, - это статика на сервере и хранятся в « / storage / songs / », поэтому я решил использовать BinaryFileResponse , а метод для обслуживания .mp3 стал:

use SymfonyComponentHttpFoundationBinaryFileResponse;

[...]

public function getSong(Song $song) {
    $path = storage_path().DIRECTORY_SEPARATOR."songs".DIRECTORY_SEPARATOR.$song->path.".mp3");

    $user = Auth::user();
    if($user->activated_at) {
        $response = new BinaryFileResponse($path);
        BinaryFileResponse::trustXSendfileTypeHeader();

        return $response;
    }
    App::abort(400);
}

BinaryFileResponse автоматически обрабатывает запросы и позволяет полностью обслуживать файл (путем создания только одного запроса с кодом Http 200) или разделить на медленное соединение (больше запросов с кодом Http 206 и один окончательный запрос с кодом 200).
Если у вас есть файл mod_xsend, который вы можете использовать (для ускорения потоковой передачи), добавив:

BinaryFileResponse::trustXSendfileTypeHeader();

Код для андроида не нужно изменять для потоковой передачи файла.

андроид, Laravel, потоковое, mp3, андроид-медиаплеер,
Похожие вопросы
Яндекс.Метрика