2016-05-31 48 views
1

這裏是我的問題:我正在寫一個laravel後端,它必須提供一個mp3文件,必須通過使用android標準媒體播放器進行復制。

對於laravel後端,我需要使用JWT來處理身份驗證,所以在每個請求標題上,我必須將「授權」字段設置爲「承載者{令牌}」。
的laravel路徑爲「/歌曲/ {ID}」,並以這種方式處理:爲Laravel提供的Android流式服務MP3

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

回答

2

問題響應::下載(...)不產生流,所以我不能爲我的.MP3文件。

解決方案: 因爲symfony HttpFoundation doc.說,在文件服務段落:

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

的.mp3文件我需要服務的服務器靜態和存儲在「/存儲/歌曲/「,所以我決定用BinaryFileResponse,併爲服務.MP3的方法變成了:

use Symfony\Component\HttpFoundation\BinaryFileResponse; 

[...] 

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_xsendfile你可以使用(使流更快)加入:

BinaryFileResponse::trustXSendfileTypeHeader(); 

Android的代碼並不需要以流的文件來改變。