前一篇文章讨论的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("");
} 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();
string requestStr = reader.ReadString(numStrBytes);
// using (IOutputStream output = args.Socket.OutputStream)
Stream outputStream = s.OutputStream.AsStreamForWrite();
{
string[] requestHeaders = requestStr.Split(new char[] { '\r', '\n' });
string requestMethod = requestHeaders[];
string[] requestParts = requestMethod.Split(' ');
string httpServer = "http:/";
string url = httpServer + requestParts[];//组装远程mp3地址
HttpWebRequest webRequest = WebRequest.CreateHttp(url);
webRequest.AllowReadStreamBuffering = false;//这里设置为false,可以避免下载全部的流才得到相应
#region HTTP头部信息处理
Dictionary<string, string> pragmaDic = new Dictionary<string, string>();
for (int i = ; i < requestHeaders.Length; i++)
{
if (!string.IsNullOrWhiteSpace(requestHeaders[i]))
{
string[] head = requestHeaders[i].Split(':'); if (head.Length == && head[] != "Host")
{
if (head[].ToLower() == "accept")
{
webRequest.Accept = head[];
continue;
}
//第一次请求不包含Range
//if (head[0].ToLower() == "range")
//{
// webRequest.Headers[head[0]] = head[1];
// hasRange = true;
// continue;
//}
if (head[].ToLower() == "contentlength")
{
webRequest.ContentLength = long.Parse(head[]);
continue;
}
if (head[].ToLower() == "contenttype")
{
webRequest.ContentType = head[];
continue;
}
if (head[].ToLower() == "user-agent")
{
webRequest.UserAgent = head[];
continue;
}
if (head[].ToLower() == "pragma")
{
pragmaDic.Add(head[], head[]);
continue;
}
webRequest.Headers[head[]] = head[];
}
} }
if (pragmaDic.Count > )
{
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}\r\n{2}" ,codeNum,codeEn, headerCollection.ToString());
//第二种响应头:将自定义头部
string header1 = String.Format(@"HTTP/1.1 200 OK\r\nContent-Type: audio/mpeg\r\nConnection: keep-alive\r\nContent-Length: {0}\r\n\r\n", response.ContentLength);
Stream stream = response.GetResponseStream();
// using (Stream stream = response.GetResponseStream())
{
byte[] headerArray = Encoding.UTF8.GetBytes(header1);
outputStream.WriteAsync(headerArray, , headerArray.Length);
stream.CopyToAsync(outputStream);
outputStream.FlushAsync();
}
});
}, webRequest);
}
}
catch (Exception ex)
{ }
}
}

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

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

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

问题原因分析:

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

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

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

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

Windows Phone后台音乐播放本地代理实现讨论的更多相关文章

  1. 与众不同 windows phone (40) - 8.0 媒体: 音乐中心的新增功能, 图片中心的新增功能, 后台音乐播放的新增功能

    [源码下载] 与众不同 windows phone (40) - 8.0 媒体: 音乐中心的新增功能, 图片中心的新增功能, 后台音乐播放的新增功能 作者:webabcd 介绍与众不同 windows ...

  2. [置顶] Windows Phone后台音乐详解一

    应用于: Windows Phone 8 | Windows PhoneOS 7.1 你可以为winphone编写在后台播放音乐的app.这表示即使当用户点击返回或开始按钮离开你的应用界面时,你的应用 ...

  3. 关于Windows Phone平台音乐播放的的技术调研

    希望看到这篇文章的开发者能提供你们的想法,让我们一起来探讨一款wp平台上面一款能流畅播放.能流畅拖拽进入条.只发一次请求就可以缓存的最好的播放器.希望大家能对我下面遇到的问题作出回答. 现在出了Win ...

  4. 微信小程序后台音乐播放注意事项

    wx.seekBackgroundAudio(OBJECT) 作用:控制音乐播放进度. 注意: 该事件 会触发 wx.onBackgroundAudioPlay(CALLBACK) 事件 ,也就是相当 ...

  5. MUI---IOS切换到后台继续播放音乐

    应用切换到后台继续音乐播放HBuilder默认生成的应用在iOS是不支持后台音乐播放的,当应用切换到后台时音乐将暂停播放,下次切换到前台继续播放.如果要支持应用切换到后台后继续播放音乐功能需要进行额外 ...

  6. c#音乐播放器

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  7. Android-bindService本地服务-音乐播放(后台播放)-下

    在上一篇  Android-bindService本地服务-音乐播放-上,博客中是不能在后台中播放到,这次博客增加了一个后台播放 通常情况下,Activity切换到后台,Service提升到前台进程, ...

  8. iOS开发系列--音频播放(音效和音乐)播放本地的

    音频 在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为 点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音频,对于这些音 ...

  9. 项目源码--Android本地音乐播放器

    下载源码 技术要点: 1.本地音乐播放与管理 2.支持在线下载 3.非库音频流的解码 4. UI控件的综合使用 5. HTTP通信模块 6. Mysql数据库的综合使用 7. 后台服务技术 8. 源码 ...

随机推荐

  1. hdu4508 完全背包,湫湫系列故事——减肥记I

    湫湫系列故事——减肥记I 对于01背包和完全背包,昨晚快睡着的时候,突然就来了灵感 区别:dp[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值 在第二重循环,01 是倒着循环的,因 ...

  2. PHP之算法偶遇隨感

    php真的很棒,很多函數把我們想要的功能都簡單實現了,是項目快速開發的首選.說實話,在BS程序開發方面我認為最好的兩種語言是PHP和JSP,我之前曾學過一段時間的java,確實很棒完全的OOP,但是它 ...

  3. 和View Controllers一起工作

    在这一课中,你会继续在FoodTracker菜谱的场景工作.你会重新安排现有的UI元素并使用图像采集器添加到照片用户界面.当你完成,你的应用程序将是这个样子: 学习目标 在课程结束时,你将能够: 了解 ...

  4. 在Android界面特效中如何做出和墨迹天气及UC中左右拖动的效果

    (国内知名Android开发论坛eoe开发者社区推荐:http://www.eoeandroid.com/) 在Android界面特效中如何做出和墨迹天气及UC中左右拖动的效果 相信这么多手机APP中 ...

  5. [纯干货] MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  6. 使用sqlserver的游标功能来导数据的常见写法

    一定要自己试过才知道么? 你也没试过吃屎,你怎么知道屎不能吃,难道你试过啊...(没有愤怒的意思) ),),) declare cursor_data CURSOR FOR SELECT [UserN ...

  7. WP-PostViews的安装和设置方法

    wordpress本身并没有文章浏览统计功能,必须借助插件.想要知道自己的文章被多数访客浏览,或者访客对哪些文章或者哪类文章更加有兴趣,这就是文章统计的重要性了.WP-PostViews插件是哥不错的 ...

  8. ViewPager中使用PhotoView时出现pointerIndex out of range异常

    问题描述: 当PhotoView 和 ViewPager 组合时 ,用双指进行放大时 是没有问题的,但是用双指进行缩小的时候,程序就会崩掉,并且抛出java.lang.IllegalArgumentE ...

  9. 在 Excel 中使用正则表达式进行查找与替换

    在 Excel 中,使用 Alt+F11 快捷键打开 VBA 项目窗口,在左侧的工作表名称上点右键,选择查看代码,即可出出现右侧的代码编辑窗口 在代码窗口中输入以下代码: Private Sub Re ...

  10. Multiple Contexts have a path of "/xxxx"问题解决

    转自:http://blog.csdn.net/ivanzhangqf/article/details/50326533 之前因为ecplise项目保存更新时一直显示等待后台操作完成,以至于一直卡住无 ...