iOS How to trigger video to keep playing after exiting fullscreen? - ios

I'm building a website that plays video in iOS. I have a fullscreen button working in iOS however the video pauses when exiting fullscreen. Does anyone know a way to either force the video to continue to play upon exiting fullscreen or how to set up a listener that triggers the video to autoplay upon exiting fullscreen?
here is my code:
<script>
var video = document.getElementById('tv'),
play = document.getElementById('fullscreenbutton'),
time;
video.addEventListener('webkitbeginfullscreen', function() {
play.innerText = '';
window.clearInterval(time);
});
video.addEventListener('webkitendfullscreen', function() {
tv.autoplay();
});
play.addEventListener('touchstart', function() {
time = window.setInterval(function() {
try {
video.webkitEnterFullscreen();
}
catch(e) {}
}, 250);
play.innerText = 'loading ...';
tv.play();
});
</script>
'''

You can use WKScriptMessageHandler in your iOS app when a button to exit fullscreen mode is tapped then resume your video player.
Here is a workaround on how I would handle this situation.
Native iOS + JavaScript
1 Step: Website front end part
When exit full screen button is tapped on your website emit an event give it a unique name something like "exitFullScreenEvent"
2 Step: iOS App
import WebKit
ViewController: WKScriptMessageHandler {
// Helper method to set configurations for your webView in iOS
func configureWebView() {
///Add the script message handler into the content controller.
let contentController = WKUserContentController()
/// Give it the same name as on the web front-end part
contentController.add(self, name: "exitFullScreenEvent")
let config = WKWebViewConfiguration()
config.userContentController = contentController
/// Most important, when initilizing your web view pass the configuration above
let webView = WKWebView(frame: .zero, configuration: config)
// Layout/add constraints to your webView
// .....
}
// Delegate method to listen an event emitted from your website
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// TODO: - Resume/ Play your video
}
}
Pure Website (Javascript only)
For website only which runs in pure Javascript without any iOS related components and on Safari browser you might want to check this webkitjs displayingfullscreen
I Haven't used it before but it worth reading the doc.
But another work around without putting lots of effort is to compare your video player's screen size with the browsers window size ie.. check if browser is full screen if so get the full screen width if it's the same with your video player's size then video is in full screen.

Related

WKWebView stop audio when backgrounding app

I have a WKWebView which is playing HTML5 video. When I click the home button and the app enters the background I can still hear the audio playing. How can I pause the HTML 5 video to stop the background audio from playing. I tried just loading a blank page when the app enters background which works,
let url = URL(string: "about:blank")
let request = URLRequest(url:url!)
self.webView.load(request)
but I want to be able to start the video at the same point when the user returns from the background so it is not a viable solution since it just loads the blank page when I open the app back up.
I was able to achive this by injecting JavaScript when the app entered the background which would pause any video elements that are playing.
NotificationCenter.default.addObserver(self, selector: #selector(enteredBackground(notification:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
#objc func enteredBackground(notification: Notification) {
let script = "var vids = document.getElementsByTagName('video'); for( var i = 0; i < vids.length; i++ ){vids.item(i).pause()}"
self.webView.evaluateJavaScript(script, completionHandler:nil)
}

Cast Sender App Shows Pause Button Instead of Stop Button

So I am trying to build a sender app for chromecast that will stream Live feeds only. The trouble is the various framework dialogs all show a Pause button, when in fact I need a Stop button (or for the feed to at least jump back to current live time when it is resumed)
The only information I can find on this through the documentation is some vague snippet
When your sender app is playing a video or audio live stream, the SDK automatically displays a play/stop button in place of the play/pause button in the mini controller.
When I create the GCKMediaInformation object to load on the chromecast, I set its Media Stream Type to Live with a content type of "vnd.apple.mpegURL" But this has no effect.
Does anybody have any idea how I can make the stop button appear instead of the pause button?
EDIT:
A strip down version of the logic used to load live stream feed
let metaData = GCKMediaMetadata(metadataType: .generic)
metaData.setString(selectedChannel!.channelName, forKey: kGCKMetadataKeyTitle)
metaData.addImage(GCKImage(url: URL(string: selectedChannel!.imgURL)!, width: 10, height: 20))
mediaInfo = GCKMediaInformation(contentID: selectedChannel!.vidURL, streamType: GCKMediaStreamType.live, contentType: "vnd.apple.mpegURL", metadata: metaData, streamDuration: 0, mediaTracks: nil, textTrackStyle: nil, customData: nil)
if sessionManager.currentCastSession != nil {
switchToCastingMode()
}
func switchToCastingMode() {
print("switching to CAST mode")
if let session = GCKCastContext.sharedInstance().sessionManager.currentCastSession {
if session.remoteMediaClient?.mediaStatus?.mediaInformation?.contentID != mediaInfo?.contentID {
session.remoteMediaClient?.loadMedia(mediaInfo!, autoplay: true)
GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()
}
}
}
I have also tried changing the media stream type to other values, but this has no effect either :(

Audio playback lock screen controls not displaying on iPhone

I am testing this using iOS 10.2 on my actual iPhone 6s device.
I am playing streamed audio and am able to play/pause audio, skip tracks, etc. I also have enabled background modes and the audio plays in the background and continues through a playlist properly. The only issue I am having is getting the lock screen controls to show up. Nothing displays at all...
In viewDidLoad() of my MainViewController, right when my app launches, I call this...
func setupAudioSession(){
UIApplication.shared.beginReceivingRemoteControlEvents()
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.mixWithOthers)
self.becomeFirstResponder()
do {
try AVAudioSession.sharedInstance().setActive(true)
print("AVAudioSession is Active")
} catch let error as NSError {
print(error.localizedDescription)
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
and then in my AudioPlayer class after I begin playing audio I call ...
func setupLockScreen(){
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.nextTrackCommand.isEnabled = true
commandCenter.nextTrackCommand.addTarget(self, action:#selector(skipTrack))
MPNowPlayingInfoCenter.default().nowPlayingInfo = [MPMediaItemPropertyTitle: "TESTING"]
}
When I lock my iPhone and then tap the power button again to go to the lock screen, the audio controls are not displayed at all. It is as if no audio is playing, I just see my normal background photo. Also no controls are displayed in the control panel (swiping up on home screen and then swiping left to where the music controls should be).
Is the issue because I am not using AVAudioPlayer or AVPlayer? But then how does, for example, Spotify get the lock screen controls to display using their own custom audio player? Thanks for any advice / help
The issue turned out to be this line...
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.duckOthers)
Once I changed it to
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: [])
everything worked fine. So it seems that passing in any argument for AVAudioSessionCategoryPlaybackOptions causes the lock screen controls to not display. I also tried passing in .mixWithOthers an that too caused the lock screen controls to not be displayed
In Swift 4. This example is only to show the player on the lock screen and works with iOS 11. To know how to play auidio on the device you can follow this thread https://stackoverflow.com/a/47710809/1283517
import MediaPlayer
import AVFoundation
Declare player
var player : AVPlayer?
Now create a function
func setupLockScreen(){
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.nextTrackCommand.isEnabled = true
commandCenter.togglePlayPauseCommand.addTarget(self, action: #selector(controlPause))
MPNowPlayingInfoCenter.default().nowPlayingInfo = [MPMediaItemPropertyTitle: currentStation]
}
now create a function for control play and pause event. I have created a BOOL "isPlaying" to determine the status of the player.
#objc func controlPause() {
if isPlaying == true {
player?.pause()
isPlaying = false
} else {
player?.play()
isPlaying = true
}
}
And ready. Now the player will be displayed on the lock screen
Yes, for the lock screen to work you need to use iOS APIs to play audio. Not sure how Spotify does it but they may be using a second audio session in parallel for this purpose and use the controls to control both. Your background handler (the singleton in my case) could start playing the second audio with 0 volume when it goes into background and stop it when in foreground. I haven't tested it myself but an option to try.

show audio or video controller in dart

I want to create a audio or video controller, but my current code only plays the content, nothing is shown to control it in my browser
#import ('dart:html');
void main () {
AudioElement audio = new AudioElement();
audio.src="http://slides.html5rocks.com/src/rushus-modal_blues.mp3";
audio.autoplay=true;
window.document.body.nodes.add(audio);
}
So how do you get Dart to show a controller for audio/video ?
The controls for audio/video are disabled by default. You will need to enable them
audio.controls = true;
should do the trick.
Alternativly you can also build the audio source and controls settings from scractch, the following examples shows this and have been tested sucessfully with dart2js
var audioSource = new SourceElement();
audioSource.src = "http://slides.html5rocks.com/src/rushus-modal_blues.mp3";
audioSource.type = "audio/mp3";
var audio = new AudioElement();
audio.attributes["controls"] = "controls";
audio.nodes.add(audioSource);
window.document.body.nodes.add(audio);
There is more info on controlling audio here and video here

webkitIsFullScreen on ipad/iphone?

I have an application that requires a page refresh whenever the orientation changes (ipad/iphone). Within this application, HTML5 videos also gets presented at certain times in UX. Whenever a user is viewing a video in full screen mode, their first inclination is to rotate the device to landscape orientation if it was not already in that mode. When they do this, however, it triggers the nasty page reload, effectively ending their viewing session. By tapping into webkit full screen API I was able to write logic to control this behavior, which works perfectly on Safari desktop as well as with the iPad/iPhone user agent selected in developer tools, but it DOES NOT work on the native iphone/ipad.
document.webkitIsFullScreen returns false/true correctly in console in Safari, but comes up as undefined on iphone/ipad. Can anyone tell me how to accomplish this on ipad/iphone, since these are the only devices that require this functionality anyway? Or is there a much simpler solution that I am overlooking? Any help is greatly appreciated!
$(document).ready( function () {
var video = document.getElementById('video');
var canrefresh = true;
video.addEventListener("webkitfullscreenchange",function(){
// Detects if video is in full screen mode and toggles canrefresh variable
// canrefresh = false when webkitfullscreenchange event is heard
// canrefresh = true after exiting full screen
if (canrefresh == true) {
canrefresh = false;
} else {
canrefresh = true;
}
console.log(document.webkitIsFullScreen+' | '+canrefresh);
}, false);
$(window).resize(function() {
// Look to make sure not in full screen, and canrefresh variable is true before refreshing page
if((document.webkitIsFullScreen == false) && (canrefresh == true)){
window.location = window.location.href+'?v='+Math.floor(Math.random()*1000);
}
});
console.log(document.webkitIsFullScreen+' | '+canrefresh);
$('body .test').text(document.webkitIsFullScreen+' | '+canrefresh); // document.webkitIsFullScreen is returning 'false' in Safari (correct), but 'undefined' on native iphone/ipad device
});
The equivalent property which is compatible with Mobile Safari is the webkitDisplayingFullscreen property on the HTMLVideoElement DOM object.

Resources