2015-12-19 14 views
9

Tôi muốn triển khai chức năng phát video trực tuyến cùng với việc tải xuống. Tôi có nghĩa là cùng một luồng tải xuống nên được sử dụng để tải xuống và phát để video có thể được lưu để sử dụng ngoại tuyến và ngăn chặn hai lần chi phí dữ liệu để phát và tải xuống riêng biệt.Tải xuống video cùng với chơi

Cho đến nay tôi đã triển khai tải xuống video với asyncTask và phát video trên OnPostExecute. Sau đây là mã:

public class MainActivity extends AppCompatActivity { 


private Button btnPlay; 
private MediaPlayer player; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 
    outFilePath = getExternalFilesDir("/") + "/video.mp4"; 
    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
    fab.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 
        .setAction("Action", null).show(); 
     } 
    }); 

    prepareVideoView(); 

} 

private VideoView videoView; 
String videoPath = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_5mb.mp4"; 
String outFilePath = "";// 

private void prepareVideoView() { 
    MediaController mediaController = new MediaController(this); 
    videoView = (VideoView) findViewById(R.id.videoView); 
    mediaController.setAnchorView(videoView); 
    videoView.setMediaController(mediaController); 
    btnPlay = (Button) findViewById(R.id.btnPlayVideo); 
    btnPlay.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      new VideoDownloader().execute(videoPath); 
     } 
    }); 

    videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 
     @Override 
     public void onPrepared(MediaPlayer mp) { 
      player = mp; 

      player.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() { 
       @Override 
       public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 
        Log.w("download","size changed"); 
       } 
      }); 
     } 
    }); 
} 
File outFile; 
class VideoDownloader extends AsyncTask<String, Integer, Void> { 

    @Override 
    protected Void doInBackground(String... params) { 


     outFile = new File(outFilePath); 
     FileOutputStream out = null; 
     BufferedInputStream input = null; 
     try { 
      out = new FileOutputStream(outFile,true); 

      try { 
       URL url = new URL(videoPath); 

       HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
       connection.connect(); 
       if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { 
        throw new RuntimeException("response is not http_ok"); 
       } 
       int fileLength = connection.getContentLength(); 

       input = new BufferedInputStream(connection.getInputStream()); 
       byte data[] = new byte[2048]; 
       long readBytes = 0; 
       int len; 
       boolean flag = true; 
       int readb = 0; 
       while ((len = input.read(data)) != -1) { 
        out.write(data,0,len); 
        readBytes += len; 
    // Following commented code is to play video along with downloading but not working. 
/*      readb += len; 
        if(readb > 1000000) 
        { 
         out.flush(); 
         playVideo(); 
         readb = 0; 
        } 
*/ 
        Log.w("download",(readBytes/1024)+"kb of "+(fileLength/1024)+"kb"); 
       } 



      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } finally { 
       if (out != null) 
        out.flush(); 
        out.close(); 
       if(input != null) 
        input.close(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 

    @Override 
    protected void onPostExecute(Void aVoid) { 
     super.onPostExecute(aVoid); 
     Log.w("download", "Done"); 
     playVideo(); 

    } 
} 

private void playVideo() { 

    videoView.setVideoPath(outFile.getAbsolutePath()); 
    videoView.start(); 
} 
} 

Mã trên đang hoạt động bình thường để tải xuống và sau đó phát. Có một số dòng mã trong bình luận trong DoInBackground mà tôi đã cố gắng để đạt được mục tiêu của tôi nhưng nó nói "không thể chơi video". Bất cứ ai biết về giải pháp? làm ơn giúp tôi.

+0

Bạn có yêu cầu về trình chiếu một video giống như những gì xảy ra trong Youtube? – midhunhk

+0

trong youtube chỉ có luồng tôi nghĩ. những gì tôi cần là chỉ sử dụng một inputstream để chơi video trực tuyến và lưu nó cho mục đích ngoại tuyến. – chandil03

+0

Phương thức 'playVideo()' của bạn sử dụng một tệp có 'setVideoPath()'. Nói cách khác, 'playVideo()' sẽ * chỉ * hoạt động với video được tải xuống đầy đủ trên đĩa. Bạn sẽ cần phải truyền các khung và âm thanh riêng lẻ đến một trình phát đa phương tiện để truyền trực tuyến, sau đó chỉ cần chuyển các byte đó vào một tệp sau khi xem bộ nhớ cache để sử dụng ngoại tuyến. – MeetTitan

Trả lời

2

Với sự giúp đỡ của câu trả lời Milos Fec 's i giải quyết vấn đề này. Tôi phải tạo hai chuỗi một để tải xuống và một luồng khác để phát trực tuyến nội dung đã tải xuống qua socketServer trong khi chăm sóc đồng bộ hóa dữ liệu được tải xuống và dữ liệu đang được phát.

Tôi đã đưa toàn bộ mã như một thư viện trên github check here

4

Bạn có thể tạo proxy cục bộ để lưu luồng.

Tạo hai chủ đề nền: tải xuống chuỗiluồng trực tuyến.

Trong thread trực tuyến tạo ServerSocket và dòng dữ liệu đó chỉ là quá trình download.

Trong VideoView, mở url localhost của ServerSocket của bạn.

Bạn sẽ cần phải xử lý đệm, đồng bộ hóa chủ đề, vv

+0

tôi không muốn tạo ra hai chủ đề. Tôi muốn chỉ có một inputStream để tiết kiệm tiêu thụ dữ liệu gấp đôi. BTW tôi không biết làm thế nào để tạo proxy địa phương. Một lời giải thích sẽ được đánh giá cao. Cảm ơn. – chandil03

+0

Một chủ đề để tải xuống từ internet, chuỗi thứ hai để phát trực tuyến tới trình phát đa phương tiện (VideoView) = không có tiêu thụ dữ liệu kép. Ở đây bạn có ví dụ về việc sử dụng ServerSocket: http://stackoverflow.com/questions/15541804/creating-the-serversocket-in-a-separate-thread –

+0

MediaPlayer chỉ chấp nhận url web, tệpDescripter và uri tệp cục bộ để phát video . Vậy StreamingThread sẽ phát video như thế nào? – chandil03

Các vấn đề liên quan