How to Add Audio to Your Angular 18 Project for iOS and Android

In this tutorial, I will guide you through creating an Angular 18 project with audio functionality that works on both iOS and Android browsers. As you may know, modern browsers have strict privacy policies that prevent audio from playing automatically without user interaction. However, using the audio HTML5 tag, we can work around this limitation. This method is not a hack, but rather a legitimate use of the audio element.

Setting Up the Project

To get started, create a new Angular 18 project by typing the following command in your terminal:

ng new angular-audio

Once the project is set up, let's dive into making sure the audio works across iOS and Android browsers. The goal is to ensure that the user can play sounds on your website after interacting with it, as many browsers restrict autoplay.

Step 1: Add the Audio Element

Now, locate the app.component.html file in your Angular project and paste the following code:

<audio #audioPlayer controls>
  <source [src]="audioSource" type="audio/mpeg">
  Your browser does not support the audio element.
</audio>

This creates an audio element in the DOM that allows users to interact with it. The downside is that this media element is visible, but we can hide it with some CSS styling.

Step 2: Hiding the Audio Element

To hide the audio element, we can use the following CSS:

audio {
  position: absolute;
  left: -1000px;
  opacity: 0;
}

This CSS will ensure the audio player is not visible but still functional. If the audio element is inside a relative block, use position: fixed instead of absolute to avoid creating blank spaces on the page.

Step 3: Script the Audio Element to Play Sounds

Next, open the app.component.ts file and add the following code to select the audio element and store an array of sounds. This will allow you to trigger sound effects based on user interaction, like clicking a button:

@ViewChild('audioPlayer') audioPlayer!: ElementRef;
audioSource: string = "";
audioObjects: { [key: string]: string } = {};

Step 4: Initialize the Audio Objects

We will initialize the sounds in the ngOnInit() lifecycle hook. Here’s how to do it:

ngOnInit(): void {
    this.initializeAudio();
}

initializeAudio(): void {
    this.audioObjects['silent'] = '/assets/audio/silent.ogg';
    this.audioObjects['honk'] = '/assets/audio/honk.ogg';
    this.audioObjects['bell'] = '/assets/audio/bell.ogg';
    this.audioObjects['whistle'] = '/assets/audio/whistle.ogg';
    this.playSound('silent');
}

This code initializes the sound files and sets the default sound to silent.ogg from the assets/audio/ directory.

Step 5: Creating the Play Sound Method

Now, let’s implement the playSound method to change the audio source and play the sound. Here’s the code:

playSound(soundKey: string): void {
    this.audioSource = this.audioObjects[soundKey];

    if (this.audioPlayer && this.audioPlayer.nativeElement) {
      const audioElement = this.audioPlayer.nativeElement;

      audioElement.src = ''; // Temporarily set to empty
      audioElement.src = this.audioSource; // Set the new source

      audioElement.play().catch((error) => {
        console.error('Error playing sound:', error);
      });
    } else {
      console.error('Audio player is not available');
    }
}

This method checks if the audio player is available, changes the source, and plays the selected sound. If there’s an issue with the player, it logs an error.

Step 6: Allowing User Interaction

Finally, let’s create a dummy button that will allow the user to interact with the interface and trigger the sound. This is necessary to comply with browser autoplay policies. Here’s the full TypeScript code for your app.component.ts file:

import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  @ViewChild('audioPlayer') audioPlayer!: ElementRef;
  title = 'audio-tutorial';
  audioSource: string = "";
  audioObjects: { [key: string]: string } = {};

  ngOnInit(): void {
    this.initializeAudio();
  }

  initializeAudio(): void {
    this.audioObjects['silent'] = '/assets/audio/silent.ogg';
    this.audioObjects['honk'] = '/assets/audio/honk.ogg';
    this.audioObjects['bell'] = '/assets/audio/bell.ogg';
    this.audioObjects['whistle'] = '/assets/audio/whistle.ogg';
    this.playSound('silent');
  }

  playSound(soundKey: string): void {
    this.audioSource = this.audioObjects[soundKey];

    if (this.audioPlayer && this.audioPlayer.nativeElement) {
      const audioElement = this.audioPlayer.nativeElement;

      audioElement.src = ''; 
      audioElement.src = this.audioSource; 

      audioElement.play().catch((error) => {
        console.error('Error playing sound:', error);
      });
    } else {
      console.error('Audio player is not available');
    }
  }

  dummyMethod(): void{
    // Add logic to trigger sounds
  }
}

Conclusion

With this approach, you can now play different sounds based on user interaction, and the audio will work across iOS and Android browsers. If you found this tutorial helpful, be sure to check out the demo here!

Thank you for reading, and feel free to leave a comment if you have any questions. Don't forget to share this article with others who might find it useful!


Last updated

Comments

Leave a Comment