Dieses Tutorial zeigt, wie man einen simplen AudioPlayer für eine native iPhone App baut. Der Player wird über ein einfach aufgebautes Interface eine mp3 Datei abspielen. Das Interface besteht aus einem Play- und Pause-Button, einem Slider mit einer Positionierfunktion und eine Darstellung der Gesamtdauer und der abgespielten Zeit. Der Quellcode wurde mit Xcode 5 verfasst. Vorige Xcode Versionen werden nicht in der Lage sein von diesem Projekt einen Build zu erstellen oder es auszuführen. Ich werde nicht zu sehr ins Detail gehen, wenn es um einfache Schritte geht, wie etwa ein Projekt anlegen oder Dateien zum Projekt hinzuzufügen. Dieses Wissen wird für dieses Tutorial vorausgesetzt.

Der gesamte Projekt Source Code kann hier bei GitHub heruntergeladen werden. Am Ende wird der AudioPlayer so aussehen, wie im nächsten Bild zu sehen.

Let’s start coding

Zuerst sollte in Xcode eine “Single View Application” in einem neuen Projekt erstellt werden. Danach können die “Supporting Files”, eine mp3 Audio Datei und Bilder, die den Play- und den Pause-Button, beinhalten zum Projekt hinzugefügt werden. Nachdem das Projekt aufgesetzt wurde, ist nun der erste Schritt, die einzelnen Player Elemente in der Storyboard Datei zu erstellen. Alles was man dafür benötigt, ist ein Button mit einem Play-Button Bild, einen Slider und zwei leere Text-Label. Danach sollte das Storyboard so aussehen:

Die AudioPlayer Klasse

Im nächsten Schritt geht es darum, eine AudioPlayer Klasse zu erstellen. Diese kann z.B. in einem Ordner mit dem Namen “AudioPlayer” gruppiert werden. Die Header Datei YMCAudioPlayer.h sollte so wie in der folgenden Abbildung dargestellt aussehen:

Die Property “audioPlayer” ist vom Typ AVAudioPlayer, einer im AVFoundation Framework enthaltenen Klasse. Um den AudioPlayer nun zu steuern benötigt man mehrere öffentliche Klassen. Ich denke die init, play und pause Methoden bedürfen keiner weiteren Erklärung. setCurrentAudioTimedient dazu, die Position zu setzen, bei welcher Zeit die Audiodatei abgespielt werden soll. getAudioDuration gibt die Länge des Audio Tracks als float wieder. Dieser Wert kann mit der Methode timeFormat in ein lesbares Zeitformat konvertiert werden. getCurrentAudioTime gibt die aktuelle Position zurück, an der die Audiodatei gerade abgespielt wird.

Die Implementierungsdatei YMCAudioPlayer.m soll folgendermaßen aussehen:

Die init Methode dient dazu, die interne “audioPlayer” Property mit der AVAudioPlayer zu initialisieren. Als Parameter wird der Dateinamen benötigt:

Danach kann [self.audioPlayer play]; bereits direkt aufgerufen werden um die Audiodatei abzuspielen. Ich habe lediglich einzelne Methoden um die Aufrufe gepackt, um zum Einen die Aufrufe konsistent zu halten und zum Anderen nicht die Möglichkeit zu verbauen, weiteren Code hinzuzufügen. Z.B. wenn Pause gedrückt wird könnte die aktuelle Player Position über NSUserDefaults gespeichert werden, damit beim wiederholten Öffnen der App die letzte Position ausgelesen und angezeigt werden kann.

Die Methode timeFormat gibt einen formatierten String zurück, um aus dem float Wert mittels runden und dividieren einen lesbaren Zeitwert zu machen: 01:38.

Die ViewController Klasse

Der nächste Schritt ist, die automatisch generierten ViewController Klassen zu editieren. Die Header Datei ViewController.h sollte so aussehen:

Die zuvor erstellte YMCAudioPlayer Klasse kann hier nun importiert werden. Die “audioPlayer” Property wird wieder gecasted, dieses mal auf den Typ der Klasse YMCAudioPlayer. Die IBOutlet Properties werden nun mit den zuvor erstellten Storyboard Elementen verknüpft. Im Assistant Editor View wird dazu einfach die jeweilige Property auf das zugehörige Storyboard Element gezogen.

Die Implementierungsdatei ViewController.m sollte wie folgt aussehen:

In diesem View, können die Methoden der YMCAudioPlayer Klasse aufgerufen, verarbeitet und den View Elementen zugewiesen werden. In der automatisch aufgerufenen Methode viewDidLoad  wird die interne “audioPlayer” Property als YMCAudioPlayerinitialisiert.

