A summary of the core technical points of IOS for playing remote network music _ios

Source: Internet
Author: User

First, the preface

The two days of a small project involving remote music playback, because the first time to do this music project, side of the data to do, which involves the main technical points are:

    • How to play remote network music
    • How to toggle music resources that are currently playing
    • How to monitor the various states of music playback (player status, playback progress, buffering progress, playback complete)
    • How to manually manipulate playback progress
    • How to play music correctly in background mode or lock screen
    • How to display music playback information and remote control music in lock screen mode

If you are interested in a technical point or are looking for relevant information, then this article may provide some reference or inspiration.

Second, the network music plays the core technical point

According to their experience and check some of the music playback of the relevant information, the simplest and most easy to use the technical program I think should be the iOS system with the Avfoundation framework.

We know that the Avfoundation framework is a library of Apple specifically designed for multimedia, a library that is very powerful to deal with complex multimedia technologies such as audio and video, and all the technical points in this article are based on a class--avplayer in the Avfoundation framework.

So what's Avplayer?

You can think of him as a packaged player, which is used to play remote or local video and audio. Because the local audio and video playback is relatively simple, here is not to tell, this is mainly about remote music playback, because all are based on Avplayer the same set of APIs, so mastering remote music playback is actually equivalent to mastering remote video playback. All right, there's no more talking, so start serving.

1, import avfoundation frame, create Avplayer player

