ios_33_ Music Playback (background play + lock screen lyrics)

Source: Internet
Author: User
Tags rewind set background

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)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.