Greetings. I’m trying to build a simple radio streaming android application using capacitor.js, ionic-vue, and howler.js. This is just a practice project as I’m new to the above-mentioned libraries. I followed the howler.js streaming radio docs and managed to get the application to work to my satisfaction (on the browser). The problem however arises when I generate an android apk and try to run the app on a native android device or android emulator. The radio stream just doesn’t play, it loads forever. It works perfectly fine when running it on the browser using ionic serve.
I’ve tried to search for a solution but to no avail. I gathered Howler.js has this html5: true option that essentially makes use of html5 audio that allows you to stream large audio files so I wonder if that has something to do with it but I set the value to true and it works fine on the browser but it still doesn’t work when I build the app into an android apk. The app UI renders just fine, when I click the play button to stream radio, it just loads indefinitely and never starts playing.
or maybe android requires certain permissions to play audio? Please assist.
Stream Function
import { ref } from 'vue';
import {Howl} from 'howler';
let sound
const currentTrack = ref(null)
const isLoading = ref(false)
const isPlaying = ref(false)
const stations = ref([
{id : 0, title: "Gabz FM", image : "gabzfm.png", stream: "https://onlineradiobox.com/json/bw/gabz/play?platform=web", description: "Power to Engage your World The most preferred contemporary adult radio station in Botswana", playing: false, loaded:false},
{id : 1, title: "Yarona FM", image : "yaronafm.png", stream: "https://onlineradiobox.com/json/bw/yarona/play?platform=web", description: "Yarona FM is a national broadcaster based in Gaborone, Botswana. The Station’s core audience comprises of young, upwardly mobile youth within the 20-29 age bracket with spillage on either side of this age group.", playing: false, loaded:false},
{id : 2, title: "Duma FM", image : "dumafm.png", stream: "http://s3.voscast.com:10076/;", description: "Duma FM is a family radio station whose primary objective is to INFORM, EDUCATE AND EDUCATE! This allows us to bring together people from all walks of life through conversation and music.", playing: false, loaded:false}
])
const streamStation = (id) => {
isLoading.value = true
stations.value.forEach(station => {
station.playing = false
station.loaded = false
});
sound = new Howl({
src: [stations.value[id].stream],
html5: true,
onload: function() {
isLoading.value = false
stations.value[id].loaded = true
console.log('Loaded Track');
isPlaying.value = true
},
onplay: function() {
stations.value[id].playing = true
currentTrack.value = stations.value[id]
},
onpause: function() {
console.log('')
},
onend: function(){
isPlaying.value = false
}
});
sound.play();
}
const pauseStream = (id) =>{
stations.value[id].playing = false
//isPlaying.value = false
sound.pause()
}
const togglePlay = (id) =>{
if(stations.value[id].playing){
pauseStream(id)
}else{
if(sound == null){
console.log('hit block 1')
streamStation(id)
}else{
console.log('hit block 2 which means i am not null')
if(stations.value[id].loaded){
console.log('hit block 2A')
sound.play()
}else{
console.log('opening new stream')
sound.unload()
streamStation(id)
}
}
}
}
const streamRadio = () => {
return {stations, isLoading, isPlaying, streamStation, togglePlay, currentTrack}
}
export default streamRadio
Ionic-Vue Component
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Radio Test App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content >
<ion-slides>
<ion-slide v-for="station in stations" :key="station.id">
<ion-card class="card-main" style="border-radius:20px;padding-bottom:30px;height:20%">
<ion-card-content>
<ion-card class="radio-logo-bg" style="border-radius:20px">
<ion-card-content>
<img style="max-width:250px" :src="`/assets/stations/`+station.image"/>
</ion-card-content>
</ion-card>
<h2>{{station.title}}</h2>
<p><b style="color:black">{{station.description}}</b></p>
<br><br>
<ion-button class="radio-btn" @click="togglePlay(station.id)" :disabled="(isLoading)? true : false " style="display:block;width:30%;margin:auto">
<ion-spinner v-if="isLoading" name="bubbles"></ion-spinner>
<ion-icon v-if="station.playing" src="/assets/icon/pause.svg"></ion-icon>
<ion-icon v-else src="/assets/icon/play.svg"></ion-icon>
</ion-button>
<ion-img v-if="station.playing" src="/assets/wave2.gif"></ion-img>
</ion-card-content>
</ion-card>
</ion-slide>
</ion-slides>
</ion-content>
</ion-page>
</template>