Unity IOS后台播放音乐被打断

RT,被QQ音乐或者其他音视频App打断音乐播放之后,我重新进入我的App重新播放音乐时,无法更新mPNowPlayingInfoCenter 显示

img

基于new Bing 和ChatGPT的回答:
在 iOS 应用中,MPNowPlayingInfoCenter 是用于管理锁屏界面和控制中心的媒体信息的类,用于显示当前播放的音频的信息,包括歌曲名、歌手名、专辑名、歌曲封面等。在应用程序进入后台或被打断时,如果想要在回到应用程序后更新媒体信息,可以调用 MPNowPlayingInfoCenter 的 nowPlayingInfo 属性来更新当前播放的音频信息。例如:

import MediaPlayer

// 更新媒体信息
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
nowPlayingInfoCenter.nowPlayingInfo = [
    MPMediaItemPropertyTitle: "歌曲名",
    MPMediaItemPropertyArtist: "歌手名",
    MPMediaItemPropertyAlbumTitle: "专辑名",
    MPMediaItemPropertyArtwork: MPMediaItemArtwork(boundsSize: CGSize(width: 100, height: 100)) { (_) -> UIImage in
        return UIImage(named: "cover")!
    }
]


在应用程序被打断或进入后台时,需要在应用程序回到前台时重新更新媒体信息。可以在 AppDelegate.swift 中的 applicationWillEnterForeground(_:) 方法中调用更新媒体信息的代码,例如:

import UIKit
import MediaPlayer

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func applicationWillEnterForeground(_ application: UIApplication) {
        // 更新媒体信息
        let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
        nowPlayingInfoCenter.nowPlayingInfo = [
            MPMediaItemPropertyTitle: "歌曲名",
            MPMediaItemPropertyArtist: "歌手名",
            MPMediaItemPropertyAlbumTitle: "专辑名",
            MPMediaItemPropertyArtwork: MPMediaItemArtwork(boundsSize: CGSize(width: 100, height: 100)) { (_) -> UIImage in
                return UIImage(named: "cover")!
            }
        ]
    }
}


这样,在应用程序重新进入前台时,MPNowPlayingInfoCenter 的 nowPlayingInfo 属性就会被更新,并在锁屏界面和控制中心显示最新的媒体信息。

该回答引用ChatGPT
根据您的问题描述,我了解到您遇到的问题是在 iOS 平台中使用 Unity 开发的 app,在后台播放音乐时被其他音频应用打断后,无法更新 mPNowPlayingInfoCenter 显示的问题。

在 iOS 平台中,只有特定的音频类型才能在后台持续播放,例如播客、语音记录等。而像音乐播放器、视频播放器等普通的媒体应用,当用户切换到其他 app 时往往会被系统打断,这是为了释放设备资源和保护用户隐私。

如果您想让您的音乐播放器在后台持续播放,您需要使用 AVAudioSession 实例来声明应用程序的音频会话类型和选项。在声明音频会话类型时,需要指定 AVAudioSessionCategoryPlayback,这个分类允许音频在静音模式下继续播放,并且允许在后台播放音频。下面是一个示例代码:


using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.iOS;

public class BackgroundMusic : MonoBehaviour
{
private string _musicPath = "file:///" + Application.streamingAssetsPath + "/music.mp3";

voic Awake ()
{
StartCoroutine(LoadMusic());
}

voic OnApplicationPause(bool pauseStatus)
{
if (!pauseStatus)
{
StartCoroutine(LoadMusic());
}
}

IEnumerator LoadMusic()
{
var uwr = new UnityEngine.Networking.UnityWebRequest(_musicPath);
uwr.downloadHandler = new UnityEngine.Networking.DownloadHandlerAudioClip(_musicPath, AudioType.MPEG);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
{
Debug.Log(uwr.error);
}
else
{
var audio = (AudioClip)DownloadHandlerAudioClip.GetContent(uwr);
var audioSource = GetComponent();
audioSource.clip = audio;

audioSource.Play();

var audioSession = AVAudioSession.SharedInstance();
audioSession.SetCategory(AVAudioSessionCategory.Playback);
audioSession.SetActive(true);
}
}
}


当用户离开您的 app 时,您可以重写 OnApplicationPause 方法以继续播放音频并更新 mPNowPlayingInfoCenter 显示。下面是 OnApplicationPause 的代码示例:


voic OnApplicationPause(bool pauseStatus)
{
if (!pauseStatus)
{
var audioSession = AVAudioSession.SharedInstance();
audioSession.SetActive(true);

UpdateNowPlayingInfo();
}
}

voic UpdateNowPlayingInfo()
{
var nowPlayingInfo = new Dictionary();

nowPlayingInfo[MPNowPlayingInfoProperty.Artist] = "Artist";
nowPlayingInfo[MPNowPlayingInfoProperty.Title] = "Title";
nowPlayingInfo[MPNowPlayingInfoProperty.AlbumTitle] = "Album";
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = audio.clip.length;
nowPlayingInfo[MPNowPlayingInfoProperty.ElapsedPlaybackTime] = audio.time;

MPNowPlayingInfoCenter.DefaultCenter().SetValuesForKeysWithDictionary(nowPlayingInfo);
}


当您的应用程序被打断或进入静音模式时,您需要暂停音乐播放并更新 mPNowPlayingInfoCenter 显示。下面是示例代码:


voic OnApplicationPause(bool pauseStatus)
{
if (pauseStatus)
{
audio.Pause();
}
else
{
var audioSession = AVAudioSession.SharedInstance();
audioSession.SetActive(true);
UpdateNowPlayingInfo();
}
}

