Hi,
I have a problem with this web radio audio streaming app.
On my devices, and on all beta tester devices, the app works and you can hear the audio.
Unfortunately at the time of review team approval I get rejected because they say that when I press ‘Listen Live’ no sound can be heard. I also thought it was a geographic blocking problem, but they can hear the audio directly from the link.
I have no errors and have never been able to replicate the problem. I have done tests on old and new iPhones and iPads.
Has anyone had a similar problem before? How can I solve it?
I attach the code I created to hear the audio stream.
Thank you very much
Roberto
I have a problem with this web radio audio streaming app.
On my devices, and on all beta tester devices, the app works and you can hear the audio.
Unfortunately at the time of review team approval I get rejected because they say that when I press ‘Listen Live’ no sound can be heard. I also thought it was a geographic blocking problem, but they can hear the audio directly from the link.
I have no errors and have never been able to replicate the problem. I have done tests on old and new iPhones and iPads.
Has anyone had a similar problem before? How can I solve it?
I attach the code I created to hear the audio stream.
Thank you very much
Roberto
B4X:
#Region Project Attributes
#ApplicationLabel: Radio Arenzano
#Version: 1.0.9
#iPhoneOrientations: Portrait
#iPadOrientations: Portrait
#Target: iPhone, iPad
#ATSEnabled: True
'#MinVersion: 16
#End Region
#PlistExtra: <key>NSAppTransportSecurity</key><dict><key>NSAllowsArbitraryLoads</key><true/>
#PlistExtra: <key>NSAllowsArbitraryLoadsInWebContent</key><true/>
#PlistExtra: </dict>
#PlistExtra: <key>UIBackgroundModes</key><array><string>audio</string></array>
Sub Process_Globals
'Queste variabili globali saranno dichiarate una sola volta all'avvio dell'app.
'Possono essere accessibili da tutti i moduli.
Private nowPlay As String
Private converImage As String
Private checkSong As Timer
Public webStreamUrl As WebView
Public App As Application
Public NavControl As NavigationController
Private Page1 As Page
Private xui As XUI
Private Button1 As Button
Private lbPlayer As Label
Private imgCover As ImageView
Private lbVer As Label
Private NativeMe As NativeObject
'Private AVQueuePlayer As NativeObject
'Private PlayerUrl As NativeObject
Dim playerStream As NativeObject
Dim urlStream As NativeObject
Private pnlStreaming As Panel
Private menuMain As spinnerMenu
Private header As Panel
Private imgLogo As ImageView
Private pnlSfondo As ImageView
Private WebView1 As WebView
' Nuova variabile per gestire Now Playing Info
Private nowPlayingInfo As NativeObject
Private lbErr As Label
End Sub
Sub Application_Start (Nav As NavigationController)
NativeMe = Me
NavControl = Nav
Page1.Initialize("Page1")
Page1.RootPanel.LoadLayout("Page1")
NavControl.ShowPage(Page1)
NavControl.SetNavigationBarVisibleAnimated(False)
NativeMe.RunMethod("setAudioSession", Null)
NativeMe.RunMethod("register", Null)
' Uso HTTPS invece di HTTP per lo streaming
'AVQueuePlayer = CreateQueuePlayer(Array("https://nrf1.newradio.it:9556/stream"))
'PlayerUrl = CreatePlayerItem("https://nrf1.newradio.it:9556/stream")
Button1.Text = "ASCOLTA LA DIRETTA! ▶️"
Button1.Tag = "PLAY"
checkSong.Initialize("checkSong", 3000)
checkSong.Enabled = True ' controllo sempre la canzone in onda
lbVer.Text = "POWERED BY LibertyLine s.r.l."
lbVer.top = GetDeviceLayoutValues.Height - lbVer.Height - header.Height - 30dip
' Inizializza Now Playing Info
'InitializeNowPlayingInfo
End Sub
Sub Page1_Resize(Width As Int, Height As Int)
' Gestire il ridimensionamento della pagina
End Sub
Sub checkSong_Tick
sync_getSing
End Sub
Sub Button1_Click
If (Button1.tag = "PLAY") Then
lbErr.visible = False
Try
urlStream = urlStream.Initialize("NSURL").RunMethod("URLWithString:", Array("https://nrf1.newradio.it:9556/stream"))
Dim avPlayerItem As NativeObject
avPlayerItem = avPlayerItem.Initialize("AVPlayerItem").RunMethod("playerItemWithURL:", Array(urlStream))
playerStream = playerStream.Initialize("AVPlayer").RunMethod("alloc", Null).RunMethod("initWithPlayerItem:", Array(avPlayerItem))
playerStream.RunMethod("play", Null)
Button1.Text = "METTI IN PAUSA ⏸"
Button1.Tag = "PAUSE"
Catch
showError("Button1_Click", LastException)
End Try
sync_getSing
Else
playerStream.RunMethod("pause", Null)
Button1.Text = "ASCOLTA LA DIRETTA! ▶️"
Button1.Tag = "PLAY"
End If
End Sub
Sub sync_getSing
Dim Job As HttpJob
Job.Initialize("getSing", Me)
Job.Download("https://nrf1.newradio.it/AudioPlayer/9556/playerInfo")
End Sub
Sub sync_getCover
Log("sync_getCover")
Dim Job As HttpJob
Job.Initialize("getCover", Me)
Job.Download("https://nrf1.newradio.it/AudioPlayer/9556/albumCover")
End Sub
Sub JobDone(Job As HttpJob)
If Job.Success Then
Dim js As JSONParser
Select Job.JobName
Case "getSing"
js.Initialize(Job.GetString)
Dim m As Map
m = js.NextObject
lbPlayer.Text = m.Get("nowplaying")
Log("getSing: " & nowPlay & " " & m.Get("nowplaying"))
If nowPlay <> m.Get("nowplaying") Then
nowPlay = m.Get("nowplaying")
sync_getCover
End If
Case "getCover"
Log("getCover")
js.Initialize(Job.GetString)
Dim m As Map
m = js.NextObject
' If converImage <> m.Get("coverImage") Then
Log("CAMBIO COVER")
converImage = m.Get("coverImage")
If converImage.EndsWith("100x100bb.jpg") Then
Dim size As Long = "400" ' pnlSfondo.Width
converImage = converImage.Replace("100x100bb.jpg", size & "x" & size & "bb.jpg")
End If
sync_downloadCover(converImage)
'End If
Case "downloadCover"
imgCover.Bitmap = Job.GetBitmap
pnlSfondo.Bitmap = imgCover.Bitmap
' Aggiorna Now Playing Info con l'artwork
Dim parts() As String = Regex.Split("-", nowPlay)
'
Try
Dim Out As OutputStream
Out = File.OpenOutput(File.DirTemp, "sing.jpg", False)
Out.Close
Log("Image saved successfully.")
Catch
Log("Error saving image: " & LastException.Message)
End Try
End Select
Else
Msgbox(Job.ErrorMessage, "Error")
End If
Job.Release
End Sub
Sub sync_downloadCover(url As String)
Dim Job As HttpJob
Job.Initialize("downloadCover", Me)
Job.Download(url)
End Sub
Private Sub imgMenu_Click
showMenu
End Sub
Sub showMenu()
menuMain.Initialize(Page1, Me, "123", "spMenuMain", Colors.RGB(0,0,0))
menuMain.SetTitle(Colors.RGB(0,0,0), Colors.White, 1)
menuMain.altezzaMenuItem = 60dip
menuMain.AddItem("diretta.png", "Segui la diretta!", Colors.RGB(255, 255, 255), Colors.Black, "diretta", "")
menuMain.AddItem("web.png", "Sito web", Colors.RGB(255, 255, 255), Colors.Black, "sito", "")
menuMain.AddItem("programmazione.png", "Programmazione", Colors.RGB(255, 255, 255), Colors.Black, "programmazione", "")
menuMain.AddItem("facebook.png", "Facebook", Colors.RGB(255, 255, 255), Colors.Black, "facebook", "")
menuMain.AddItem("whatsapp.png", "Whatsapp", Colors.RGB(255, 255, 255), Colors.Black, "whatsapp", "")
menuMain.OpenMenu(0, 1dip, getWidth(80), 0)
End Sub
Sub spMenuMain_Click(SelectedItem As Object, text As String)
WebView1.Top = header.Height
WebView1.Left = 0
WebView1.Width = 100%x
WebView1.Height = 100%y - header.Height
Dim op As String = SelectedItem
If op.Contains("diretta") Then
pnlStreaming.Visible = True
WebView1.Visible= False
End If
If op.Contains("sito") Then
pnlStreaming.Visible = False
WebView1.Visible= True
WebView1.Top = header.Height - 60dip '-5dip
WebView1.Height = 100%y - header.Height + 60dip
WebView1.LoadUrl("https://www.radioarenzano.net")
'WebView1.LoadUrl("https://nrf1.newradio.it:9556/stream")
End If
If op.Contains("programmazione") Then
pnlStreaming.Visible = False
WebView1.Visible= True
WebView1.LoadUrl("https://www.radioarenzano.net/la-radio/programmazione/")
WebView1.Top = header.Height - 60dip '-5dip
WebView1.Height = 100%y - header.Height + 60dip
End If
If op.Contains("facebook") Then
Dim WA_URI As String = "https://www.facebook.com/radioarenzano"
Dim NativeMe As NativeObject = Me
NativeMe.RunMethod("openScheme:", Array(WA_URI))
End If
If op.Contains("whatsapp") Then
Dim WA_URI As String = "https://api.whatsapp.com/send/?phone=393123456789"
Dim NativeMe As NativeObject = Me
NativeMe.RunMethod("openScheme:", Array(WA_URI))
End If
End Sub
Public Sub getWidth(perc As Double) As Double
Return GetDeviceLayoutValues.Width * (perc / 100)
End Sub
Sub showError(title As String, err As String)
lbErr.Visible = True
Log(title & CRLF & err)
lbErr.Text = title & CRLF & err
End Sub
#If OBJC
@import MediaPlayer;
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
- (void)setAudioSession {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
// Configurazione per audio in background
BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback
error:&err];
if (success) {
success = [audioSession setActive:YES error:&err];
success = [audioSession setPreferredSampleRate:44100 error:nil]; // Usa una frequenza di campionamento standard
// Registrazione per le notifiche di interruzione
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleInterruption:)
name:AVAudioSessionInterruptionNotification
object:audioSession];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
if (!success) {
[NSException raise:@"" format:@"Error setting audio session: %@", err];
}
}
- (void)register {
MPRemoteCommandCenter* center = [MPRemoteCommandCenter sharedCommandCenter];
// Abilita tutti i comandi necessari
center.playCommand.enabled = YES;
center.pauseCommand.enabled = YES;
center.togglePlayPauseCommand.enabled = YES;
// Aggiungi i target per i comandi
[center.playCommand addTarget:self action:@selector(play)];
[center.pauseCommand addTarget:self action:@selector(pause)];
[center.togglePlayPauseCommand addTarget:self action:@selector(togglePlayPause)];
}
- (void)handleInterruption:(NSNotification *)notification {
NSDictionary *info = notification.userInfo;
AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
[self.bi raiseEvent:nil event:@"audiointerruption:" params:@[@(type)]];
}
- (MPRemoteCommandHandlerStatus)play {
[self.bi raiseEvent:nil event:@"controlevent:" params:@[@"play"]];
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)pause {
[self.bi raiseEvent:nil event:@"controlevent:" params:@[@"pause"]];
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)togglePlayPause {
[self.bi raiseEvent:nil event:@"controlevent:" params:@[@"togglePlayPause"]];
return MPRemoteCommandHandlerStatusSuccess;
}
#end if