2015-06-17 2 views
-1

Я пытаюсь реализовать функцию в приложении, которое я делаю, что позволяет пользователю прослушивать онлайн-поток. Что мне нужно сделать, так это загрузить файл вместе с его воспроизведением.Как загружать и передавать аудио в Android?

Я так много вычислил, что мне нужен локальный HTTP-сервер, который я использовал NanoHTTPD. Теперь сложной частью является то, как фактически загружать и передавать аудио одновременно.

Это код, который я придумал до сих пор:

public class LocalHttpServer extends NanoHTTPD { 
    public static final int SERVER_PORT = 5987; 
    private String mUrl; 
    private InputStream input; 
    private FileOutputStream output; 

    public LocalHttpServer(String url) { 
     super(SERVER_PORT); 
     mUrl = url; 
    } 

    private File createFile(String url) { 
     File path = new File(MyApplication.getContext().getFilesDir(), "audio/"); 
     path.mkdirs(); 

     return new File(path, Util.md5(url)); 
    } 

    @Override 
    public Response serve(IHTTPSession session) { 
     input = null; 
     output = null; 
     HttpURLConnection connection = null; 
     try { 
      URL url = new URL(mUrl); 
      connection = (HttpURLConnection) url.openConnection(); 
      connection.connect(); 
      if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { 
       return new Response(Response.Status.BAD_REQUEST, "audio/mpeg3", null, 0); 
      } 
      int fileLength = connection.getContentLength(); 

      input = connection.getInputStream(); 
      output = new FileOutputStream(createFile(mUrl)); 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        byte data[] = new byte[4096]; 
        int count; 
        try { 
         while ((count = input.read(data)) != -1) { 
          output.write(data, 0, count); 
         } 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } finally { 
         try { 
          if (output != null) 
           output.close(); 
          if (input != null) 
           //input.close(); don't close it 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      }).start(); 
      return new Response(Response.Status.OK, "audio/mpeg3", input, fileLength); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return new Response(Response.Status.BAD_REQUEST, "audio/mpeg3", null, 0); 
    } 
} 

Проблема с ним, когда подается в MediaPlayer, происходит the unexpected end of stream исключение.

+0

Вы можете попробовать использовать https://github.com/google/ExoPlayer#, который также работает только с аудио. –

+0

@HugoGresse Хорошо, похоже, что он работает, но как я могу использовать ExoPlayer для сохранения файла ? –

+0

Зачем вы хотите сохранить файл? –

ответ

1

Поскольку никто не отправил ответ на мой вопрос, я привожу сюда еще одно решение, которое я использовал для выполнения аналогичной задачи.

Я понял, что могу использовать AsyncTask для загрузки файла, и когда загрузка достигла 10% от всего запуска, MediaPlayer использует обратные вызовы интерфейса. И после обновления MediaPlayer, когда загружается еще 20%.

Вот источник для указанного AsyncTask: https://gist.github.com/2hamed/63a31bd55fc6514d12b5

public class DownloadAndPlayAsyncTask extends AsyncTask<String, Integer, Integer> { 
    private static final String TAG = "DownloadAndPlayAsync"; 
    DownloadCallback downloadCallback; 
    File tempFile, fullFile; 

    private void createFiles(String url) { 
     tempFile = Util.getTempFilePath(url); 
     fullFile = Util.getFilePath(url); 
    } 

    public void setOnDownloadCallback(DownloadCallback callback) { 
     downloadCallback = callback; 
    } 

    @Override 
    protected Integer doInBackground(String... strings) { 

     if (Util.isFileDownloaded(strings[0])) { 
      createFiles(strings[0]); 
      return 1; 
     } 
     InputStream input = null; 
     OutputStream output = null; 
     HttpURLConnection connection = null; 
     try { 
      URL url = new URL(strings[0]); 
      connection = (HttpURLConnection) url.openConnection(); 
      connection.connect(); 

      // expect HTTP 200 OK, so we don't mistakenly save error report 
      // instead of the file 
      if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { 
       Log.d(TAG, "Server returned HTTP " + connection.getResponseCode() 
         + " " + connection.getResponseMessage()); 
       return -1; 
      } 

      // this will be useful to display download percentage 
      // might be -1: server did not report the length 
      int fileLength = connection.getContentLength(); 
      createFiles(strings[0]); 
      // download the file 
      input = connection.getInputStream(); 
      output = new FileOutputStream(tempFile); 

      byte data[] = new byte[4096]; 
      long total = 0; 
      int count; 
      while ((count = input.read(data)) != -1) { 
       // allow canceling with back button 
       if (isCancelled()) { 
        input.close(); 
        return null; 
       } 
       total += count; 
       // publishing the progress.... 
       if (fileLength > 0) // only if total length is known 
        publishProgress((int) (total * 100/fileLength)); 
       output.write(data, 0, count); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return -1; 
     } finally { 
      try { 
       if (output != null) 
        output.close(); 
       if (input != null) 
        input.close(); 
      } catch (IOException ignored) { 
      } 

      if (connection != null) 
       connection.disconnect(); 
     } 
     return 0; 
    } 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
    } 

    @Override 
    protected void onPostExecute(Integer result) { 
     super.onPostExecute(result); 
     if (result == 0) { 
      try { 
       Util.copy(tempFile, fullFile); 
       tempFile.delete(); 
       if (downloadCallback != null) { 
        downloadCallback.onFinished(fullFile.getAbsolutePath()); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } else if (result == 1) { 
      if (downloadCallback != null) { 
       downloadCallback.onFinished(fullFile.getAbsolutePath()); 
      } 
     } else { 
      if (downloadCallback != null) { 
       downloadCallback.onFailed(); 
      } 
     } 
    } 

    @Override 
    protected void onProgressUpdate(Integer... values) { 
     super.onProgressUpdate(values); 
     if (downloadCallback != null) { 
      downloadCallback.onProgressUpdate(values[0], tempFile.getAbsolutePath()); 
     } 
    } 

    @Override 
    protected void onCancelled(Integer result) { 
     super.onCancelled(result); 
    } 

    @Override 
    protected void onCancelled() { 
     super.onCancelled(); 
    } 

    public interface DownloadCallback { 
     void onProgressUpdate(int progress, String filePath); 

     void onFinished(String fullFile); 

     void onFailed(); 
    } 
} 

, если вы заметили, есть DownloadCallback в конце кода.