• Windows Phone后台音乐播放本地代理实现讨论


    前一篇文章讨论的wp平台音乐播放的一些遇到的问题,经过苦思冥想和多方参考安卓实现;发现我们可以考虑一种本地代理的思想来完成我们的边听边存,并且流畅拖动进度条。希望大家一起讨论。可以下载我的代码一同研究

    源代码

    安卓实现本地代理文章参考:

    Android MediaPlayer与Http Proxy结合之基础篇

    Android MediaPlayer与Http Proxy结合之提高篇  如果我们也能这样实现的话,我们还能实现缓冲进度条

    玩转 Android MdeiaPlayer之Meida Proxy

    通过上面的参考我的思路如下:

    1、首先我将BackGroundAudiaoPlayer的AudiaoTrack地址设为本地代理的地址,请求本地代理;

    2、本地代理受到请求,将同样的请求发送给远程服务器;

    3、远程服务器响应流给本地代理,

    4、本地代理将流返回BackGroundAudiaoPlayer;

    接下来我们先来看看我抓包分析BackGroundAudiaoPlayer直接请求远程服务器的过程,他包括两个过程,第一个请求:

    在我听歌一段时间后,它会继续发一个Range请求:

    BackGroundAudiaoPlayer直接请求远程服务器的两个过程,一帮应该是发送上面两个请求,如果文件大的话可能第二步会重复。

    接下来就是我的实现过程:

    1、首先我将远程地址替换成本地地址,并且启动本地监听:

     //启动本地代理监听
                MediaProxy mp = new MediaProxy();
                mp.StartSocketListener();
                //在服务器地址前面加上本地地址和端口,让他请求本地代理
                string mp3Url = @"http://127.0.0.1:33123/qq.djwma.com/mp3/江南style_最新dj版.mp3";
                BackgroundAudioPlayer.Instance.Track = new AudioTrack(new Uri(mp3Url, UriKind.Absolute), "江南Style", "棒子", null, null, null, EnabledPlayerControls.All);
                BackgroundAudioPlayer.Instance.Play();

    第二步我在本地代理里面处理相关的请求MdeiaProxy.cs:

       /// <summary>
        /// 代理类
        /// </summary>
        public class MediaProxy
        {
            StreamSocketListener socketListener;
            public void StartSocketListener()
            {
                socketListener = new StreamSocketListener();//创建一个本地StreamSocketListener监听
                socketListener.ConnectionReceived += socketListener_ConnectionReceived;
                socketListener.BindServiceNameAsync("33123");
            }
    
            void socketListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
            {
                StreamSocket s = args.Socket;
                RequestHttp(s);
            }
            /// <summary>
            /// 远程请求服务器
            /// </summary>
            /// <param name="obj"></param>
            private async void RequestHttp(object obj)
            {
                StreamSocket s = obj as StreamSocket;
                // bool hasRange = false;//用于标记第二次请求
                try
                {
                    DataReader reader = new DataReader(s.InputStream);
                    reader.InputStreamOptions = InputStreamOptions.Partial;
                    uint numStrBytes = await reader.LoadAsync(5120);
                    string requestStr = reader.ReadString(numStrBytes);
                    // using (IOutputStream output = args.Socket.OutputStream)
                    Stream outputStream = s.OutputStream.AsStreamForWrite();
                    {
                        string[] requestHeaders = requestStr.Split(new char[] { '
    ', '
    ' });
                        string requestMethod = requestHeaders[0];
                        string[] requestParts = requestMethod.Split(' ');
                        string httpServer = "http:/";
                        string url = httpServer + requestParts[1];//组装远程mp3地址
                        HttpWebRequest webRequest = WebRequest.CreateHttp(url);
                        webRequest.AllowReadStreamBuffering = false;//这里设置为false,可以避免下载全部的流才得到相应
                        #region HTTP头部信息处理
                        Dictionary<string, string> pragmaDic = new Dictionary<string, string>();
                        for (int i = 1; i < requestHeaders.Length; i++)
                        {
                            if (!string.IsNullOrWhiteSpace(requestHeaders[i]))
                            {
                                string[] head = requestHeaders[i].Split(':');
    
                                if (head.Length == 2 && head[0] != "Host")
                                {
                                    if (head[0].ToLower() == "accept")
                                    {
                                        webRequest.Accept = head[1];
                                        continue;
                                    }
                                    //第一次请求不包含Range
                                    //if (head[0].ToLower() == "range")
                                    //{
                                    //    webRequest.Headers[head[0]] = head[1];
                                    //    hasRange = true;
                                    //    continue;
                                    //}
                                    if (head[0].ToLower() == "contentlength")
                                    {
                                        webRequest.ContentLength = long.Parse(head[1]);
                                        continue;
                                    }
                                    if (head[0].ToLower() == "contenttype")
                                    {
                                        webRequest.ContentType = head[1];
                                        continue;
                                    }
                                    if (head[0].ToLower() == "user-agent")
                                    {
                                        webRequest.UserAgent = head[1];
                                        continue;
                                    }
                                    if (head[0].ToLower() == "pragma")
                                    {
                                        pragmaDic.Add(head[1], head[1]);
                                        continue;
                                    }
                                    webRequest.Headers[head[0]] = head[1];
                                }
                            }
    
                        }
                        if (pragmaDic.Count > 0)
                        {
                            string pragma = string.Empty;
                            foreach (string p in pragmaDic.Values)
                            {
                                pragma += p;
                            }
                            webRequest.Headers["Pragma"] = pragma;
                        }
                        #endregion
                        webRequest.BeginGetResponse((res) =>
                        {
                            System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                            {
                                HttpWebRequest request = res.AsyncState as HttpWebRequest;
                                HttpWebResponse response = request.EndGetResponse(res) as HttpWebResponse;
                                WebHeaderCollection headerCollection = response.Headers;
                                string codeEn = response.StatusCode.ToString();
                                int codeNum = (int)response.StatusCode;
                                //第一种响应头:将服务器返回的头信息全部返回给播放器
                                //string header =string.Format("HTTP/1.1 {0} {1}
    {2}" ,codeNum,codeEn, headerCollection.ToString());
                                //第二种响应头:将自定义头部
                                string header1 = String.Format(@"HTTP/1.1 200 OK
    Content-Type: audio/mpeg
    Connection: keep-alive
    Content-Length: {0}
    
    ", response.ContentLength);
                                Stream stream = response.GetResponseStream();
                                // using (Stream stream = response.GetResponseStream())
                                {
                                    byte[] headerArray = Encoding.UTF8.GetBytes(header1);
                                    outputStream.WriteAsync(headerArray, 0, headerArray.Length);
                                    stream.CopyToAsync(outputStream);
                                    outputStream.FlushAsync();
                                }
                            });
                        }, webRequest);
                    }
                }
                catch (Exception ex)
                {
    
                }
            }
        }
    View Code

    我不知道我上面的实现有问题还是怎么,我遇到了很多莫名奇妙的问题:

    1、我有时候能播放歌曲,但是播放到部分就报错,有时候也能连续播放歌曲,但是大部分时候是不能播放歌曲的,希望大家在测试我代码的时候在AudioPlayer.cs的OnError里面打一个断点。

    2、因为每次报错都进入了OnError,并且每次的异常消息都是一串数字,搞得我不知道哪里出错。

    问题原因分析:

    在OnError的备注里有这么一句话"每次播放出错(如 AudioTrack 未正确下载)时调用",所以我猜测是我的数据没有正确返回导致错误的。

    还有就是在监听处理函数里面我会得到相同的请求,我想可能因为在WP里面HTTP的请求都是异步的,因为异步是非阻塞的,所以当我的数据还没有返回的时候,BackgroudAudiaPlayer没有收到就继续发送同一个请求,

    一般在收到两个之后程序就会产生异常,并且进入OnError。所以我猜测如果有同步请求是不是就会正确(貌似安卓就是同步请求实现的),调试了几天都没解决,希望大家看看我的思路是否可行,或者还是我的实现有问题,

    望指点。 欢迎关注我的微博@多了特 一起讨论

  • 相关阅读:
    Nothing
    交换机基础
    BringWindowToTop(), SetForegroundWindow(), SetActiveWindow()
    NYOJ 38 布线问题_(解法2 Prim算法)
    Cocos2d-x3.0TestCpp文件夹笔记(二)
    SqlServer禁用启用触发器、外键约束
    Qt之zip压缩/解压缩(QuaZIP)
    Qt中用QuaZip来压缩和解压缩文件
    Qt 之 ZIP开源库 QuaZIP
    sqlserver 获取存储过程执行时间
  • 原文地址:https://www.cnblogs.com/duolete/p/3434104.html
Copyright © 2020-2023  润新知