MEDIA-SYSSERVICES媒体播放
1 简单的音乐播放器
1.1 问题
本案例结合之前所学的网络和数据解析等知识完成一个网络音乐播放器,如图-1所示:
图-1
1.2 方案
首先创建一个SingleViewApplication应用,在Storyboard文件中搭建音乐播放器界面,该应用有三个场景组成,第一个场景用于搜索,第二场景显示歌曲列表,第三个场景是播放歌曲界面,有一个播放进度条。这三个场景由一个导航视图控制器管理,如图-2所示:
图-2
本案例使用一个百度的音乐开放接口http://mp3.baidu.com,首先创建一个模型类TRMusicInfo存放音乐的相关信息。
其次将网络请求和解析的代码封装在两个类中TRWebUtils和TRParser。TRWebUtils类中有两个方法,一个是requestMusicsByWord:andCallBack:,该方法根据用户输入的歌手姓名获取到网络请求的路径,然后采用NSURLConnection类发送异步请求,返回的数据是Json格式的,然后采用NSJSONSerialization类进行Json解析,得到音乐的相关信息。
TRWebUtils类中的另一个方法requestMusicDetailByMusic:andCallBack,该方法是通过音乐信息中的音乐ID发送网络请求,然后通过数据解析获取到音乐的下载的地址和歌词地址。对应的在TRParser类有两个解析数据的方法parseMusicInfoByArray:和parseMusicDetailByDic:andMusic:。
然后完成音乐列表视图控制器TRMusicListViewController的代码,该视图控制器继承至UITableViewController,有一个NSMutableArray类型的属性musics,用于存放需要展示的音乐信息。在viewDidLoad方法中通过TRWebUtils类调用requestMusicsByWord:andCallBack:方法,根据用户输入的歌手姓名发送网络请求,解析歌曲数据得到属性self.music数据,刷新界面。
由于表视图的每个Cell需要展示歌曲的信息,所以这里需要自定义一个Cell,因此创建一个TRMusicCell类,继承至UITableViewCell类,需要显示专辑封面,歌曲名、歌手名以及专辑名,如图-3所示:
图-3
然后实现音乐播放视图控制器TRPlayViewController的代码,该视图控制器有一个TRMusicInfo类型的公开属性music,用于记录用户从上一个界面选择的音乐信息。
该视图控制器还有如下几个私有属性:
AVAudioPlayer类型的player,用于播放音乐;
NSURLConnection类型的conn,用于发送下载请求;
NSMutableData类型的allData,用于存放下载的音乐数据;
NSUInteger类型的fileLength,用于记录下载音乐的大小;
在TRPlayViewController的viewDidLoad方法中通过TRWebUtils类调用requestMusicDetailByMusic:andCallBack:方法,根据音乐信息获取到音乐的下载地址和歌词地址,然后通过音乐下载地址发送下载请求,将发送下载请求的代码封装在downloadMusic方法中。
接下来实现NSURLConnectionDelegate的协议方法,在connection:didReceiveResponse:方法中解析头文件,获取到文件的大小并初始化self.allData属性。
在connection:didReceiveData:方法中将下载到的音乐数据保存在self.allData中,并且创建音乐播放器并播放歌曲,实现边下载边播放的功能。
在connectionDidFinishLoading:方法中将音乐的数据存入本地。
最后开启一个计时器,更新进度条的显示,即音乐的播放进度。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建模型类
首先创建一个SingleViewApplication应用,在Storyboard文件中搭建音乐播放器界面,该应用有三个场景组成,第一个场景用于搜索,第二场景显示歌曲列表,第三个场景是播放歌曲界面,有一个播放进度条。
本案例使用一个百度的音乐开放接口http://mp3.baidu.com,首先创建一个模型类TRMusicInfo存放音乐的相关信息,代码如下所示:
@interface TRMusicInfo : NSObject
@property (nonatomic, copy)NSString *name;
@property (nonatomic, copy)NSString *singerName;
@property (nonatomic, copy)NSString *albumName;
@property (nonatomic, copy)NSString *songID;
@property (nonatomic, copy)NSString *albumImagePath;
@property (nonatomic, copy)NSString *musicPath;
@property (nonatomic, copy)NSString *lrcPath;
@end
其次将网络请求和解析的代码封装在两个类中TRWebUtils和TRParser。TRWebUtils类中有两个方法,一个是requestMusicsByWord:andCallBack:,该方法根据用户输入的歌手姓名获取到网络请求的路径,然后采用NSURLConnection类发送异步请求,返回的数据是Json格式的,然后采用NSJSONSerialization类进行Json解析,得到音乐的相关信息,代码如下所示:
+ (void)requestMusicsByWord:(NSString *)word andCallBack:(MyCallback)callback{
NSString *path = [NSString stringWithFormat:@"http://mp3.baidu.com/dev/api/?tn=getinfo&ct=0&word=%@&ie=utf-8&format=json",word];
path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:path];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSArray *arr = [NSJSONSerialization JSONObjectWithData:data options: error:Nil];
if (arr.count==) {
[TRWebUtils requestMusicsByWord:word andCallBack:callback];
}
NSMutableArray *musics = [TRParser parseMusicInfoByArray:arr];
callback(musics);
}];
}
TRWebUtils类中的另一个方法requestMusicDetailByMusic:andCallBack,该方法是通过音乐信息中的音乐ID发送网络请求,然后通过数据解析获取到音乐的下载的地址和歌词地址,代码如下所示:
+ (void)requestMusicDetailByMusic:(TRMusicInfo *)music andCallBack:(MyCallback)callback{
NSString *path = [NSString stringWithFormat:@"http://ting.baidu.com/data/music/links?songIds=%@",music.songID];
NSLog(@"%@",path);
NSURL *url = [NSURL URLWithString:path];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options: error:Nil];
[TRParser parseMusicDetailByDic:dic andMusic:music];
callback(music);
}];
}
对应的在TRParser类有两个解析数据的方法parseMusicInfoByArray:和parseMusicDetailByDic:andMusic:,代码如下所示:
+(NSMutableArray *)parseMusicInfoByArray:(NSArray *)arr{
NSMutableArray *musics = [NSMutableArray array];
for (NSDictionary *musicDic in arr) {
TRMusicInfo *mi = [[TRMusicInfo alloc]init];
mi.name = [musicDic objectForKey:@"song"];
mi.singerName = [musicDic objectForKey:@"singer"];
mi.albumName = [musicDic objectForKey:@"album"];
mi.songID = [musicDic objectForKey:@"song_id"];
mi.albumImagePath = [musicDic objectForKey:@"albumPicSmall"];
[musics addObject:mi];
}
return musics;
}
+(void)parseMusicDetailByDic:(NSDictionary *)dic andMusic:(TRMusicInfo *)music{
NSDictionary *dataDic = [dic objectForKey:@"data"];
NSArray *songListArr = [dataDic objectForKey:@"songList"];
NSDictionary *musicDic = [songListArr lastObject];
NSString *musicPath = [musicDic objectForKey:@"showLink"];
music.musicPath = musicPath;
music.lrcPath = [NSString stringWithFormat:@"http://ting.baidu.com%@",[musicDic objectForKey:@"lrcLink"]];
}
步骤二:实现TRMusicListViewController展示音乐列表功能
音乐列表视图控制器TRMusicListViewController继承至UITableViewController,它有一个NSMutableArray类型的属性musics,用于存放需要展示的音乐信息。
在viewDidLoad方法中通过TRWebUtils类调用requestMusicsByWord:andCallBack:方法,根据用户输入的歌手姓名发送网络请求,解析歌曲数据得到属性self.music数据,刷新界面,代码如下所示:
- (void)viewDidLoad
{
[super viewDidLoad];
[TRWebUtils requestMusicsByWord:self.word andCallBack:^(id obj) {
self.musics = obj;
[self.tableView reloadData];
}];
}
用户所挑选的图片将呈现在下方的ScrollView上面,因此需要在弹出ImagePickerController时创建一个ScrollView和一个确定按钮,当点击确定按钮时表示用户完成图片选择,返回之前的界面,该功能需要在navigationController:didShowViewController:animated:方法中实现,代码如下所示:
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
//创建确定按钮
UIImageView *iv = [[UIImageView alloc]initWithFrame:CGRectMake(, , , )];
[iv setBackgroundColor:[UIColor yellowColor]];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(, , , );
[btn setTitle:@"确定" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(finishPickImage) forControlEvents:UIControlEventTouchUpInside];
btn.tag = ;
[iv addSubview:btn];
iv.userInteractionEnabled = YES;
[viewController.view addSubview:iv];
//创建呈现挑选图片的ScrollView
self.pickerScrollView = [[UIScrollView alloc]init];
self.pickerScrollView.frame = CGRectMake(, , ,);
[self.pickerScrollView setBackgroundColor:[UIColor grayColor]];
[viewController.view addSubview:self.pickerScrollView];
}
于表视图的每个Cell需要展示歌曲的信息,所以这里需要自定义一个Cell,因此创建一个TRMusicCell类,继承至UITableViewCell类,需要显示专辑封面,歌曲名、歌手名以及专辑名,代码如下所示:
//TRMusicCell.h
@interface TRMusicCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UILabel *singerLabel;
@property (weak, nonatomic) IBOutlet UIImageView *albumIV;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *albumLabel;
@property (nonatomic, strong)TRMusicInfo *music;
@end
//TRMusicCell.m
@implementation TRMusicCell
-(void)layoutSubviews{
[super layoutSubviews];
self.nameLabel.text = self.music.name;
self.singerLabel.text = self.music.singerName;
self.albumLabel.text = self.music.albumName;
NSLog(@"%@",self.music.albumImagePath);
//从网络获取图片比较耗时,将此操作放入一个操作队列异步执行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.music.albumImagePath]];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
self.albumIV.image = image;
});
});
}
@end
最后实现表视图的数据源方法和delegate委托方法,代码如下所示:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.musics.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
TRMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
TRMusicInfo *music = self.musics[indexPath.row];
cell.music = music;
return cell;
}
//当用户选择某一首歌曲的时候跳转到音乐播放界面
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
TRMusicInfo *m = self.musics[indexPath.row];
[self performSegueWithIdentifier:@"playvc" sender:m];
}
步骤三:实现TRPlayViewController的音乐下载和播放功能
音乐播放视图控制器TRPlayViewController有一个TRMusicInfo类型的公开属性music,用于记录用户从上一个界面选择的音乐信息,代码如下所示:
@interface TRPlayViewController : UIViewController
@property (nonatomic, strong)TRMusicInfo *music;
@end
该视图控制器的私有属性,代码如下所示:
@interface TRPlayViewController ()
@property (weak, nonatomic) IBOutlet UISlider *mySlider;
@property (nonatomic, strong)NSMutableData *allData;
@property (nonatomic, strong)AVAudioPlayer *player;
@property (nonatomic, strong)NSTimer *myTimer;
@property (nonatomic, strong) NSURLConnection *conn;
@property (nonatomic) NSUInteger fileLength;
@end
其次在TRPlayViewController的viewDidLoad方法中通过TRWebUtils类调用requestMusicDetailByMusic:andCallBack:方法,根据音乐信息获取到音乐的下载地址和歌词地址,代码如下所示:
- (void)viewDidLoad
{
[super viewDidLoad];
[TRWebUtils requestMusicDetailByMusic:self.music andCallBack:^(id obj) {
[self downloadMusic];
}];
}
然后通过音乐下载地址发送下载请求,将发送下载请求的代码封装在downloadMusic方法中,代码如下所示:
-(void)downloadMusic{
NSURL *url = [NSURL URLWithString:self.music.musicPath];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//对象创建出来时异步请求已经发出
self.conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if (!self.conn) {
NSLog(@"链接创建失败");
}
}
接下来实现NSURLConnectionDelegate的协议方法,在connection:didReceiveResponse:方法中解析头文件,获取到文件的大小并初始化self.allData属性,代码如下所示:
//接收到服务器响应
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;
NSDictionary *headerDic = res.allHeaderFields;
NSLog(@"%@",headerDic);
self.fileLength = [[headerDic objectForKey:@"Content-Length"] intValue];
self.allData = [NSMutableData data];
}
在connection:didReceiveData:方法中将下载到的音乐数据保存在self.allData中,并且创建音乐播放器并播放歌曲,实现边下载边播放的功能,代码如下所示:
//接收到数据
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
// NSLog(@"%d",data.length);
[self.allData appendData:data];
//初始化player对象
if (self.allData.length>*&&!self.player) {
NSLog(@"开始播放");
self.player = [[AVAudioPlayer alloc]initWithData:self.allData error:Nil];
[self.player play];
float allTime = self.player.duration*self.fileLength/self.allData.length;
self.mySlider.maximumValue = allTime;
}
}
在connectionDidFinishLoading:方法中将音乐的数据存入本地,代码如下所示:
//加载完成
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"下载完成");
//下载完成之后更新准确的歌曲时长
self.mySlider.maximumValue = self.player.duration;
NSString *filePath = [NSString stringWithFormat:@"/Users/Vivian/Desktop/%@",self.music.name];
filePath = [filePath stringByAppendingPathExtension:@"mp3"];
[self.allData writeToFile:filePath atomically:YES];
}
最后在downloadMusic方法中开启一个计时器,更新进度条的显示,即音乐的播放进度,代码如下所示:
-(void)downloadMusic{
NSURL *url = [NSURL URLWithString:self.music.musicPath];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//对象创建出来时异步请求已经发出
self.conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if (!self.conn) {
NSLog(@"链接创建失败");
}
//开启一个计时器,更新界面的进度条
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:. target:self selector:@selector(updateUI) userInfo:Nil repeats:YES];
}
-(void)viewDidDisappear:(BOOL)animated{
[self.myTimer invalidate];
}
-(void)updateUI{
self.mySlider.value = self.player.currentTime;
}
1.4 完整代码
本案例中,TRViewController.m文件中的完整代码如下所示:
#import "TRViewController.h"
#import "TRMusicListViewController.h"
@interface TRViewController ()
@property (weak, nonatomic) IBOutlet UITextField *myTF;
@end
@implementation TRViewController
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
TRMusicListViewController *vc = segue.destinationViewController;
vc.word = self.myTF.text;
}
@end
本案例中,TRMusicListViewController.h文件中的完整代码如下所示:
#import <UIKit/UIKit.h>
@interface TRMusicListViewController : UITableViewController
@property (nonatomic, copy)NSString *word;
@end
本案例中,TRMusicListViewController.m文件中的完整代码如下所示:
#import "TRMusicCell.h"
#import "TRMusicListViewController.h"
#import "TRParser.h"
#import "TRMusicInfo.h"
#import "TRWebUtils.h"
#import "TRPlayViewController.h"
@interface TRMusicListViewController ()
@property (nonatomic, strong)NSMutableArray *musics;
@end
@implementation TRMusicListViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[TRWebUtils requestMusicsByWord:self.word andCallBack:^(id obj) {
self.musics = obj;
[self.tableView reloadData];
}];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.musics.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
TRMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
TRMusicInfo *music = self.musics[indexPath.row];
cell.music = music;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
TRMusicInfo *m = self.musics[indexPath.row];
[self performSegueWithIdentifier:@"playvc" sender:m];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
TRPlayViewController *vc = segue.destinationViewController;
vc.music = sender;
}
@end
本案例中,TRPlayViewController.h文件中的完整代码如下所示:
#import <UIKit/UIKit.h>
#import "TRMusicInfo.h"
@interface TRPlayViewController : UIViewController
@property (nonatomic, strong)TRMusicInfo *music;
@end
本案例中,TRPlayViewController.m文件中的完整代码如下所示:
#import "TRPlayViewController.h"
#import "TRWebUtils.h"
#import <AVFoundation/AVFoundation.h>
@interface TRPlayViewController ()
@property (weak, nonatomic) IBOutlet UISlider *mySlider;
@property (nonatomic, strong)NSMutableData *allData;
@property (nonatomic, strong)AVAudioPlayer *player;
@property (nonatomic, strong)NSTimer *myTimer;
@property (nonatomic, strong) NSURLConnection *conn;
@property (nonatomic) NSUInteger fileLength;
@end
@implementation TRPlayViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[TRWebUtils requestMusicDetailByMusic:self.music andCallBack:^(id obj) {
[self downloadMusic];
}];
}
-(void)downloadMusic{
NSURL *url = [NSURL URLWithString:self.music.musicPath];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//对象创建出来时 异步请求已经发出
self.conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if (!self.conn) {
NSLog(@"链接创建失败");
}
//开启一个计时器,更新界面的进度条
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:. target:self selector:@selector(updateUI) userInfo:Nil repeats:YES];
}
-(void)viewDidDisappear:(BOOL)animated{
[self.myTimer invalidate];
}
-(void)updateUI{
self.mySlider.value = self.player.currentTime;
}
#pragma mark NSURLConnectionDelegate
//接收到服务器响应
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;
NSDictionary *headerDic = res.allHeaderFields;
NSLog(@"%@",headerDic);
self.fileLength = [[headerDic objectForKey:@"Content-Length"] intValue];
self.allData = [NSMutableData data];
}
//接收到数据
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
// NSLog(@"%d",data.length);
[self.allData appendData:data];
//初始化player对象
if (self.allData.length>*&&!self.player) {
NSLog(@"开始播放");
self.player = [[AVAudioPlayer alloc]initWithData:self.allData error:Nil];
[self.player play];
float allTime = self.player.duration*self.fileLength/self.allData.length;
self.mySlider.maximumValue = allTime;
}
}
//加载完成
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"下载完成");
//下载完成之后更新准确的歌曲时长
self.mySlider.maximumValue = self.player.duration;
NSString *filePath = [NSString stringWithFormat:@"/Users/Vivian/Desktop/%@",self.music.name];
filePath = [filePath stringByAppendingPathExtension:@"mp3"];
[self.allData writeToFile:filePath atomically:YES];
}
@end
本案例中,TRMusicCell.h文件中的完整代码如下所示:
#import <UIKit/UIKit.h>
#import "TRMusicInfo.h"
@interface TRMusicCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UILabel *singerLabel;
@property (weak, nonatomic) IBOutlet UIImageView *albumIV;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *albumLabel;
@property (nonatomic, strong)TRMusicInfo *music;
@end
本案例中,TRMusicCell.m文件中的完整代码如下所示:
@implementation TRMusicCell
-(void)layoutSubviews{
[super layoutSubviews];
self.nameLabel.text = self.music.name;
self.singerLabel.text = self.music.singerName;
self.albumLabel.text = self.music.albumName;
NSLog(@"%@",self.music.albumImagePath);
//从网络获取图片比较耗时,将此操作放入一个操作队列异步执行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.music.albumImagePath]];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
self.albumIV.image = image;
});
});
}
@end
本案例中,TRMusicInfo.h文件中的完整代码如下所示:
#import <Foundation/Foundation.h>
@interface TRMusicInfo : NSObject
@property (nonatomic, copy)NSString *name;
@property (nonatomic, copy)NSString *singerName;
@property (nonatomic, copy)NSString *albumName;
@property (nonatomic, copy)NSString *songID;
@property (nonatomic, copy)NSString *albumImagePath;
@property (nonatomic, copy)NSString *musicPath;
@property (nonatomic, copy)NSString *lrcPath;
@end
本案例中,TRParser.h文件中的完整代码如下所示:
#import <Foundation/Foundation.h>
#import "TRMusicInfo.h"
@interface TRParser : NSObject
+ (NSMutableArray *)parseMusicInfoByArray:(NSArray *)arr;
+ (void)parseMusicDetailByDic:(NSDictionary *)dic andMusic:(TRMusicInfo *)music;
@end
本案例中,TRParser.m文件中的完整代码如下所示:
#import "TRParser.h"
#import "TRMusicInfo.h"
@implementation TRParser
+(NSMutableArray *)parseMusicInfoByArray:(NSArray *)arr{
NSMutableArray *musics = [NSMutableArray array];
for (NSDictionary *musicDic in arr) {
TRMusicInfo *mi = [[TRMusicInfo alloc]init];
mi.name = [musicDic objectForKey:@"song"];
mi.singerName = [musicDic objectForKey:@"singer"];
mi.albumName = [musicDic objectForKey:@"album"];
mi.songID = [musicDic objectForKey:@"song_id"];
mi.albumImagePath = [musicDic objectForKey:@"albumPicSmall"];
[musics addObject:mi];
}
return musics;
}
+(void)parseMusicDetailByDic:(NSDictionary *)dic andMusic:(TRMusicInfo *)music{
NSDictionary *dataDic = [dic objectForKey:@"data"];
NSArray *songListArr = [dataDic objectForKey:@"songList"];
NSDictionary *musicDic = [songListArr lastObject];
NSString *musicPath = [musicDic objectForKey:@"showLink"];
music.musicPath = musicPath;
music.lrcPath = [NSString stringWithFormat:@"http://ting.baidu.com%@",[musicDic objectForKey:@"lrcLink"]];
}
@end
本案例中,TRWebUtils.h文件中的完整代码如下所示:
#import <Foundation/Foundation.h>
#import "TRMusicInfo.h"
typedef void (^MyCallback)(id obj);
@interface TRWebUtils : NSObject
+ (void)requestMusicsByWord:(NSString *)word andCallBack:(MyCallback)callback;
+ (void)requestMusicDetailByMusic:(TRMusicInfo *)music andCallBack:(MyCallback)callback;
@end
本案例中,TRWebUtils.m文件中的完整代码如下所示:
#import "TRWebUtils.h"
#import "TRParser.h"
@implementation TRWebUtils
+ (void)requestMusicsByWord:(NSString *)word andCallBack:(MyCallback)callback{
NSString *path = [NSString stringWithFormat:@"http://mp3.baidu.com/dev/api/?tn=getinfo&ct=0&word=%@&ie=utf-8&format=json",word];
path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:path];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSArray *arr = [NSJSONSerialization JSONObjectWithData:data options: error:Nil];
if (arr.count==) {
[TRWebUtils requestMusicsByWord:word andCallBack:callback];
}
NSMutableArray *musics = [TRParser parseMusicInfoByArray:arr];
callback(musics);
}];
}
+ (void)requestMusicDetailByMusic:(TRMusicInfo *)music andCallBack:(MyCallback)callback{
NSString *path = [NSString stringWithFormat:@"http://ting.baidu.com/data/music/links?songIds=%@",music.songID];
NSLog(@"%@",path);
NSURL *url = [NSURL URLWithString:path];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options: error:Nil];
[TRParser parseMusicDetailByDic:dic andMusic:music];
callback(music);
}];
}
@end
MEDIA-SYSSERVICES媒体播放的更多相关文章
- (原创)jQuery Media Plugin-jQuery的网页媒体播放器插件的使用心得
jQuery Media Plugin是一款基于jQuery的网页媒体播放器插件,它支持大部分的网络多媒体播放器和多媒体格式,比如:Flash, Windows Media Player, Real ...
- 与众不同 windows phone (15) - Media(媒体)之后台播放音频
原文:与众不同 windows phone (15) - Media(媒体)之后台播放音频 [索引页][源码下载] 与众不同 windows phone (15) - Media(媒体)之后台播放音频 ...
- 与众不同 windows phone (14) - Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成
原文:与众不同 windows phone (14) - Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成 [索引页][源码下载] 与众不同 win ...
- C#编写媒体播放器--Microsoft的Directx提供的DirectShow组件,该组件的程序集QuartzTypeLib.dll.
使用C#编写媒体播放器时,需要用到Microsoft的Directx提供的DirectShow组件.用该组件前需要先注册程序集QuartzTypeLib.dll. 1.用QuartzTypeLib.d ...
- 快速构建Windows 8风格应用21-构建简单媒体播放器
原文:快速构建Windows 8风格应用21-构建简单媒体播放器 本篇博文主要介绍如何构建一个简单的媒体播放器. <快速构建Windows 8风格应用20-MediaElement>博文中 ...
- WinForm媒体播放器
媒体播放控件(Windows Media Player )的常用属性和方法,并且利用它设计一个简单的媒体应用程序——媒体播放器.该媒体播放器可以播放 wav.avi.mid 和 mp3 等格式的文件. ...
- JavaScript自定义媒体播放器
使用<audio>和<video>元素的play()和pause()方法,可以手工控制媒体文件的播放.组合使用属性.事件和这两个方法,很容易创建一个自定义的媒体播放器,如下面的 ...
- Plyr – 简单,灵活的 HTML5 媒体播放器
Plyr 是一个简单的 HTML5 媒体播放器,包含自定义的控制选项和 WebVTT 字幕.它是只支持现代浏览器,轻量,方便和可定制的媒体播放器.还有的标题和屏幕阅读器的全面支持. 在线演示 ...
- 【C语言入门教程】4.10 综合实例 - 媒体播放器
4.10.1 建立播放列表 数据字典 名称 数据类型 说明 MAX_LENGTH 符号常量 用于定义数组长度,表示列表最大长度 MAX_FILE_LENGTH 符号常量 用于定义数组长度,表示文件名最 ...
- .net C# 网页播放器 支持多种格式 媒体播放器 播放器 代码
.avi格式代码片断如下:<object id='video' width='400' height='200' border='0' classid='clsid:CFCDAA03-8BE4- ...
随机推荐
- CSS 盒子模型概述
一.简介 CSS 盒子模型(元素框)由元素内容(content).内边距(padding).边框(border).外边距(margin)组成. 盒子模型,最里面的部分是实际内容:直接包围内 ...
- Duilib实现类似电脑管家扫描目录效果
实现原理: 1.后台开线程遍历目录,遍历出一个文件路径在界面上更新显示(通过发消息通知主界面) 2.需要扩展一下Duilib控件,在此我扩展了CLabelUI,重写了PaintText函数 扩展控件的 ...
- iOS开发数据库篇—SQLite常用的函数
iOS开发数据库篇—SQLite常用的函数 一.简单说明 1.打开数据库 int sqlite3_open( const char *filename, // 数据库的文件路径 sqlite3 * ...
- 使用easyui时 进入一个新页面 前要经过一个页面混乱的时候 才到正常的页面去
var width = $(window).width(); var height = $(window).height(); var html = "<div id='loading ...
- N的阶乘末尾0的个数和其二进制表示中最后位1的位置
问题一解法: 我们知道求N的阶乘结果末尾0的个数也就是说我们在从1做到N的乘法的时候里面产生了多少个10, 我们可以这样分解,也就是将从0到N的数分解成因式,再将这些因式相乘,那么里面有多少个 ...
- SAP的物料归档
我们在对前台对物料进行删除时,是物理删除,也就是打个删除标志,并没有正真的从数据库里删除,在前台还是可以看到的,下面介绍一下SAP的归档处理可以 把已删除的物料在前台删除掉,注意:项目里根据情况得到领 ...
- LCT专题练习
[bzoj2049]洞穴勘测 http://www.cnblogs.com/Sdchr/p/6188628.html 小结 (1)LCT可以方便维护树的连通性,但是图的连通性的维护貌似很麻烦. [bz ...
- Construct Binary Tree from Preorder and Inorder Traversal [LeetCode]
Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...
- App压力测试整理
压力测试结果:CRASH:崩溃,应用程序在使用过程中,非正常退出ANR:Application Not Responding MonkeyRunner APIs MonkeyRunner:用来连接设备 ...
- 介绍开源的.net通信框架NetworkComms框架之八 UDP通信
原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 许可是 ...