Eventually:
Application proxy (three-step background play)
beyondappdelegate.h// 33_ audio//// Created by Beyond on 14-9-10.// Copyright (c) 2014 Com.beyond. All rights reserved.//#import <UIKit/UIKit.h> @interface Beyondappdelegate:uiresponder < Uiapplicationdelegate> @property (Strong, nonatomic) UIWindow *window; @end
////BeyondAppDelegat e.m//33_ Audio////Created by Beyond on 14-9-10.//Copyright (c) 2014 Com.beyond. All rights reserved.//#import "BeyondAppDelegate.h" @implementation beyondappdelegate-(BOOL) Application: ( UIApplication *) Application didfinishlaunchingwithoptions: (nsdictionary *) launchoptions{//Override point for Customi Zation after application launch. return YES;} -(void) Applicationdidenterbackground: (uiapplication *) application{//Use the method to release shared resources, SAV E user data, invalidate timers, and store enough application state information to restore your application State-in-case it is terminated later. If your application supports background execution, this method is called instead of Applicationwillterminate:when the User quits. Background play one of three steps: Let the app run in the background [application Beginbackgroundtaskwithexpirationhandler:nil];} @end
Controller
songcontroller.h// 33_ audio//// Created by Beyond on 14-9-10.// Copyright (c) 2014 Com.beyond. All rights reserved.// music playback controller, inherited from Tableviewctrl#import <UIKit/UIKit.h> @interface Songcontroller: Uitableviewcontroller@end
songcontroller.m//33_ Audio////Created by Beyond on 14-9-10.//Copyright (c) 2014 Com.beyond. All rights reserved.//Music playback controller, inherits from Tableviewctrl#import "SongController.h"//core frame, must import, lock screen display lyrics #import <avfoundation/ avfoundation.h> #import <mediaplayer/mediaplayer.h>//model #import "Song.h"//View #import "SongCell.h"//Tools # Import "SongTool.h" #pragma mark-class extension @interface Songcontroller () <avaudioplayerdelegate>//Object array @property (strong , nonatomic) Nsarray *songarr;//the player (temporarily useless) that corresponds to the line currently selected @property (Nonatomic, strong) Avaudioplayer * currentplayingaudioplayer;//Player Agent method, there is no way to listen to the song playback progress//can only open a timer, real-time monitoring the progress of the song @property (Nonatomic, Strong) Cadisplaylink *link;-(ibaction) Jump: (ID) sender; @end @implementation songcontroller-(void) viewdidload{[super Viewdidload]; Prevent the navigation bar from covering Self.tableView.contentInset = Uiedgeinsetsmake (20, 0, 0, 0);} #pragma mark-Lazy load-(Nsarray *) songarr{if (!_songarr) {//Classification method, one-Step object array Self.songarr = [Song objectarray withfilename:@ "SOngarr.plist "]; } return _songarr;} The agent method of the player, there is no way to listen to the song playback progress//can only open a timer, real-time listening to the progress of the song playback-(Cadisplaylink *) link{if (!_link) {self.link = [Cadispla Ylink displaylinkwithtarget:self selector: @selector (update)]; } return _link;} #pragma mark-clock method//Player's proxy method, there is no way to listen to the song playback progress//can only open a timer, real-time listening to the progress of the song//real-time update (60 times in 1 seconds)-(void) update{//NSLog (@ " Total length:%f Current playback:%f ", Self.currentPlayingAudioPlayer.duration, self.currentPlayingAudioPlayer.currentTime); #warning Adjust the lyrics of the lock screen} #pragma mark-connect Method-(ibaction) Jump: (ID) sender{//Control playback progress (in seconds) self.currentPlayingAudioPlayer.currentTime = self.currentplayingaudioplayer.duration-3;} #pragma mark-avaudioplayer Proxy method//Call when a song is finished, stop the animation, and skip to the next play-(void) audioplayerdidfinishplaying: (Avaudioplayer *) Player successfully: (BOOL) flag{//1. Start with the line number of the song that is currently playing, and through it, calculate the line number of the next line (anti-crossing) nsindexpath *selectedpath = [Self.tableview i Ndexpathforselectedrow]; int NextRow = Selectedpath.row + 1; if (NextRow = = Self.songArr.count) {NextRow= 0; }//2. Stop circling the previous song (Modify the model and pass the model again to the custom cell) Songcell *cell = (Songcell *) [Self.tableview Cellforrowatindexpath:selec Tedpath]; Song *music = Self.songarr[selectedpath.row]; music.playing = NO; The inside will intercept the setter method and stop the spinning animation cell.music = music; 3. Play the next song (select and scroll to the corresponding location) nsindexpath *nextpath = [Nsindexpath indexpathforrow:nextrow inSection:selectedPath.section]; The interface is selected [Self.tableview selectrowatindexpath:nextpath animated:yes scrollposition:uitableviewscrollpositiontop]; Invoke proxy method manually [self TableView:self.tableView didselectrowatindexpath:nextpath];} #pragma mark play interrupted and resumed//music player interrupted (e.g. start, answer call)-(void) Audioplayerbegininterruption: (Avaudioplayer *) player{//will automatically pause do Nothing ... NSLog (@ "Audioplayerbegininterruption---interrupted");} Music player interrupt termination (e.g. end of call, answer call)-(void) Audioplayerendinterruption: (Avaudioplayer *) player withoptions: (Nsuinteger) flags{//Hand Resume playback [player play]; NSLog (@ "Audioplayerendinterruption---interrupt termination");} #pragma mark-Data source//How many lines-(Nsinteger) TableView: (UITableView *) TableView numberofrowsinsection: (nsinteger) section{return self.songArr.count;} Each row is unique to the cell (to the custom cell delivery model)-(UITableViewCell *) TableView: (UITableView *) TableView Cellforrowatindexpath: ( Nsindexpath *) indexpath{//1. Custom cell class method, quickly create cell songcell *cell = [Songcell Cellwithtableview:tableview]; 2. Set the data source of the cell cell.music = Self.songarr[indexpath.row]; 3. Return the generated and populated cell return cell;} Height of each line-(cgfloat) TableView: (UITableView *) TableView Heightforrowatindexpath: (Nsindexpath *) indexpath{return 70;} #pragma mark-Proxy method//Select a line to play the corresponding music-(void) TableView: (UITableView *) TableView Didselectrowatindexpath: (Nsindexpath *) indexpath{//1. Obtain the corresponding model of the line and modify its IsPlaying property Song *music = Self.songarr[indexpath.row]; if (music.isplaying) {return; }//property "playing" assignment is true music.playing = YES; 2. Pass the data source model to the tool class play music avaudioplayer *audioplayer = [Songtool playMusic:music.filename]; Audioplayer.delegate = self; Self.currentplayingaudioplayer = Audioplayer; 3. Important ~ ~ ~ Display song information on the lock screen [self showinfoinlockedscreen:music]; 4. Turn on the timer, monitor the playback progress (first close the old) [Self.link invalidate]; Self.link = nil; [Self.link Addtorunloop:[nsrunloop Mainrunloop] formode:nsdefaultrunloopmode]; 5. Pass the data source model again to the custom cell (performing a spinning animation) Songcell *cell = (Songcell *) [TableView Cellforrowatindexpath:indexpath]; Cell.music = music;} When a row is deselected, the music is stopped, animation-(void) TableView: (UITableView *) TableView Diddeselectrowatindexpath: (Nsindexpath *) indexpath{// 1. Obtain the corresponding model of the line and modify its IsPlaying property Song *music = Self.songarr[indexpath.row]; music.playing = NO; 2. According to the music name, stop the music (internal will traverse) [Songtool StopMusic:music.filename]; 3. Pass the data source model again to the custom cell (stop circling) Songcell *cell = (Songcell *) [TableView Cellforrowatindexpath:indexpath]; Cell.music = music;} #pragma mark-Lock screen lyrics//display the song information on the lock screen (real-time change picture mpmediaitemartwork can achieve the purpose of real-time change lyrics)-(void) Showinfoinlockedscreen: (Song *) music{ Robustness: If this class exists, you can display lyrics if (N) on the lock screen.Sclassfromstring (@ "Mpnowplayinginfocenter")) {//Core: Dictionary nsmutabledictionary *info = [nsmutabledictionary dic Tionary]; Title (music name) info[mpmediaitempropertytitle] = Music.name; Artist Info[mpmediaitempropertyartist] = Music.singer; Album name Info[mpmediaitempropertyalbumtitle] = Music.singer; Picture Info[mpmediaitempropertyartwork] = [[Mpmediaitemartwork alloc] Initwithimage:[uiimage ImageNamed:music.icon] ; The only API, Singleton, Nowplayinginfo dictionary [mpnowplayinginfocenter defaultcenter].nowplayinginfo = info; }} @end
Model
song.h// 33_ audio//// Created by Beyond on 14-9-10.// Copyright (c) 2014 Com.beyond. All rights reserved.// model, a song, members many #import <Foundation/Foundation.h> @interface song:nsobject// Song name @property (copy, nonatomic) nsstring *name;//file name, such as @ "A.mp3" @property (copy, nonatomic) NSString *filename;// Artist @property (copy, nonatomic) nsstring *singer;//artist Avatar @property (copy, nonatomic) nsstring *singericon;//artist Big Picture ( Lock screen when used) @property (copy, nonatomic) nsstring *icon;//tag, used to rotate the avatar @property (nonatomic, assign, getter = isplaying) BOOL playi ng; @end
Custom View Songcell
songcell.h// 33_ audio//// Created by Beyond on 14-9-10.// Copyright (c) 2014 Com.beyond. All rights reserved.// view, custom cell, dependent model #import <uikit/uikit.h>//View dependent model @class Song; @interface Songcell : uitableviewcell//Data Source Model @property (nonatomic, strong) Song *music;//Controller knows least + (Instancetype) Cellwithtableview: ( UITableView *) TableView; @end
songcell.m//33_ Audio////Created by Beyond on 14-9-10.//Copyright (c) 2014 Com.beyond. All rights reserved.//View, custom cell, dependent model #import "SongCell.h"//model, data source #import "Song.h" #import "Colours.h" #pragma mark-class Extended @interface Songcell ()//For Avatar rotation cgaffinetransformrotate, one second turn 45 degrees @property (nonatomic, strong) Cadisplaylink *link;@ End@implementation songcell#pragma mark-Lazy load-(Cadisplaylink *) link{if (!_link) {self.link = [Cadisplaylink D Isplaylinkwithtarget:self selector: @selector (update)]; } return _link;} #pragma mark-For external calls + (Instancetype) Cellwithtableview: (UITableView *) tableview{static NSString *id = @ "Music"; Songcell *cell = [TableView dequeuereusablecellwithidentifier:id]; if (cell = = nil) {cell = [[Songcell alloc] Initwithstyle:uitableviewcellstylesubtitle Reuseidentifier:id]; } return cell; Block setter methods, assign values to inner child controls, and animate in circles-(void) Setmusic: (Song *) music{_music = music; Set unique data Self.textLabel.text = Music.name; Self.Detailtextlabel.text = Music.singer; Classification method, create a circular border self.imageView.image = [UIImage circleImageWithName:music.singerIcon borderwidth:2 bordercolor:[ Uicolor Skybluecolor]]; If the properties of the model isplaying true, start cgaffinetransformrotate if (music.isplaying) {[Self.link addtorunloop:[nsrunloop MainR Unloop] Formode:nsdefaultrunloopmode]; } else {//If the model's isplaying is false, stop the clock animation and return the cgaffinetransformrotate to zero [self.link invalidate]; Self.link = nil; Self.imageView.transform = cgaffinetransformidentity; }} #pragma mark-clock method//angular speed: 45°/s, i.e. 8 second turn-(void) update{//Deltaangle = 1/60 seconds * 45//Two calls rotation angle = = time * Speed CGFloat angle = self.link.duration * M_PI_4; No core animation, because after entering the background, the animation stopped self.imageView.transform = Cgaffinetransformrotate (self.imageView.transform, angle);} @end
Music Playback Tool Class
songtool.h// 33_ audio//// Created by Beyond on 14-9-10.// Copyright (c) 2014 Com.beyond. All rights reserved.//#import <foundation/foundation.h>//Music Tool class, you must import Avfoundation's main header file #import <avfoundation /avfoundation.h> @interface songtool:nsobject//class method, play Music, parameters: Music file name such as @ "A.mp3", in order to be able to give the player Avaudioplayer object set proxy, After creating the Player object, return it to the caller//set up the agent, you can listen to the player interrupted and resumed interrupt + (Avaudioplayer *) Playmusic: (NSString *) filename;//class method, pause music, parameters: Music filename such as @ "A.mp3" + (void) Pausemusic: (NSString *) filename;//class method, stop music, parameters: Music filename such as @ "A.mp3", remember to remove + (void) from the dictionary Stopmusic :(NSString *) filename;//returns the music player that is currently playing, allowing the outside world to control its fast forward, rewind or other methods + (Avaudioplayer *) Currentplayingaudioplayer; @end
songtool.m//33_ Audio////Created by Beyond on 14-9-10.//Copyright (c) 2014 Com.beyond. All rights reserved.//#import "SongTool.h" @implementation songtool//dictionary, storing all the music players, keys are: Music name, value is corresponding to the music player object audioplayer// A song corresponds to a music player static nsmutabledictionary *_audioplayerdict; #pragma mark-life cycle+ (void) initialize{//Dictionary, key is: Music name, value is the corresponding The music player Object _audioplayerdict = [Nsmutabledictionary dictionary]; Set background playback [self sutupforbackgroundplay];} Set background play + (void) sutupforbackgroundplay{//Background play The third step of three steps, set the audio session type avaudiosession *session = [Avaudiosession Sharedin STANCE]; Type: Play and record [session Setcategory:avaudiosessioncategoryplayandrecord Error:nil]; and to activate the audio session [session Setactive:yes Error:nil];} #pragma mark-for external calls//class methods, play music, Parameters: Music file name such as @ "A.mp3"//In order to be able to set the agent Avaudioplayer object, after creating a good player object, return it to the caller//set up the agent, Can listen to the player being interrupted and resumed interrupt + (Avaudioplayer *) Playmusic: (NSString *) filename{//Robustness judgment if (!filename) return nil; 1. First from the dictionary, according to the music file name, take out the corresponding Audioplayer AVAUDIOPLayer *audioplayer = _audioplayerdict[filename]; if (!audioplayer) {//if not, the corresponding music player needs to be created and stored in the dictionary//1.1 load Music file Nsurl *url = [[NSBundle Mainbundle] Urlf Orresource:filename Withextension:nil]; Robustness judgment if (!url) return nil; 1.2 According to the music URL, create the corresponding audioplayer Audioplayer = [[Avaudioplayer alloc] Initwithcontentsofurl:url Error:nil]; 1.3 Start buffering [Audioplayer Preparetoplay]; If you want to achieve variable speed playback, you must also set the following two parameters//audioplayer.enablerate = YES; Audioplayer.rate = 10.0; 1.4 Finally, put dictionary _audioplayerdict[filename] = audioplayer; }//2. To start playing if (!audioplayer.isplaying) {[Audioplayer play] if it is paused or stopped; }//3. Returns the created player, facilitates the caller to set the agent, listens to the player's progress currenttime return audioplayer;} class method, pause music, parameters: music filename such as @ "A.mp3" + (void) Pausemusic: (NSString *) filename{//Robustness judgment if (!filename) return; 1. First from the dictionary, according to the key "filename", remove Audioplayer "must have value" Avaudioplayer *audioplayer = _audioplayerdict[filename]; 2. If you are playing, you need to pause if (audioplayer.isplaying) {[Audioplayer pause]; }}//class method, stop music, parameters: music filename such as @ "A.mp3", remember to remove the + (void) Stopmusic from the Dictionary: (NSString *) filename{//Robustness judgment if (!filename) return; 1. First from the dictionary, according to the key "filename", remove Audioplayer "must have value" avaudioplayer *audioplayer = _audioplayerdict[filename]; 2. If it is playing, only need to stop if (audioplayer.isplaying) {//2.1 stop [audioplayer stop]; 2.2 Finally, remember to remove [_audioplayerdict removeobjectforkey:filename] from the dictionary; }}//returns the currently playing music player to facilitate outside control of its fast forward, rewind or other method + (Avaudioplayer *) currentplayingaudioplayer{//Traversal dictionary key, and then according to the key to remove the value, if it is playing, The player for (NSString *filename in _audioplayerdict) {Avaudioplayer *audioplayer = _audioplayerdict[filename] is returned; if (audioplayer.isplaying) {return audioplayer; }} return nil;} @end
Category of picture plus circle border
uiimage+circle.h// 33_ audio//// Created by Beyond on 14-9-15.// Copyright (c) 2014 Com.beyond. All rights reserved.// round bezel #import <UIKit/UIKit.h> @interface UIImage (circle) + (Instancetype) Circleimagewithname: (NSString *) name BorderWidth: (cgfloat) borderWidth bordercolor: (Uicolor *) bordercolor; @end
uiimage+circle.m//33_ Audio////Created by Beyond on 14-9-15.//Copyright (c) 2014 Com.beyond. All rights reserved.//#import "Uiimage+circle.h" @implementation UIImage (Circle) + (instancetype) circleimagewithname :(NSString *) name BorderWidth: (cgfloat) borderWidth bordercolor: (Uicolor *) bordercolor{//1. Loading the original image UIImage *oldimage = [UIImage Imagenamed:name]; 2. Open context CGFloat Imagew = oldImage.size.width + 2 * borderWidth; CGFloat Imageh = oldImage.size.height + 2 * borderWidth; Cgsize imageSize = Cgsizemake (Imagew, Imageh); Uigraphicsbeginimagecontextwithoptions (ImageSize, NO, 0.0); 3. Get the current context cgcontextref CTX = Uigraphicsgetcurrentcontext (); 4. Draw the frame (great circle) [BorderColor set]; CGFloat Bigradius = Imagew * 0.5; Circle radius cgfloat CenterX = Bigradius; Center CGFloat centery = Bigradius; Cgcontextaddarc (CTX, CenterX, CenterY, Bigradius, 0, M_PI * 2, 0); Cgcontextfillpath (CTX); Draw a circle//5. Small Circle CGFloat Smallradius = Bigradius -BorderWidth; Cgcontextaddarc (CTX, CenterX, CenterY, Smallradius, 0, M_PI * 2, 0); Cropping (the things that are drawn later will be affected by clipping) Cgcontextclip (CTX); 6. Drawing [Oldimage Drawinrect:cgrectmake (BorderWidth, BorderWidth, OldImage.size.width, OldImage.size.height)]; 7. Take figure UIImage *newimage = Uigraphicsgetimagefromcurrentimagecontext (); 8. End context Uigraphicsendimagecontext (); return newimage;} @end
ios_33_ Music Playback (background play + lock screen lyrics)