mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-10 04:54:57 +02:00
Merge pull request #106 from rasmuslos/master
Show "now playing" on lock screen & in control center
This commit is contained in:
commit
f5088d0384
2 changed files with 81 additions and 42 deletions
|
@ -7,6 +7,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
|
UIApplication.shared.beginReceivingRemoteControlEvents()
|
||||||
// Override point for customization after application launch.
|
// Override point for customization after application launch.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,13 @@ import Capacitor
|
||||||
import MediaPlayer
|
import MediaPlayer
|
||||||
import AVKit
|
import AVKit
|
||||||
|
|
||||||
|
extension UIImage {
|
||||||
extension UIImageView {
|
func imageWith(newSize: CGSize) -> UIImage {
|
||||||
public func imageFromUrl(urlString: String) {
|
let renderer = UIGraphicsImageRenderer(size: newSize)
|
||||||
if let url = NSURL(string: urlString) {
|
let image = renderer.image { _ in
|
||||||
let request = NSURLRequest(url: url as URL)
|
self.draw(in: CGRect.init(origin: CGPoint.zero, size: newSize))
|
||||||
NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: OperationQueue.main) {
|
|
||||||
(response: URLResponse?, data: Data?, error: Error?) -> Void in
|
|
||||||
if let imageData = data as Data? {
|
|
||||||
self.image = UIImage(data: imageData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return image.withRenderingMode(self.renderingMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +19,7 @@ struct Audiobook {
|
||||||
var title = "No Title"
|
var title = "No Title"
|
||||||
var author = "Unknown"
|
var author = "Unknown"
|
||||||
var playWhenReady = false
|
var playWhenReady = false
|
||||||
var startTime = 0
|
var startTime = 0.0
|
||||||
var cover = ""
|
var cover = ""
|
||||||
var duration = 0
|
var duration = 0
|
||||||
var series = ""
|
var series = ""
|
||||||
|
@ -74,7 +69,7 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
title: call.getString("title") ?? "No Title",
|
title: call.getString("title") ?? "No Title",
|
||||||
author: call.getString("author") ?? "Unknown",
|
author: call.getString("author") ?? "Unknown",
|
||||||
playWhenReady: call.getBool("playWhenReady", false),
|
playWhenReady: call.getBool("playWhenReady", false),
|
||||||
startTime: call.getInt("startTime") ?? 0,
|
startTime: Double(call.getString("startTime") ?? "0") ?? 0.0,
|
||||||
cover: call.getString("cover") ?? "",
|
cover: call.getString("cover") ?? "",
|
||||||
duration: call.getInt("duration") ?? 0,
|
duration: call.getInt("duration") ?? 0,
|
||||||
series: call.getString("series") ?? "",
|
series: call.getString("series") ?? "",
|
||||||
|
@ -98,7 +93,7 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
|
|
||||||
// For play in background
|
// For play in background
|
||||||
do {
|
do {
|
||||||
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay])
|
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .spokenAudio, options: [.allowAirPlay])
|
||||||
NSLog("[TEST] Playback OK")
|
NSLog("[TEST] Playback OK")
|
||||||
try AVAudioSession.sharedInstance().setActive(true)
|
try AVAudioSession.sharedInstance().setActive(true)
|
||||||
NSLog("[TEST] Session is Active")
|
NSLog("[TEST] Session is Active")
|
||||||
|
@ -116,8 +111,11 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
context: &playerItemContext)
|
context: &playerItemContext)
|
||||||
|
|
||||||
self.audioPlayer = AVPlayer(playerItem: playerItem)
|
self.audioPlayer = AVPlayer(playerItem: playerItem)
|
||||||
let time = self.audioPlayer.currentItem?.currentTime()
|
|
||||||
|
|
||||||
|
let startTime = CMTime(seconds: (audiobook?.startTime ?? 0.0) / 1000, preferredTimescale: 1000)
|
||||||
|
self.audioPlayer.seek(to: startTime)
|
||||||
|
|
||||||
|
let time = self.audioPlayer.currentItem?.currentTime()
|
||||||
print("Audio Player Initialized \(String(describing: time))")
|
print("Audio Player Initialized \(String(describing: time))")
|
||||||
|
|
||||||
call.resolve(["success": true])
|
call.resolve(["success": true])
|
||||||
|
@ -206,9 +204,10 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
self.notifyListeners("onPlayingUpdate", data: [
|
self.notifyListeners("onPlayingUpdate", data: [
|
||||||
"value": true
|
"value": true
|
||||||
])
|
])
|
||||||
|
sendMetadata()
|
||||||
|
|
||||||
playerState = .playing
|
playerState = .playing
|
||||||
setupNowPlaying()
|
updateNowPlaying()
|
||||||
}
|
}
|
||||||
|
|
||||||
func pause() {
|
func pause() {
|
||||||
|
@ -216,6 +215,7 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
self.notifyListeners("onPlayingUpdate", data: [
|
self.notifyListeners("onPlayingUpdate", data: [
|
||||||
"value": false
|
"value": false
|
||||||
])
|
])
|
||||||
|
sendMetadata()
|
||||||
|
|
||||||
playerState = .paused
|
playerState = .paused
|
||||||
}
|
}
|
||||||
|
@ -271,8 +271,10 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
case .readyToPlay:
|
case .readyToPlay:
|
||||||
// Player item is ready to play.
|
// Player item is ready to play.
|
||||||
NSLog("AVPlayer ready to play")
|
NSLog("AVPlayer ready to play")
|
||||||
|
|
||||||
setNowPlayingMetadata()
|
setNowPlayingMetadata()
|
||||||
sendMetadata()
|
sendMetadata()
|
||||||
|
|
||||||
if (audiobook?.playWhenReady == true) {
|
if (audiobook?.playWhenReady == true) {
|
||||||
NSLog("AVPlayer playWhenReady == true")
|
NSLog("AVPlayer playWhenReady == true")
|
||||||
play()
|
play()
|
||||||
|
@ -291,7 +293,7 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func appDidEnterBackground() {
|
@objc func appDidEnterBackground() {
|
||||||
setupNowPlaying()
|
updateNowPlaying()
|
||||||
NSLog("[TEST] App Enter Backround")
|
NSLog("[TEST] App Enter Backround")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,53 +305,89 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
func setupRemoteTransportControls() {
|
func setupRemoteTransportControls() {
|
||||||
// Get the shared MPRemoteCommandCenter
|
// Get the shared MPRemoteCommandCenter
|
||||||
let commandCenter = MPRemoteCommandCenter.shared()
|
let commandCenter = MPRemoteCommandCenter.shared()
|
||||||
|
|
||||||
// Add handler for Play Command
|
commandCenter.playCommand.isEnabled = true
|
||||||
commandCenter.playCommand.addTarget { [unowned self] event in
|
commandCenter.playCommand.addTarget { [unowned self] event in
|
||||||
NSLog("[TEST] Play Command \(playbackRate())")
|
play()
|
||||||
if playbackRate() == 0.0 {
|
return .success
|
||||||
play()
|
|
||||||
return .success
|
|
||||||
}
|
|
||||||
return .commandFailed
|
|
||||||
}
|
}
|
||||||
|
commandCenter.pauseCommand.isEnabled = true
|
||||||
// Add handler for Pause Command
|
|
||||||
commandCenter.pauseCommand.addTarget { [unowned self] event in
|
commandCenter.pauseCommand.addTarget { [unowned self] event in
|
||||||
NSLog("[TEST] Pause Command \(playbackRate())")
|
pause()
|
||||||
if playbackRate() == 1.0 {
|
return .success
|
||||||
pause()
|
}
|
||||||
return .success
|
|
||||||
|
commandCenter.skipForwardCommand.isEnabled = true
|
||||||
|
commandCenter.skipForwardCommand.preferredIntervals = [30]
|
||||||
|
commandCenter.skipForwardCommand.addTarget { [unowned self] event in
|
||||||
|
guard let command = event.command as? MPSkipIntervalCommand else {
|
||||||
|
return .noSuchContent
|
||||||
}
|
}
|
||||||
return .commandFailed
|
|
||||||
|
self.audioPlayer.seek(to: CMTime(seconds: currentTime() + command.preferredIntervals[0].doubleValue, preferredTimescale: 1000))
|
||||||
|
updateNowPlaying()
|
||||||
|
|
||||||
|
return .success
|
||||||
|
}
|
||||||
|
commandCenter.skipBackwardCommand.isEnabled = true
|
||||||
|
commandCenter.skipBackwardCommand.preferredIntervals = [30]
|
||||||
|
commandCenter.skipBackwardCommand.addTarget { [unowned self] event in
|
||||||
|
guard let command = event.command as? MPSkipIntervalCommand else {
|
||||||
|
return .noSuchContent
|
||||||
|
}
|
||||||
|
|
||||||
|
self.audioPlayer.seek(to: CMTime(seconds: currentTime() - command.preferredIntervals[0].doubleValue, preferredTimescale: 1000))
|
||||||
|
updateNowPlaying()
|
||||||
|
|
||||||
|
return .success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getData(from url: URL, completion: @escaping (UIImage?) -> Void) {
|
||||||
|
URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
|
||||||
|
if let data = data {
|
||||||
|
completion(UIImage(data:data))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.resume()
|
||||||
|
}
|
||||||
func setNowPlayingMetadata() {
|
func setNowPlayingMetadata() {
|
||||||
|
if (audiobook?.cover != nil) {
|
||||||
|
guard let url = URL(string: audiobook!.cover) else { return }
|
||||||
|
getData(from: url) { [weak self] image in
|
||||||
|
guard let self = self,
|
||||||
|
let downloadedImage = image else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let artwork = MPMediaItemArtwork.init(boundsSize: downloadedImage.size, requestHandler: { _ -> UIImage in
|
||||||
|
return downloadedImage
|
||||||
|
})
|
||||||
|
|
||||||
|
self.setNowPlayingMetadataWithImage(artwork)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setNowPlayingMetadataWithImage(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func setNowPlayingMetadataWithImage(_ artwork: MPMediaItemArtwork?) {
|
||||||
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
|
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
|
||||||
var nowPlayingInfo = [String: Any]()
|
var nowPlayingInfo = [String: Any]()
|
||||||
|
|
||||||
NSLog("%@", "**** Set track metadata: title \(audiobook?.title ?? "")")
|
NSLog("%@", "**** Set track metadata: title \(audiobook?.title ?? "")")
|
||||||
nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = audiobook?.playlistUrl ?? ""
|
nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = audiobook?.playlistUrl != nil ? URL(string: audiobook!.playlistUrl) : nil
|
||||||
nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = "hls"
|
nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = "hls"
|
||||||
nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false
|
nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false
|
||||||
nowPlayingInfo[MPMediaItemPropertyTitle] = audiobook?.title ?? ""
|
nowPlayingInfo[MPMediaItemPropertyTitle] = audiobook?.title ?? ""
|
||||||
nowPlayingInfo[MPMediaItemPropertyArtist] = audiobook?.author ?? ""
|
nowPlayingInfo[MPMediaItemPropertyArtist] = audiobook?.author ?? ""
|
||||||
|
|
||||||
if (audiobook?.cover != nil) {
|
if (artwork != nil) {
|
||||||
let myImageView = UIImageView()
|
nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork
|
||||||
myImageView.imageFromUrl(urlString: audiobook?.cover ?? "")
|
|
||||||
nowPlayingInfo[MPMediaItemPropertyArtwork] = myImageView.image
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nowPlayingInfo[MPMediaItemPropertyAlbumArtist] = audiobook?.author ?? ""
|
|
||||||
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = audiobook?.title ?? ""
|
|
||||||
|
|
||||||
nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
|
nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupNowPlaying() {
|
func updateNowPlaying() {
|
||||||
|
|
||||||
if (playerState != .playing) {
|
if (playerState != .playing) {
|
||||||
NSLog("[TEST] Not current playing so not updating now playing info")
|
NSLog("[TEST] Not current playing so not updating now playing info")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue