HardBirch

Android MediaPlayer与Http Proxy结合之提高篇

时间:12-05-27 栏目:安卓入门与提高 作者:张飞不张,文采横飞 评论:10 点击: 6,611 次

       《基础篇》实现一个简单的代理服务器与Android的MediaPlayer结合(仅支持Http Get),可以通过代理服务器来转发MediaPlayer的Request以及传输服务器的Response,但《基础篇》还不能支持Seek,这次提高篇支持了Seek。代理服务器可以增强MediaPlayer对复杂的Http情况的适应,可以播放带防盗链的媒体文件,边播边存,还可以对大体积的媒体文件(如视频)进行多线程预加载,达到快速播放的效果。

       本文代码运行在模拟器上,使用Microsoft Network Monitor 3.4来抓包,通过抓包可以发现seek的操作会重新连接服务器,并在Http Get请求中加入Range 字段,所以代理服务器每次监听到MediaPlayer的request都需要新建socket与远程服务器连接。

本文的代码可以到http://download.csdn.net/detail/hellogv/4332362下载,本文程序运行效果如图:

接下来贴出核心代码HttpGetProxy.java:

public class HttpGetProxy {
	final static private String TAG = "HttpGetProxy";
	final static private String LOCAL_IP_ADDRESS = "127.0.0.1";
	final static private int HTTP_PORT = 80;

	private int local_ip_port;
	private ServerSocket localServer = null;
	private Socket localSocket = null;
	private Socket remoteSocket = null;
	private String remoteHost;

	private InputStream in_remoteSocket;
	private OutputStream out_remoteSocket;
	private InputStream in_localSocket;
	private OutputStream out_localSocket;

	private SocketAddress address;
	private interface OnFinishListener {
		void onFinishListener();
	}

	/**
	 * 初始化代理服务器
	 * @param localport 代理服务器监听的端口
	 */
	public HttpGetProxy(int localport) {
		local_ip_port=localport;
		try {
			localServer = new ServerSocket(localport, 1,
					InetAddress.getByName(LOCAL_IP_ADDRESS));
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 结束时,清除所有资源
	 */
	private OnFinishListener finishListener = new OnFinishListener() {

		@Override
		public void onFinishListener() {
			System.out.println("..........release all..........");
			Log.e(TAG, "..........release all..........");
			try {
				in_localSocket.close();
				out_remoteSocket.close();

				in_remoteSocket.close();
				out_localSocket.close();

				localSocket.close();
				remoteSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	};

	/**
	 * 把网络URL转为本地URL,127.0.0.1替换网络域名
	 * @param url 网络URL
	 * @return 本地URL
	 */
	public String getLocalURL(String url){
		String result = null;
		URI originalURI=URI.create(url);
		remoteHost=originalURI.getHost();
		if(originalURI.getPort()!=-1){//URL带Port
			address = new InetSocketAddress(remoteHost,
					originalURI.getPort());//使用默认端口
			result=url.replace(remoteHost+":"+originalURI.getPort(),
					LOCAL_IP_ADDRESS+":"+local_ip_port);
		}
		else{//URL不带Port
			address = new InetSocketAddress(remoteHost,
					HTTP_PORT);//使用80端口
			result=url.replace(remoteHost,LOCAL_IP_ADDRESS+":"+local_ip_port);
		}
		return result;

	}

	/**
	 * 启动代理服务器
	 * @throws IOException
	 */
	public void startProxy() throws IOException {

		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->代理服务器
						//--------------------------------------
						localSocket = localServer.accept();

						Log.e(TAG, "..........localSocket connected..........");
						in_localSocket = localSocket.getInputStream();
						out_localSocket = localSocket.getOutputStream();
						Log.e(TAG, "..........init local Socket I/O..........");

						String buffer = "";//保存MediaPlayer的HTTP请求
						while ((bytes_read = in_localSocket.read(local_request)) != -1) {
							String str = new String(local_request);
							Log.e("localSocket---->", str);
							buffer = buffer + str;
							if (buffer.contains("GET")
									&& buffer.contains("rnrn")) {
								// ---把request中的本地ip改为远程ip---//
								buffer = buffer.replace(LOCAL_IP_ADDRESS,remoteHost);
								break;
							}
						}
						Log.e(TAG, "..........local finish receive..........");

						//--------------------------------------
						//把MediaPlayer的请求发到网络服务器,代理服务器->网络服务器
						//--------------------------------------
						remoteSocket = new Socket();
						remoteSocket.connect(address);
						Log.e(TAG,"..........remote Server connected..........");
						in_remoteSocket = remoteSocket.getInputStream();
						out_remoteSocket = remoteSocket.getOutputStream();
						out_remoteSocket.write(buffer.getBytes());//发送MediaPlayer的请求
						out_remoteSocket.flush();

						//------------------------------------------------------
						//把网络服务器的反馈发到MediaPlayer,网络服务器->代理服务器->MediaPlayer
						//------------------------------------------------------
						Log.e(TAG,"..........remote start to receive..........");
						while ((bytes_read = in_remoteSocket.read(remote_reply)) != -1) {
							out_localSocket.write(remote_reply, 0, bytes_read);
							out_localSocket.flush();
						}
						Log.e(TAG, "..........over..........");
						finishListener.onFinishListener();//释放资源
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}.start();
	}
}

声明: 本文由( 张飞不张,文采横飞 )原创编译,转载请保留链接: Android MediaPlayer与Http Proxy结合之提高篇

Android MediaPlayer与Http Proxy结合之提高篇:目前有10 条留言

  1. 10楼
    hmc1985:

    支持一下!

    2012-05-27 11:08 [回复]
  2. 群里弦月,支持你~~

    2012-05-27 11:15 [回复]
  3. 顶老大…

    2012-05-27 22:51 [回复]
  4. 7楼
    qooqym:

    支持~

    2012-05-28 10:17 [回复]
  5. 6楼
    lumeng9051:

    看看

    2012-05-28 13:02 [回复]
  6. 5楼
    cywindor:

    你好,有个问题请教一下,现在的视频都是切片,代理服务器如何做到切片的连播而且不会有黒场

    2012-06-29 18:00 [回复]
  7. 4楼
    hellogv:

    [reply]cywindor[/reply]
    我正在做这个,很多android产品的MediaPlayer只是 单例,所以必须有个释放再初始化播放的过程,肯定会停顿至少几百毫秒,至于黑屏,你可以用截图留住最后一帧

    2012-06-30 08:09 [回复]
  8. 地板
    匿名:

    实现截图貌似比较麻烦,请指点[reply]hellogv[/reply]

    2012-07-02 10:20 [回复]
  9. 板凳
    Iptton:

    顶一下..

    2012-07-30 17:41 [回复]
  10. 沙发
    ivychen0324:

    good! for beginner~

    2012-09-09 19:21 [回复]

发表评论


QQ群互动

Linux系统与内核学习群:194051772

WP建站技术学习交流群:194062106

魔豆之路QR

魔豆的Linux内核之路

魔豆的Linux内核之路

优秀工程师当看优秀书籍

优秀程序员,要看优秀书!

赞助商广告

友荐云推荐