-(Avplayer *) player
{
  if (_player = = nil) {
     //Avplayeritem is a class that wraps music resources that can be passed into a music URL when initialized
    Avplayeritem *item = [[Avplayeritem alloc] initwithurl:[nsurl urlwithstring:@ "http://xxxxxxxx"]];
    Initializing the player
    _player = [[Avplayer alloc] initwithplayeritem:item] via avplayeritem;

  return _player;
}

Here lazy load Create, let the player become the controller's global properties, note that need strong reference, otherwise the recovery is released out of the can not play.

2. Play or stop music

  Start playing
  [Self.player play];
   Stop playing
  [Self.player pause];

This is nothing to talk about, just call Avplayer's two instance methods

3, switch the current music resources are playing

Create the Avplayeritem avplayeritem that need to be played
 *item = [[Avplayeritem alloc] Initwithurl:[nsurl URLWithString:model.url]];
 Replace the current music resource 
 [Self.player Replacecurrentitemwithplayeritem:item];

This can be used for the song switch, such as the previous one, the next song.

4, through the KVO monitor the status of the player

 [Self.player.currentItem addobserver:self forkeypath:@ "status" Options:nskeyvalueobservingoptionnew Context:nil];

Get the player's CurrentItem, register the current object as the observer, and listen for its status attribute. The Status property is the Avplayeritemstatus type, which is an enumeration type, as follows:

typedef ns_enum (Nsinteger, avplayeritemstatus) {
  avplayeritemstatusunknown,//unknown state
  avplayeritemstatusreadytoplay,//ready to play
  avplayeritemstatusfailed//load Failure
};

When the Status property value changes, a callback for the observer method is triggered, as follows:

Observer callback
-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary< nskeyvaluechangekey,id> *) Change context: (void *) context
{
  //Note The Self.player.status attribute is viewed here
  if ([ KeyPath isequaltostring:@ "status") {
    switch (self.player.status) {case
      Avplayerstatusunknown:
      {
        NSLog (@ "Unknown state");
      }
        break;
      Case Avplayerstatusreadytoplay:
      {
        NSLog (@ "Ready to play");
      }
        break;
      Case avplayerstatusfailed:
      {
        NSLog (@ "load failed");
      }
        break;
         Default: Break;}}}

Whenself.player.status ==  AVPlayerStatusReadyToPlay, the music will start to play normally, the other two state music is unable to play, you can in the above method corresponding state to give a hint. What needs to be stressed here is that the observer listens to the object self.player.currentItemInstead of self.player, and when the listener's properties change, the Observer's callback method needs to see self.player.status。 Of course, you can not do this, but I tried several times, the consequences of not doing so can not be heard self.player.statusChanges to the property.

When the music is finished, or switch to the next song, be sure to remove the observer, or you will crash. The operation is as follows:

Removal of the observer
 [Self.player.currentItem removeobserver:self forkeypath:@ "status"];

5, listening to the music of the buffer progress

This is also the Loadedtimeranges property that listens to the music resource Avplayeritem the player is currently playing via KVO. We look at the monitor first, as follows:

KVO Listening for music buffering status
[Self.player.currentItem addobserver:self forkeypath:@ "loadedtimeranges" options: Nskeyvalueobservingoptionnew Context:nil];

When Loadedtimeranges property changes, the callback is as follows:

-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: ( nsdictionary<nskeyvaluechangekey,id> *) Change context: (void *) Context {if ([KeyPath isequaltostring:@)
    Loadedtimeranges "]) {Nsarray * timeranges = self.player.currentItem.loadedTimeRanges;
    The buffer time range cmtimerange Timerange = [Timeranges.firstobject cmtimerangevalue];
    Total buffer length Nstimeinterval totalloadtime = Cmtimegetseconds (timerange.start) + cmtimegetseconds (timerange.duration);
    The total time of the music nstimeinterval duration = Cmtimegetseconds (self.player.currentItem.duration);
    Calculates the buffer percentage example nstimeinterval scale = totalloadtime/duration;
  Update buffer progress bar self.loadTimeProgress.progress = scale; }

}

Loadedtimeranges This property is an array, which contains the time range of this buffer, which is expressed in a structure CMTimeRange , of course, in OC, the structure can not be directly stored in the array, so it is packaged as an OC object NSValue .

Let's take a look at this structure:

typedef struct
{
  cmtime      start;    
  Cmtime      duration;  
} Cmtimerange;

Start represents the starting point of this buffer time, Duratin represents the duration of this buffer, detailed calculation method can see the implementation of the above method.

When the music is finished, or switch to the next song, be sure to remove the observer, or you will crash. The operation is as follows:

[Self.player.currentItem addobserver:self forkeypath:@ "Loadedtimeranges" options:nskeyvalueobservingoptionnew Context:nil];

6, monitor the progress of music playback

This is not through KVO, Avplayer specifically provides the following API to monitor playback progress:

/**
 listens for music playback progress

 @param interval listening interval, used to set how long the callback
 @param queue  , General pass main queue
 @param  block The block of the callback will pass the current playback time

 @return The object being monitored
 /
-(ID) Addperiodictimeobserverforinterval: (cmtime) interval Queue: (nullable dispatch_queue_t) queue usingblock: (void (^) (cmtime time) block;

The operation is as follows:

 __weak typeof (self) weakself = self;
  Self.timeobserver = [Self.player addperiodictimeobserverforinterval:cmtimemake (1.0, 1.0) Queue:dispatch_get_main_ Queue () usingblock:^ (cmtime time) {
    //the current playback times
    float = cmtimegetseconds.
    Total time
    float = cmtimegetseconds (item.duration);
    if (current) {
      float progress = current/total;
      Update playback progress bar
      weakSelf.playSlider.value = progress;
      WeakSelf.currentTime.text = [Weakself timeformatted:current];
    }
  ];

We can get the current playback time in this block, calculate the current playback time proportion based on the total time, and update the playback progress bar last. This involves a data class type Cmtime, which is also a struct, used as a format for time, defined as follows:

  typedef struct
   cmtimevalue  value;    
   Cmtimescale  Timescale;  
   Cmtimeflags  flags;    
   Cmtimeepoch  epoch;    
  } Cmtime;

Cmtime is a fraction of the form of time, value represents the numerator, timescale represents the denominator, flags are bitmask, indicating the state of time specified. So we need the number of seconds to get the numerator divided by the denominator. Of course you can also use the following function to get the number of seconds in time:

Float64 Cmtimegetseconds (cmtime time)

Finally, when the music is played or the music is switched, the listener still needs to be removed:

if (self.timeobserver) {
    [Self.player removeTimeObserver:self.timeObserver];
    Self.timeobserver = nil;
  }

7, manual control (move slider) playback progress

This is a very common function of playing audio and video, so powerful avplayer of course provide a few APIs, the following is only one of the simplest:

/**
 The playback time

 specified @param time
 *
/(void) Seektotime: (Cmtime) times;
Use the following:

//Move slider to adjust playback progress
-(Ibaction) Playslidervaluechange: (UISlider *) sender
{
  //time
  calculated based on value Float time = Sender.value * Cmtimegetseconds (self.player.currentItem.duration);
  Jumps to the current specified time
  [Self.player Seektotime:cmtimemake (Times, 1)];
}

8, listening music playback complete

General audio and video playback completed when we have more or less to deal with some business, such as loop playback, finished the exit interface and so on. Here's how to listen for Avplayer playback complete.

Add playback completion notification to Avplayeritem
  [[nsnotificationcenter defaultcenter] addobserver:self selector: @selector ( playfinished:) name:avplayeritemdidplaytoendtimenotification Object:_player.currentitem];

Here is the use of registered monitoring avplayeritemdidplaytoendtimenotification notice, when avplayer a play completed, it will issue this notice, we received a notification after processing can be

9, set music background playback

We know that a program running on the iOS system will be dormant when it goes backstage, the program stops running, and there's no music to play. But there are some specific features of the app is still in the background to run, such as the music type of the app is in this category. However, it is not that you play music in your application and you can sit back and relax, you still need to do the following steps:

(1) Open the background mode

Target->capabilities-> Background modes-> Open switch-> tick the first option

(2) Set up audio session when the program starts

  General in method: Application:didfinishlaunchingwithoptions: Set
  //Get audio session
  avaudiosession *session = [avaudiosession Sharedinstance];
  The settings type is playback.
  [Session Setcategory:avaudiosessioncategoryplayback Error:nil];
  Activates an audio session.
  [Session Setactive:yes Error:nil];

The above two steps are correct, the program enters the background mode, can play music

10, how to set the music lock frequency information

We see Baidu Music lock frequency, also can still display songs on the screen information, as well as switch songs. Let's look at how this function is implemented:

Music lock screen information display-(void) Setuplockscreeninfo {//1. Get lock Screen Center mpnowplayinginfocenter *playinginfocenter = [Mpnowplayinginfocen

  Ter Defaultcenter];
  Initializes a dictionary that holds music information nsmutabledictionary *playinginfodict = [Nsmutabledictionary dictionary]; 2, set the song name if (self.currentModel.name) {[Playinginfodict setObject:self.currentModel.name Forkey:mpmediaitempropert
  Yalbumtitle]; //Set singer name if (self.currentModel.artist) {[Playinginfodict setObject:self.currentModel.artist forkey:mpmediaitemp
  Ropertyartist];
  }//3 set cover picture uiimage *image = [self GetMusicImageWithMusicId:self.currentModel];
    if (image) {mpmediaitemartwork *artwork = [[Mpmediaitemartwork alloc] initwithimage:image];
  [Playinginfodict setobject:artwork forkey:mpmediaitempropertyartwork]; }//4 Set the total length of the song [Playinginfodict setObject:self.currentModel.detailDuration Forkey:

  Mpmediaitempropertyplaybackduration];

  Music information assignment to obtain the Nowplayinginfo attribute of the lock screen center playinginfocenter.nowplayinginfo = playinginfodict; //5. Open remote interaction, only open this can be remote control [[UIApplication sharedapplication] beginreceivingremotecontrolevents];

 }

Here to set the picture need to pay attention to, the asynchronous load network picture and then set is not valid, so the picture information is best to first request down before setting.

Remote-controlled callbacks are as follows:

Listening for remote interaction method
-(void) Remotecontrolreceivedwithevent: (Uievent *) event
{

  switch (event.subtype) {
    //Play Case
    uieventsubtyperemotecontrolplay:{
      [Self.player play];
          }
      break;
    Stop case
    uieventsubtyperemotecontrolpause:{
      [self.player pause];
          }
      break;
    Next Case
    uieventsubtyperemotecontrolnexttrack:
      [self nextbtnaction:nil];
      break;
    Previous case
    uieventsubtyperemotecontrolprevioustrack:
      [self lastbtnaction:nil];
      break;

    Default: Break
      ;
  }
}

Third, summary

Finally, draw a picture summarizing the process of playing remote network music:

According to the interface of the QQ music to do a small demo, the following is the demo of the real machine front and background playback of the operation effect:

Iv. concluding remarks

Play the remote network Music core technology has been basically finished, of course, Avplayer still have a lot of powerful features did not write out, interested can be further excavation. Wrote here has been extremely tired, the follow-up will continue to update some wonderful technical points, but also hope that we support the cloud habitat community.

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.