void OnApplicationFocus(bool hasFocus)
{
if (!hasFocus)
{
audio.Pause();
}
}


这些代码示例应该可以帮助您解决您的问题。但是由于您没有提供更多的细节和代码,无法详细分析您遇到的问题。如果您还遇到问题,可以进一步提供细节和代码,我可以帮助您进行更准确的分析和解决方案提供。

这个问题的产生原因是因为 QQ 音乐或其他音视频 App 运行时,它们会占用 iOS 中的 MPNowPlayingInfoCenter 对象,从而导致你的 App 无法更新该对象。要解决这个问题,你需要在你的 App 运行时,对 MPNowPlayingInfoCenter 进行监测,如果发现被修改了,则重新设置一遍。

下面是一个示例代码,可以解决这个问题:


// 在 AppDelegate 的 applicationDidBecomeActive 方法中添加该代码
if let info = MPNowPlayingInfoCenter.default().nowPlayingInfo {
    MPNowPlayingInfoCenter.default().nowPlayingInfo = info
}

这段代码实现了在 applicationDidBecomeActive 方法中重新设置 MPNowPlayingInfoCenter 的功能。具体思路是,在重启 App 之后,在你的 App 运行时,检查当前的 MPNowPlayingInfoCenter 中是否有数据,如果有数据就重新设置一遍。

需要注意的是,这个问题主要是由于 iOS 系统的基本机制所导致的。但是,在实际应用中,为了提高用户体验,可以在用户打开 App 之前,提醒用户先暂停 QQ 音乐或其他音视频 App 的播放,以避免此类问题的产生。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在iOS中,当你的App在后台播放音频时,其他音频应用程序(如QQ音乐或其他视频应用程序)可能会打断你的音频播放。这是iOS的默认行为,以确保用户可以轻松地切换不同的音频应用程序。当打断发生时,系统会向你的应用程序发送一个通知,让你暂停音乐播放。当用户从其他应用程序切回你的应用程序时,你需要重新启动音频播放。在这种情况下,你需要重新配置mPNowPlayingInfoCenter以更新正在播放的信息。

以下是一个示例函数,用于配置mPNowPlayingInfoCenter以更新正在播放的信息:

void ConfigureNowPlayingInfoCenter()
{
    // Set up the now playing info center with the current track information
    MPNowPlayingInfoCenter *nowPlayingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
    NSMutableDictionary *nowPlayingInfo = [NSMutableDictionary dictionaryWithDictionary:nowPlayingInfoCenter.nowPlayingInfo];
    
    // Update the title of the current track
    NSString *title = @"My Song Title";
    [nowPlayingInfo setObject:title forKey:MPMediaItemPropertyTitle];
    
    // Update the artist name of the current track
    NSString *artist = @"My Song Artist";
    [nowPlayingInfo setObject:artist forKey:MPMediaItemPropertyArtist];
    
    // Update the artwork of the current track
    UIImage *artworkImage = [UIImage imageNamed:@"mySongArtwork.jpg"];
    MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:artworkImage];
    [nowPlayingInfo setObject:artwork forKey:MPMediaItemPropertyArtwork];
    
    nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo;
}

如果你的应用程序在后台播放音频,并且音频播放被其他应用程序打断,你可以在调用你的应用程序中的重新启动音频播放的代码之前调用此函数,以确保正在播放的信息正确更新。例如:

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Reconfigure the now playing info center with the updated track information
    [self configureNowPlayingInfoCenter];
    
    // Restart audio playback
    [self restartAudioPlayback];
}

注意:上面的代码样例按照Obj-C来写的,请根据你自己的语言进行修改。
如果我的回答解决了您的问题,请采纳!

以下内容部分参考ChatGPT模型:
我可以为您提供一些解决方案:

  1. 检查您的代码是否正确地实现了AVAudioSession的中断处理方法。当音频被打断时,系统会调用此方法,您需要在方法中执行必要的操作来恢复音频播放。

  2. 确认您是否正确地设置了mPNowPlayingInfoCenter。在您的App重新进入前台时,您需要更新mPNowPlayingInfoCenter以反映当前正在播放的音频信息。

  3. 检查您的App是否正确地申请了后台播放权限。如果您的App没有后台播放权限,它将无法在后台继续播放音频。

以下是一些代码示例:

在您的AppDelegate.m文件中,您需要实现以下方法来处理音频中断:

- (void)audioSessionInterruption:(AVAudioSessionInterruptionNotification *)notification {
    AVAudioSessionInterruptionType interruptionType = [notification.userInfo[AVAudioSessionInterruptionTypeKey] integerValue];
    if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
        // 处理音频中断开始的情况
    } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
        // 处理音频中断结束的情况
        BOOL shouldResume = [notification.userInfo[AVAudioSessionInterruptionOptionKey] boolValue];
        if (shouldResume) {
            // 恢复音频播放
        }
    }
}

在您的播放器类中,您需要实现以下方法来更新mPNowPlayingInfoCenter:

- (void)updateNowPlayingInfoCenter {
    NSMutableDictionary *nowPlayingInfo = [NSMutableDictionary dictionary];
    nowPlayingInfo[MPMediaItemPropertyTitle] = self.currentSong.title;
    nowPlayingInfo[MPMediaItemPropertyArtist] = self.currentSong.artist;
    nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = self.currentSong.album;
    nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = @(1.0);
    nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = @(self.currentSong.duration);
    nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(self.currentTime);
    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:nowPlayingInfo];
}

在您的AppDelegate.m文件中,您需要在applicationDidEnterBackground方法中请求后台播放权限:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setActive:YES error:nil];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    [application beginReceivingRemoteControlEvents];
}

希望这些代码示例能够帮助您解决问题。