Danach kann die setupAudioPlayer Methode aufgerufen werden. Diese Methode füllt die Text-Labels, wie z.B. die “timeElapsed” Property:

Oder die “duration” Property, indem die timeFormat Methode verwendet wird, um den Rückgabewert der zuvor erstelltengetAudioDuration Methode zu formatieren:

Die folgende playAudioPressed Methode wird als IBAction mit dem playButton verknüpft:

Diese Methode prüft die “isPaused” Property um die Darstellung der Bilder abhängig vom aktuellen Status auf dem Button zu verarbeiten (spielt gerade oder pausiert). Zusätzlich wird eine Timer-Funktion aufgerufen um die Text-Labels jede Sekunde mit dem neu formatierten String zu befüllen. Hier wird ebenfalls der Wert des Slider Elements geupdated.

Die “scrubbing” Property dient zur Erkennung, ob der Benutzer gerade den Slider verschiebt. Wenn ja, dann soll der Slider nicht jede Sekunde automatisch geupdated werden. Wäre das der Fall, würde die Slider Position bei der Darstellung flackern, da jede Sekunde die Position und gleichzeitig der aktuelle Drag-Wert des Benutzers den Slider updaten würden.

Die Methode setCurrentTime ist als weiteres IBAction Element wie erwähnt genau dazu da, um die aktuelle Position des Sliders zu bestimmen. Auch die userIsScrubbing Methode ist mit diesem UISlider Element verknüpft. Es wird das Touch drag Inside Event genutzt, um zu prüfen, ob der Benutzer den Slider gerade verschiebt:

Nachdem alle Methoden mit den Elementen im Storyboard verknüpft sind, steht alles bereit um einen Build zu erstellen und unsere AudioPlayer App auszuführen.

Der gesamte Projekt Source Code kann bei GitHub heruntergeladen werden.
Ich freue mich immer über Kommentare oder Vorschläge für neue Artikel.

Audiofile “Something Elated” taken from freemusicarchive.org, Copyright

(This blog post is also available in English)

5 Kommentare

  1. Danke für anregende Anleitung. Mich interessiert, an welcher Stelle ich ansetzen muss, um das Projekt zu skalieren.

    mfg

    s

    Antworten
  2. Vielen dank für den tollen Antwort, ich habe den code in ViewController.m wie unten rein kopiert, aber bekam eine Fehler Meldung.
    Wie gesagt ich bin noch in der Anfangsfase. Dein Audioplayer ist wirklich Fantastisch. Deswegen will ich das der Player über http mp3 dateien wiedergibt. In deinem Link (stackoverflow) habe ich auch geschaut aber da ich noch am Anfang bin ist es wie ein Labyrinth.
    ————-
    – (void)viewDidLoad
    {
    AVPlayer *player = [[AVPlayer playerWithURL:[NSURL URLWithString:@“http://www.mp3.com/mp3file.mp3″]] retain];
    [player play];

    }
    ————-

    Fehlermeldung:
    ARC forbids explicit message send of ‚retain‘

    Ich wäre unheimlich Glücklich wenn du mir helfen könntest.
    Am Besten ist Natürlich wenn es in dem AudioPlayer oben auch eingebunden wäre

    Antworten
    • Thomas Zinnbauer

      Hi Erdem,
      leider kan ich dir nicht weiterhelfen. Der Audioplayer ist ein Template, dass man als Arbeitsgrundlage nutzen und erweitern kann.
      Den retain Fehler kann man beseitigen, indem man es einfach weglässt, z.B. so
      [AVPlayer playerWithURL:[NSURL URLWithString:@“http://www.mp3.com/mp3file.mp3″]

      Antworten
  3. Hallo,

    vielen dank für diesen super Blog Eintrag, ich finde es super die Beschreibung und auch das man es Downloaden kann. Ich versuche den xcode zu lernen und muss mich durch viele Millionen Beiträge in Google und Co. weiterzukommen.

    Ich habe eine Frage und zwar wie kann ich einen http link anstatt interne mp3 Datei einfügen? Der Audiofile soll am Besten ein m3u Datei sein worin die mp3 Dateien jederzeit geändert werden können.

     

    Ich freue mich schon auf den Antwort.

    Vielen dank

    Eraslan

    Antworten
    • Thomas Zinnbauer

      Hi Erdem,
      eine Datei von einem Server laden macht man ganz einfach mit NSUrl. Also so z.B

      AVPlayer *player = [[AVPlayer playerWithURL:[NSURL URLWithString:@“http://www.mp3.com/mp3file.mp3″]] retain];
      [player play];

      Es gibt meistens Jemand, der dasselbe Problem schon einmal hatte… auf http://stackoverflow.com findest du viele gute Antworten.

      Antworten

Einen Kommentar abschicken

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *