玩轉 Android MediaPlayer之Media Proxy

來源:互聯網
上載者:User

本文來自http://blog.csdn.net/hellogv/ ,引用必須註明出處!

       本文是在《Android MediaPlayer與Http Proxy結合之提高篇》基礎上,進一步最佳化Proxy 伺服器,支援了Http的302、301重新導向,擷取Http Request和Http Response的常值內容。本文以視頻播放結合Http Proxy,講述MediaPlayer播放過程中的握手過程。

吐槽一下:用google搜尋“Proxy 伺服器”無效,所以本文用Media Proxy,大家懂的......

先來看看本文程式啟動並執行截屏動畫:

再來看看程式運行時輸出的Log資訊.....這裡是關鍵:

07-29 15:51:30.692: E/HttpGetProxy(449): ..........sckPlayer connected.......... MediaPlayer發出請求
07-29 15:51:30.692: E/to Media Server---->(449): GET /vids/family_guy_penis_car.3gp HTTP/1.1

07-29 15:51:30.692: E/to Media Server---->(449): User-Agent: stagefright/1.0 (Linux;Android 2.2)

07-29 15:51:30.692: E/to Media Server---->(449): Host: daily3gp.com

07-29 15:51:30.692: E/to Media Server---->(449):

07-29 15:51:31.119: E/HttpGetProxy(449): ..........remote Server connected..........
07-29 15:51:31.122: E/HttpGetProxy(449): ..........remote start to receive..........
07-29 15:51:31.775: E/from Media Server---->(449): HTTP/1.1 200 OK

07-29 15:51:31.775: E/from Media Server---->(449): Date: Sun, 29 Jul 2012 15:51:33 GMT

07-29 15:51:31.775: E/from Media Server---->(449): Server: Apache

07-29 15:51:31.775: E/from Media Server---->(449): Last-Modified: Thu, 14 Jan 2010 23:29:02 GMT

07-29 15:51:31.775: E/from Media Server---->(449): Accept-Ranges: bytes

07-29 15:51:31.775: E/from Media Server---->(449): Content-Length: 754777

07-29 15:51:31.775: E/from Media Server---->(449): Content-Type: video/3gpp


07-29 15:51:34.512: E/HttpGetProxy(449): ..........sckPlayer connected..........MediaPlayer發出請求
07-29 15:51:34.532: E/to Media Server---->(449): GET /vids/family_guy_penis_car.3gp HTTP/1.1

07-29 15:51:34.532: E/to Media Server---->(449): User-Agent: stagefright/1.0 (Linux;Android 2.2)

07-29 15:51:34.532: E/to Media Server---->(449): Host: daily3gp.com

07-29 15:51:34.532: E/to Media Server---->(449): Range: bytes=720896-

07-29 15:51:34.532: E/to Media Server---->(449):

07-29 15:51:34.873: E/HttpGetProxy(449): ..........remote Server connected..........
07-29 15:51:34.873: E/HttpGetProxy(449): ..........remote start to receive..........
07-29 15:51:35.505: E/from Media Server---->(449): HTTP/1.1 206 Partial Content

07-29 15:51:35.505: E/from Media Server---->(449): Date: Sun, 29 Jul 2012 15:51:36 GMT

07-29 15:51:35.505: E/from Media Server---->(449): Server: Apache

07-29 15:51:35.505: E/from Media Server---->(449): Last-Modified: Thu, 14 Jan 2010 23:29:02 GMT

07-29 15:51:35.505: E/from Media Server---->(449): Accept-Ranges: bytes

07-29 15:51:35.505: E/from Media Server---->(449): Content-Length: 33881

07-29 15:51:35.505: E/from Media Server---->(449): Content-Range: bytes 720896-754776/754777

07-29 15:51:35.505: E/from Media Server---->(449): Content-Type: video/3gpp
07-29 15:51:38.754: E/HttpGetProxy(449): ..........over..........


07-29 15:51:51.461: E/HttpGetProxy(449): ..........sckPlayer connected..........MediaPlayer發出請求
07-29 15:51:51.471: E/to Media Server---->(449): GET /vids/family_guy_penis_car.3gp HTTP/1.1

07-29 15:51:51.471: E/to Media Server---->(449): User-Agent: stagefright/1.0 (Linux;Android 2.2)

07-29 15:51:51.471: E/to Media Server---->(449): Host: daily3gp.com

07-29 15:51:51.471: E/to Media Server---->(449): Range: bytes=196608-

07-29 15:51:51.471: E/to Media Server---->(449):

