You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Theos Tweak中AVAudioSession中断后播放异常求助

问题:来电中断后音频播放器重启仅播放0.3秒即被停用

我用Theos为iOS应用编写Tweak,通过后台播放静音WAV文件延长后台生命周期。但来电会中断音频播放,我编写了AVAudioSessionInterruptionNotification的处理逻辑后,播放器虽能重启,但仅播放约0.3秒就被停用。我添加了大量日志仍未定位原因,作为Tweak开发新手,希望解决该问题,同时了解可用的调试工具。怀疑应用内存在其他中断通知处理器,想要找出是谁停用了音频播放器,进而通过Hook或其他方式规避。


相关代码

// Register interruption handler
[[NSNotificationCenter defaultCenter]  addObserver:self  
                                          selector:@selector(audioSessionInterruption:)  
                                          name:AVAudioSessionInterruptionNotification  
                                          object:nil];

- (void)audioSessionInterruption:(NSNotification *)notification{
   NSNumber *interruptionType = [[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey];
   NSNumber *interruptionOption = [[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey];

   switch (interruptionType.unsignedIntegerValue) {
      case AVAudioSessionInterruptionTypeBegan:{
         NSLog(@"AVAudioSessionInterruptionTypeBegan");
      } break;
      case AVAudioSessionInterruptionTypeEnded:{
         if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
               // Here should continue playback. Active audio session and play
               // Unfortunately, the audio player playing less one second, and be deactived by something
               NSLog(@"AVAudioSessionInterruptionTypeEnded");
               [[AVAudioSession sharedInstance] setActive:YES error:nil];
               [self.audioPlayer play];
         }
      } break;
      default:
         break;
   }
}

日志信息

CAReportingClient.mm:508   message {API = "[AVAudioSession etActive:activate]";    ElapsedTime = "6.517041";}: (176093659500)
CAReportingClient.mm:508   message {API = "-[AVAudioSession ategory]";    ElapsedTime = "0.158375";}: (176093659500)
CAReportingClient.mm:508   message {API = "-[AVAudioSession privateSetCategoryWithOptions:modes:routeSharingPolicy:options:]";    ElapsedTime = "5.618958";}: (176093659500)
AVAudioSession_iOS.mm:1271  Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
CAReportingClient.mm:508   message {API = "[AVAudioSession setActive:deactivate]";    ElapsedTime = "656.548541";}: (176093659500)

问题排查与解决方案

1. 定位停用音频会话的调用方

用Theos的Logos语法HookAVAudioSession的setActive:error:方法,打印调用栈找出是谁触发了停用操作:

%hook AVAudioSession
- (BOOL)setActive:(BOOL)active error:(NSError **)error {
    BOOL result = %orig;
    if (!active) {
        NSLog(@"=== AVAudioSession setActive:NO 调用栈 ===");
        NSLog(@"%@", [NSThread callStackSymbols]);
    }
    return result;
}
%end

2. 检查应用内的其他中断通知观察者

HookNSNotificationCenter的添加观察者方法,捕获所有监听AVAudioSessionInterruptionNotification的对象,确认是否有其他处理器干扰:

%hook NSNotificationCenter
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject {
    if ([aName isEqualToString:AVAudioSessionInterruptionNotification]) {
        NSLog(@"=== 新增AVAudioSession中断通知观察者:%@,方法:%@ ===", observer, NSStringFromSelector(aSelector));
    }
    %orig;
}
%end

3. 修正音频会话激活逻辑

在恢复播放时不要忽略激活错误,同时确保播放器状态正常:

case AVAudioSessionInterruptionTypeEnded:{
    if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
        NSLog(@"AVAudioSessionInterruptionTypeEnded");
        NSError *error = nil;
        BOOL activateSuccess = [[AVAudioSession sharedInstance] setActive:YES error:&error];
        if (!activateSuccess) {
            NSLog(@"激活音频会话失败:%@", error);
        }
        if (!self.audioPlayer.isPlaying && self.audioPlayer.readyToPlay) {
            [self.audioPlayer play];
        }
    }
} break;

常用调试工具

  • Console.app/系统日志:用Mac的Console.app查看应用日志,或在终端执行log show --predicate 'process == "你的应用名"' --info过滤目标应用日志。
  • LLDB调试:通过Theos的debugserver连接设备,在LLDB中给AVAudioSession setActive:error:设置断点,实时查看调用栈。
  • Cycript:注入到应用进程后,执行[[NSNotificationCenter defaultCenter] observersForName:@"AVAudioSessionInterruptionNotification" object:nil]直接查看所有中断通知观察者。
  • Logos Hook:利用Theos的Logos语法快速Hook任意方法,打印参数、返回值和调用栈。

内容的提问来源于stack exchange,提问作者ARD7N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 06:00:00