iOS Question Show Player Controllers when Screen is off

ilan

Expert
Licensed User
Longtime User

Erel

B4X founder
Staff member
Licensed User
Longtime User
The controls should be there:

i_view64_NnsQWaGi0o.png


Don't miss the plist extra line.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
thanks erel for your reply.

Don't miss the plist extra line.

do you mean this line erel:

B4X:
#PlistExtra: <key>UIBackgroundModes</key><array><string>audio</string></array>

yes, i have added it. After some research, I found out that the first song that was loaded shows the buttons but loading another song (or url) removes them.

this is my code:

B4X:
'Code module
#Region  Project Attributes
   #ApplicationLabel: B4i Example
   #Version: 1.0.0
   'Orientation possible values: Portrait, LandscapeLeft, LandscapeRight and PortraitUpsideDown
   #iPhoneOrientations: Portrait, LandscapeLeft, LandscapeRight
   #iPadOrientations: Portrait, LandscapeLeft, LandscapeRight, PortraitUpsideDown
   #Target: iPhone, iPad
   #MinVersion: 8
#End Region

#PlistExtra: <key>UIBackgroundModes</key><array><string>audio</string></array>
#CertificateFile: ios_development.cer
#ProvisionFile: iosdev.mobileprovision


Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private NativeMe As NativeObject
    Private VideoPlayer1 As VideoPlayer
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NativeMe = Me
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("1")
    NavControl.ShowPage(Page1)
    NativeMe.RunMethod("setAudioSession", Null)
    VideoPlayer1.LoadVideo(File.DirAssets,"CRO - Traum (Official Version).mp3") '.("https://stream-dc1.radioparadise.com/mp3-32")
    VideoPlayer1.Play
    NativeMe.RunMethod("register", Null)
End Sub

Public Sub ControlEvent (Command As String)
    Select Command
        Case "play"
            VideoPlayer1.Play
        Case "pause"
            VideoPlayer1.Pause
    End Select
End Sub

Sub Button1_Click
    NativeMe.RunMethod("setAudioSession", Null)
    VideoPlayer1.LoadVideoUrl("https://stream-dc1.radioparadise.com/mp3-32")
    VideoPlayer1.Play
    NativeMe.RunMethod("register", Null)
End Sub

#If OBJC
@import MediaPlayer;
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
- (void)setAudioSession {
  AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  NSError *err = nil;
  BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&err];
  if (success) {
     success = [audioSession setActive:YES error:&err];
   success = [audioSession setPreferredSampleRate:4096 error:nil];
   [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
  }
  if (!success)
  [NSException raise:@"" format:@"Error setting audio session: %@", err];
}
- (void)register {
   MPRemoteCommandCenter* center = [MPRemoteCommandCenter sharedCommandCenter];
   center.playCommand.enabled = true;
   center.pauseCommand.enabled = true;
   [center.playCommand addTarget:self action:@selector(play)];
   [center.pauseCommand addTarget:self action:@selector(pause)];
}
- (MPRemoteCommandHandlerStatus) play {
   NSLog(@"test");
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"play"]];
   return MPRemoteCommandHandlerStatusSuccess;

}
- (MPRemoteCommandHandlerStatus) pause {
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"pause"]];
   return MPRemoteCommandHandlerStatusSuccess;
}

#end if

first, i load a song from DirAssets folder. exit the app and turning off the screen shows the buttons. getting back to the app and clicking the button to load the URL removes the button. now no buttons are shown. now i understand why sometimes i saw buttons and sometimes not.
i also tried to load the URL without calling "setAudioSession" and "register" but same results.

loading song from DirDocuments gives the same results.

am i doing something wrong?

thank you
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The audio background modes end once playback completes. You will need to use AVQueuePlayer and set the list of songs to play:
B4X:
#PlistExtra: <key>UIBackgroundModes</key><array><string>audio</string></array>
Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private NativeMe As NativeObject
    Private AVQueuePlayer As NativeObject
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NativeMe = Me
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("1")
    NavControl.ShowPage(Page1)
    NativeMe.RunMethod("setAudioSession", Null)
   
    NativeMe.RunMethod("register", Null)
    AVQueuePlayer = CreateQueuePlayer(Array("https://html5demos.com/assets/dizzy.mp4", "https://stream-dc1.radioparadise.com/mp3-32"))
    AVQueuePlayer.RunMethod("play", Null)
End Sub


Private Sub CreateQueuePlayer (Urls As List) As NativeObject
    Dim items As List
    items.Initialize
    For Each url As String In Urls
        items.Add(CreatePlayerItem(url))
    Next
    Dim no As NativeObject
    Return no.Initialize("AVQueuePlayer").RunMethod("queuePlayerWithItems:", Array(items))
End Sub

Public Sub ControlEvent (Command As String)
    Select Command
        Case "play"
            AVQueuePlayer.RunMethod("play", Null)
        Case "pause"
            AVQueuePlayer.RunMethod("pause", Null)
    End Select
End Sub

Private Sub CreatePlayerItem(Url As String) As NativeObject
    Dim u As NativeObject
    u = u.Initialize("NSURL").RunMethod("URLWithString:", Array(Url))
    Dim playerItem As NativeObject
    Return playerItem.Initialize("AVPlayerItem").RunMethod("playerItemWithURL:", Array(u))
End Sub

#If OBJC
@import MediaPlayer;
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
- (void)setAudioSession {
  AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  NSError *err = nil;
  BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&err];
  if (success) {
     success = [audioSession setActive:YES error:&err];
   success = [audioSession setPreferredSampleRate:4096 error:nil];
   [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
  }
  if (!success)
  [NSException raise:@"" format:@"Error setting audio session: %@", err];
}
- (void)register {
   MPRemoteCommandCenter* center = [MPRemoteCommandCenter sharedCommandCenter];
   center.playCommand.enabled = true;
   center.pauseCommand.enabled = true;
   [center.playCommand addTarget:self action:@selector(play)];
   [center.pauseCommand addTarget:self action:@selector(pause)];
}
- (MPRemoteCommandHandlerStatus) play {
   NSLog(@"test");
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"play"]];
   return MPRemoteCommandHandlerStatusSuccess;

}
- (MPRemoteCommandHandlerStatus) pause {
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"pause"]];
   return MPRemoteCommandHandlerStatusSuccess;
}

#end if

You can use XUI.FileUri to access local files.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
i have tried your code and the problem is that it is now a different object which will be very hard to manage. i will need to implement all player controls by myself and do everything with nativeobject which is too complicated for me. even changing between the songs is too complicated.

the thing is that i am not trying to create a list and play it until it is finished. what i try to do is click on an item in a clv and play that song with works fine using the videoplayer but locking my phone wont show the controls on the screen. ONLY on the first song it does show the controls. using AVQueuePlayer will play a list of items but going back to the app and loading a new song will again remove the controls from the lock screen.
 
Upvote 0
Top