07-29 15:51:51.722: E/HttpGetProxy(449): ..........remote Server connected..........
07-29 15:51:51.722: E/HttpGetProxy(449): ..........remote start to receive..........
07-29 15:51:52.285: E/from Media Server---->(449): HTTP/1.1 206 Partial Content

07-29 15:51:52.285: E/from Media Server---->(449): Date: Sun, 29 Jul 2012 15:51:53 GMT

07-29 15:51:52.285: E/from Media Server---->(449): Server: Apache

07-29 15:51:52.285: E/from Media Server---->(449): Last-Modified: Thu, 14 Jan 2010 23:29:02 GMT

07-29 15:51:52.285: E/from Media Server---->(449): Accept-Ranges: bytes

07-29 15:51:52.285: E/from Media Server---->(449): Content-Length: 558169

07-29 15:51:52.285: E/from Media Server---->(449): Content-Range: bytes 196608-754776/754777

07-29 15:51:52.285: E/from Media Server---->(449): Content-Type: video/3gpp


07-29 15:51:54.812: E/HttpGetProxy(449): ..........sckPlayer connected..........MediaPlayer發出請求
07-29 15:51:54.822: E/to Media Server---->(449): GET /vids/family_guy_penis_car.3gp HTTP/1.1

07-29 15:51:54.822: E/to Media Server---->(449): User-Agent: stagefright/1.0 (Linux;Android 2.2)

07-29 15:51:54.822: E/to Media Server---->(449): Host: daily3gp.com

07-29 15:51:54.822: E/to Media Server---->(449): Range: bytes=589824-

07-29 15:51:54.822: E/to Media Server---->(449):

07-29 15:51:55.117: E/HttpGetProxy(449): ..........remote Server connected..........
07-29 15:51:55.117: E/HttpGetProxy(449): ..........remote start to receive..........
07-29 15:51:55.693: E/from Media Server---->(449): HTTP/1.1 206 Partial Content

07-29 15:51:55.693: E/from Media Server---->(449): Date: Sun, 29 Jul 2012 15:51:57 GMT

07-29 15:51:55.693: E/from Media Server---->(449): Server: Apache

07-29 15:51:55.693: E/from Media Server---->(449): Last-Modified: Thu, 14 Jan 2010 23:29:02 GMT

07-29 15:51:55.693: E/from Media Server---->(449): Accept-Ranges: bytes

07-29 15:51:55.693: E/from Media Server---->(449): Content-Length: 164953

07-29 15:51:55.693: E/from Media Server---->(449): Content-Range: bytes 589824-754776/754777

07-29 15:51:55.693: E/from Media Server---->(449): Content-Type: video/3gpp
07-29 15:51:59.620: E/HttpGetProxy(449): ..........over..........

 

從截屏動畫和Log資訊看出,手動seek一次,但MediaPlayer進行了多次Range請求,這說明了“MediaPlayer會自動seek”,或許與MediaPlayer本機快取有關。另外,不同硬解廠家實現的MediaPlayer估計會有不同的操作。

 

本文的代碼可以到這裡下載:

http://download.csdn.net/detail/hellogv/4463651

HttpGetProxy.JAVA還是本文的關鍵區段:

public class HttpGetProxy {      final static private String TAG = "HttpGetProxy";      final static private String LOCAL_IP_ADDRESS_1 = "127.0.0.1";    final static private String LOCAL_IP_ADDRESS_2 = "10.0.2.2";    final static private int HTTP_PORT = 80;    final static private String HTTP_END="\r\n\r\n";        /**Proxy 伺服器使用的連接埠*/    private int proxy_ip_port;    /**連結帶的連接埠*/    private String original_ip_port;    /**遠程伺服器位址*/    private String remoteHost;    /**本機伺服器地址*/    private String localHost;    private ServerSocket localServer = null;      /**收發Media Player請求的Socket*/    private Socket sckPlayer = null;    /**收發Media Server請求的Socket*/    private Socket sckServer = null;      private SocketAddress address;         /**      * 初始化Proxy 伺服器      * @param localport Proxy 伺服器監聽的連接埠      */      public HttpGetProxy(int localport) {      try {_HttpGetProxy(LOCAL_IP_ADDRESS_1,localport);} catch (Exception e) {Log.e(TAG,LOCAL_IP_ADDRESS_1+"???"+e.toString());try {_HttpGetProxy(LOCAL_IP_ADDRESS_2,localport);}catch (Exception e1) {Log.e(TAG,LOCAL_IP_ADDRESS_2+"???"+e.toString());System.exit(0);}}    }        private void _HttpGetProxy(String ipAddress,int localport) throws UnknownHostException, IOException {      proxy_ip_port=localport;          localServer = new ServerSocket(localport,1,InetAddress.getByName(ipAddress));        localHost=ipAddress;    }       /**      * 把網路URL轉為本地URL,127.0.0.1替換網路網域名稱      * @param url 網路URL       * @return 本地URL      */      public String getLocalURL(String urlString){    //----排除HTTP特殊----//    String targetUrl=ProxyUtils.getRedirectUrl(urlString);    //----擷取對應本地Proxy 伺服器的連結----//        String result = null;        URI originalURI=URI.create(targetUrl);          remoteHost=originalURI.getHost();          if(originalURI.getPort()!=-1){//URL帶Port            address = new InetSocketAddress(remoteHost,originalURI.getPort());//使用預設連接埠              original_ip_port = originalURI.getPort()+"";//儲存連接埠,中轉時替換            result=targetUrl.replace(remoteHost+":"+originalURI.getPort(),              localHost+":"+proxy_ip_port);          }          else{//URL不帶Port              address = new InetSocketAddress(remoteHost,HTTP_PORT);//使用80連接埠             original_ip_port = "";            result=targetUrl.replace(remoteHost,localHost+":"+proxy_ip_port);          }        return result;         }          /**      * 啟動Proxy 伺服器      * @throws IOException      */      public void asynStartProxy(){          new Thread() {              public void run() {                int bytes_read;                  byte[] local_request = new byte[1024];                  byte[] remote_reply = new byte[1024];                  while (true) {                      try {                          //--------------------------------------                          //監聽MediaPlayer的請求,MediaPlayer->Proxy 伺服器                          //--------------------------------------                          sckPlayer = localServer.accept();                          Log.e(TAG, "..........sckPlayer connected..........");                                                   String requestStr = "";                        while ((bytes_read = sckPlayer.getInputStream().read(local_request)) != -1) {                            byte[] tmpBuffer=new byte[bytes_read];                             System.arraycopy(local_request,0,tmpBuffer,0,bytes_read);                            String str = new String(tmpBuffer);                            //Log.e("from MediaPlayer---->", str);                              requestStr = requestStr + str;                              if (requestStr.contains("GET")                                      && requestStr.contains(HTTP_END)) {                                  break;                            }                           }                                                //把request中的本地ip改為遠程ip                        requestStr = requestStr.replace(localHost,remoteHost);                        //把Proxy 伺服器連接埠改為原URL連接埠                        if(TextUtils.isEmpty(original_ip_port))                        requestStr = requestStr.replace(":"+proxy_ip_port, "");                        else                        requestStr = requestStr.replace(":"+proxy_ip_port, ":"+original_ip_port);                        Log.e("to Media Server---->", requestStr);                        //--------------------------------------                          //把MediaPlayer的請求發到網路伺服器,Proxy 伺服器->網路伺服器                          //--------------------------------------                        sckServer = new Socket();                          sckServer.connect(address);                          Log.e(TAG,"..........remote Server connected..........");                          sckServer.getOutputStream().write(requestStr.getBytes());//發送MediaPlayer的請求                          //------------------------------------------------------                          //把網路伺服器的反饋發到MediaPlayer,網路伺服器->Proxy 伺服器->MediaPlayer                          //------------------------------------------------------                        Log.e(TAG,"..........remote start to receive..........");                        String responseStr = "";                        boolean isCaptured=false;                        while ((bytes_read = sckServer.getInputStream().read(remote_reply)) != -1) {                        byte[] tmpBuffer=new   byte[bytes_read];                             System.arraycopy(remote_reply,0,tmpBuffer,0,bytes_read);                            //----捕獲收到的Response常值內容----//if (!isCaptured) {String str = new String(tmpBuffer);responseStr += str;if (responseStr.contains("HTTP/")                                      && responseStr.contains(HTTP_END)) {int endIndex=responseStr.indexOf(HTTP_END, 0);responseStr=responseStr.substring(0, endIndex);Log.e("from Media Server---->", responseStr);isCaptured=true;                            }}                            sckPlayer.getOutputStream().write(tmpBuffer);                              sckPlayer.getOutputStream().flush();                        }                        Log.e(TAG, "..........over..........");                                                //關閉對內,對內 2個SOCKET                        sckPlayer.close();                          sckServer.close();                      } catch (IOException e) {                          // TODO Auto-generated catch block                          e.printStackTrace();                      }                  }              }          }.start();      }  }  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.