iOS Tutorial Background playback

Erel

Administrator
Staff member
Licensed User
This tutorial explains how you can play local audio files or stream audio while your app is in the background.
Standard applications are killed when moved to the background. However you can add the following attribute to your project to mark it as an application that plays audio in the background:
B4X:
#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: 7.1
#End Region
#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 vv As VideoView
End Sub

Private Sub Application_Start (Nav As NavigationController)
   NativeMe = Me
   NavControl = Nav
   Page1.Initialize("Page1")
   Page1.Title = "Page 1"
   Page1.RootPanel.Color = Colors.White
   NavControl.ShowPage(Page1)
   NativeMe.RunMethod("setAudioSession", Null)
   vv.Initialize("vv")
   vv.LoadVideoUrl("http://stream-dc1.radioparadise.com/mp3-32")
   vv.Play
   NativeMe.RunMethod("register", Null)
End Sub

Public Sub ControlEvent (Command As String)
   Select Command
       Case "play"
           vv.Play
       Case "pause"
           vv.Pause
   End Select
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)];
}
- (void) play {
   NSLog(@"test");
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"play"]];
}
- (void) pause {
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"pause"]];
}

#end if
The above code (depends on iMedia library and B4i v1.8+) will play the radio stream. You can leave your app and the streaming will continue.

With this code the user can play and pause the playback from the bottom drawer.
Note that it is supported by iOS 7.1+.
 
Last edited:

ilan

Expert
Licensed User
this is great... just discovered this thread, did not knew its possible with b4i..
 

yonson

Active Member
Licensed User
brilliant thank you so much for this, really essential for a lot of apps I'm srue
 

Daniel Uribe

Member
Licensed User
Greetings, here the next and previous buttons in background, result very efficient when you have a playlist.

B4X:
Public Sub ControlEvent (Command AsString)
Select Command
         Case"play"
            vv.Play
         Case"pause"
            vv.Pause
        Case "nextTrack"
            Log("next")
        Case "previousTrack"
            Log("previous")
    End Select
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];
  }
  if (!success)
  [NSException raise:@"" format:@"Error setting audio session: %@", err];
  [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
- (void)register {
   MPRemoteCommandCenter* center = [MPRemoteCommandCenter sharedCommandCenter];
   center.playCommand.enabled = true;
   center.pauseCommand.enabled = true;
   center.nextTrackCommand.enabled = true;
   center.previousTrackCommand.enabled = true;
   [center.playCommand addTarget:self action:@selector(play)];
   [center.pauseCommand addTarget:self action:@selector(pause)];
   [center.nextTrackCommand addTarget:self action:@selector(nextTrack)];
   [center.previousTrackCommand addTarget:self action:@selector(previousTrack)];
}
- (void) play {
   NSLog(@"test");
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"play"]];
}
- (void) pause {
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"pause"]];
}
- (void) nextTrack {
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"nextTrack"]];
}
- (void) previousTrack {
   [self.bi raiseEvent:nil event:@"controlevent:"  params:@[@"previousTrack"]];
}
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
  if (receivedEvent.type == UIEventTypeRemoteControl) {
     [self.bi raiseEvent:nil event:@"remotecontrol_event:"
       params:@[@(receivedEvent.subtype)]];
   }
}

#end if
 

Erel

Administrator
Staff member
Licensed User
1. Add this code to the OBJC block:
B4X:
- (MPMediaItemArtwork*)createArtwork:(UIImage*) image {
   return [[MPMediaItemArtwork alloc] initWithBoundsSize:image.size requestHandler:^UIImage* _Nonnull(CGSize aSize) { return image; }];
}
2. Set title and artwork:
B4X:
  Dim artwork As NativeObject = NativeMe.RunMethod("createArtwork:", Array(LoadBitmapResize(File.DirAssets, "b4i_128_128.png", 64, 64, True)))
   SetPlayingInfo(CreateMap("title": "Radio Paradise", "artwork": artwork))
End Sub

Sub SetPlayingInfo (info As Map)
   Dim NowPlayingInfoCenter As NativeObject
   NowPlayingInfoCenter = NowPlayingInfoCenter.Initialize("MPNowPlayingInfoCenter").RunMethod("defaultCenter", Null)
   Dim no As NativeObject = info
   NowPlayingInfoCenter.SetField("nowPlayingInfo", no.RunMethod("ToDictionary", Null))
End Sub
 

cloner7801

Active Member
Licensed User
1. Add this code to the OBJC block:
B4X:
- (MPMediaItemArtwork*)createArtwork:(UIImage*) image {
   return [[MPMediaItemArtwork alloc] initWithBoundsSize:image.size requestHandler:^UIImage* _Nonnull(CGSize aSize) { return image; }];
}
2. Set title and artwork:
B4X:
  Dim artwork As NativeObject = NativeMe.RunMethod("createArtwork:", Array(LoadBitmapResize(File.DirAssets, "b4i_128_128.png", 64, 64, True)))
   SetPlayingInfo(CreateMap("title": "Radio Paradise", "artwork": artwork))
End Sub

Sub SetPlayingInfo (info As Map)
   Dim NowPlayingInfoCenter As NativeObject
   NowPlayingInfoCenter = NowPlayingInfoCenter.Initialize("MPNowPlayingInfoCenter").RunMethod("defaultCenter", Null)
   Dim no As NativeObject = info
   NowPlayingInfoCenter.SetField("nowPlayingInfo", no.RunMethod("ToDictionary", Null))
End Sub
How can I set playing info ? with SetPlayingInfo

can you post a example?
---
SOLVED !
 
Last edited:
Top