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- ...
随机推荐
- [转]NPOI 单元格级别应用
原文地址:http://hi.baidu.com/linrao/item/fadf96dce8770753d63aaef2 HSSFWorkbook hssfworkbook = new HSSFWo ...
- python 学习笔记十二 html基础(进阶篇)
HTML 超级文本标记语言是标准通用标记语言下的一个应用,也是一种规范,一种标准,它通过标记符号来标记要显示的网页中的各个部分.网页文件本身 是一种文本文件,通过在文本文件中添加标记符, 可以告诉浏览 ...
- 解决安装完centos6.6之后/etc/sysconfig/目录下没有iptables 的问题
我在安装完成centos6.6之后对防火墙进行配置,但是发现在/etc/sysconfig目录下没有iptables,心里犯嘀咕,随后就写了一条命令,保存下试试,谁知道成功了! 如图 没有发现ipta ...
- oracle组查询
概念: 所谓组查询即将数据按照某列或者某些列相同的值进行分组,然后对该组的数据进行组函数运用,针对每一组返回一个结果. note: 1.组函数可以出现的位置: select子句和having 子句 2 ...
- 【转载】详解CreateProcess调用内核创建进程的过程
原文:详解CreateProcess调用内核创建进程的过程 昨天同学接到了腾讯的电面,有一题问到了CreateProcess创建进程的具体实现过程,他答得不怎么好吧应该是, 为了以防万一,也为了深入学 ...
- [HIHO1052]基因工程(找规律)
题目链接:http://hihocoder.com/problemset/problem/1052 题意:中文题面,就是修改其中几个字符,使得[0,k-1]和[n-k,n-1]的字符相同. 会发现一个 ...
- jsp标签精华(持续更新中)
<%@ taglib uri="/struts-tags" prefix="s" %> <%@ taglib uri="http:/ ...
- PHP 小方法之 计算两个时间戳之间相差的日时分秒
if(! function_exists ('timediff') ) { function timediff($begin_time,$end_time){ if($begin_time < ...
- GPRS模块上电后复位会导致开机函数不正常的问题原因及解决方法
之前使用的开机函数 void Gprs_modem_start_up(){GPIO_SetBits(GPIOB,GPIO_Pin_0); //RESET 脚要置成高电平,防止重启do{ GPIO_Se ...
- 通过java输出当前系统时间
获取当前系统时间和日期并格式化输出: import java.util.Date; import java.text.SimpleDateFormat; public class NowString ...