[iOS]音视频呼叫时手机震动或者播放来电铃声

接入环信音视频聊天时,安卓的demo上有来电铃声功能而iOS的demo上并没提供此功能,所以就诞生了本文。
主要看文末的参考文章吧, 懒得重复去描述了。
GitHub:https://github.com/Gamin-fzym/GACallSoundDemo
Demo:https://download.csdn.net/download/u012881779/12084810
[ViewController]
接入铃声功能

#import "ViewController.h"
#import "RBDMuteSwitch.h"
#import "GAMsgBell.h"

@interface ViewController () <RBDMuteSwitchDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [[RBDMuteSwitch sharedInstance] setDelegate:self];
}

- (IBAction)callAction:(id)sender {
    // 检测”静音模式“是否开启
    [[RBDMuteSwitch sharedInstance] detectMuteSwitch];
}

- (IBAction)linkAction:(id)sender {
    GAMsgBell *bell = [GAMsgBell sharedMsgBellMethod];
    [bell stop];
}

#pragma mark - RBDMuteSwitchDelegate

- (void)isMuted:(BOOL)muted {
    if (muted) {
        // 当前是[静音模式]
        // 若在“设置-声音-开启了静音模式震动”手机才会震动,未开启静音模式震动时手机是静音的,这里就是设置了震动去播放仍然设备是静音的。
        NSLog(@"[静音模式]");
        GAMsgBell *bell = [GAMsgBell sharedMsgBellMethod];
        [bell setupSystemShake];
        [bell setupCompletion:soundCompleteCallback];
        [bell play];
    } else {
        // 当前是[响铃模式]
        NSLog(@"[响铃模式]");
        GAMsgBell *bell = [GAMsgBell sharedMsgBellMethod];
        [bell setupSystemSoundWithName:@"iphone6dx" SoundType:@"caf"];
        [bell setupCompletion:soundCompleteCallback];
        [bell play];
    }
}

/**
 *  播放完成回调函数
 *
 *  @param soundID    系统声音ID
 *  @param clientData 回调时传递的数据
 */
void soundCompleteCallback(SystemSoundID soundID, void * clientData) {
    NSLog(@"播放完成...");
    GAMsgBell *bell = [GAMsgBell sharedMsgBellMethod];
    [bell play];
}

@end

[GAMsgBell]
设置震动、系统声音或自定义声音,控制播放和停止。

#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import "RBDMuteSwitch.h"

@interface GAMsgBell : NSObject {
    SystemSoundID sound; // 系统声音的id 取值范围为:1000-2000
}

+ (id)sharedMsgBellMethod;

// 系统 震动
- (void)setupSystemShake;

// 初始化系统声音、自定义声音
- (void)setupSystemSoundWithName:(NSString *)soundName SoundType:(NSString *)soundType;

// 设置播放完成回调
- (void)setupCompletion:(AudioServicesSystemSoundCompletionProc)completeBlock;

// 停止回调、停止播放
- (void)stop;

// 播放
- (void)play;

@end
#import "GAMsgBell.h"

static GAMsgBell *sharedMsgBell = nil;

@implementation GAMsgBell

+ (id)sharedMsgBellMethod {
    @synchronized (self){
        if (!sharedMsgBell) {
            sharedMsgBell = [[GAMsgBell alloc] init];
        }
        return sharedMsgBell;
    }
    return sharedMsgBell;
}

- (void)setupSystemShake {
    [self stop];
    sound = kSystemSoundID_Vibrate; // 震动
}
 
- (void)setupSystemSoundWithName:(NSString *)soundName SoundType:(NSString *)soundType {
    [self stop];
    //NSString *path1 = [NSString stringWithFormat:@"/System/Library/Audio/UISounds/%@.%@",soundName,soundType];
    //NSString *path2 = [[NSBundle bundleWithIdentifier:@"com.apple.UIKit" ] pathForResource:soundName ofType:soundType];// 得到苹果框架资源UIKit.framework ,从中取出所要播放的系统声音的路径
    //[[NSBundle mainBundle] URLForResource:@"tap" withExtension: @"aif"]; //  获取自定义的声音
    NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:soundType];
    if (path) {
        OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path],&sound);
        if (error != kAudioServicesNoError) {
            // 获取的声音的时候,出现错误
            sound = nil;
        }
    }
}
 
- (void)setupCompletion:(AudioServicesSystemSoundCompletionProc)completeBlock {
    // 如果需要在播放完之后执行某些操作,可以调用如下方法注册一个播放完成回调函数
    AudioServicesAddSystemSoundCompletion(sound, NULL, NULL, completeBlock, NULL);
}

- (void)play {
    // 铃声静音仍然可播放声音
    // [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [audioSession setActive:YES error:nil];
    
    AudioServicesPlaySystemSound(sound);
}

- (void)stop {
    [[RBDMuteSwitch sharedInstance] stop];
    [self stopCompletion];
    [self stopPlay];
}

- (void)stopCompletion {
    AudioServicesRemoveSystemSoundCompletion(sound);
    AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
}

- (void)stopPlay {
    AudioServicesDisposeSystemSoundID(sound);
    AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);
}

@end

[RBDMuteSwitch]
监听iOS设备静音按钮的状态

#import <Foundation/Foundation.h>
#include <AudioToolbox/AudioToolbox.h>

@class RBDMuteSwitch;

@protocol RBDMuteSwitchDelegate
    @required
    - (void)isMuted:(BOOL)muted;
@end

@interface RBDMuteSwitch : NSObject {
    @private
    NSObject<RBDMuteSwitchDelegate> *delegate;
    float soundDuration;
    NSTimer *playbackTimer;
    SystemSoundID soundFileObject;
}

/**
 Your delegate
 */
@property (readwrite, retain) NSObject<RBDMuteSwitchDelegate> *delegate;

/** Creates a shared instance
 */
+ (RBDMuteSwitch *)sharedInstance;

/** Determines if the device is muted, wait for delegate callback using isMuted: on your delegate.
 */
- (void)detectMuteSwitch;

- (void)stop;

@end
#import "RBDMuteSwitch.h"

static RBDMuteSwitch *_sharedInstance;

@implementation RBDMuteSwitch

@synthesize delegate;

+ (RBDMuteSwitch *)sharedInstance {
    if (!_sharedInstance) {
        _sharedInstance = [[[self class] alloc] init];
    }
    return _sharedInstance;
}

- (id)init {
    self = [super init];
    if (self) {
    }
    return self;
}

- (void)playbackComplete {
    if ([(id)self.delegate respondsToSelector:@selector(isMuted:)]) {
        // NSLog(@"playbackComplete >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nsoundDuration    %f",soundDuration);
        // If playback is far less than 100ms then we know the device is muted
        if (soundDuration < 0.001) {
            [delegate isMuted:YES];
        } else {
             [delegate isMuted:NO];
        }
    }
    [playbackTimer invalidate];
    playbackTimer = nil;
}

static void soundCompletionCallback (SystemSoundID mySSID, void* myself) {
    AudioServicesRemoveSystemSoundCompletion (mySSID);
    AudioServicesDisposeSystemSoundID(mySSID);
    [[RBDMuteSwitch sharedInstance] playbackComplete];
}

- (void)stop {
    AudioServicesRemoveSystemSoundCompletion (soundFileObject);
    AudioServicesDisposeSystemSoundID(soundFileObject);
    if (playbackTimer) {
        [playbackTimer invalidate];
        playbackTimer = nil;
    }
}

- (void)incrementTimer {
    soundDuration = soundDuration + 0.001;
//    NSLog(@"incrementTimer>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nsoundDuration    %f",soundDuration);
}

- (void)detectMuteSwitch {
#if TARGET_IPHONE_SIMULATOR
    // The simulator doesn't support detection and can cause a crash so always return muted
    if ([(id)self.delegate respondsToSelector:@selector(isMuted:)]) {
        [self.delegate isMuted:YES];
    }
    return;
#endif
#if !TARGET_IPHONE_SIMULATOR
    // iOS 5+ doesn't allow mute switch detection using state length detection
    // So we need to play a blank 100ms file and detect the playback length
    soundDuration = 0.0;
    CFURLRef        soundFileURLRef;
    
    // Get the main bundle for the app
    CFBundleRef mainBundle;
    mainBundle = CFBundleGetMainBundle();
    
    // Get the URL to the sound file to play
    soundFileURLRef  =    CFBundleCopyResourceURL(
                                                mainBundle,
                                                CFSTR ("detection"),
                                                CFSTR ("aiff"),
                                                NULL
                                                );
    
    // Create a system sound object representing the sound file
    AudioServicesCreateSystemSoundID (soundFileURLRef,
                                      &soundFileObject
                                      );
    
    AudioServicesAddSystemSoundCompletion (soundFileObject,NULL,NULL,
                                           soundCompletionCallback,
                                           (void*) CFBridgingRetain(self));
    
    // Start the playback timer
    playbackTimer = [NSTimer scheduledTimerWithTimeInterval:0.010 target:self selector:@selector(incrementTimer) userInfo:nil repeats:YES];
//    NSLog(@"playbackTimer>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nsoundDuration    %f",soundDuration);
    // Play the sound
    AudioServicesPlaySystemSound(soundFileObject);
    return;
#endif
}

@end

TO:
iOS开发 AudioServices(音效播放)的使用
https://blog.csdn.net/wgl_happy/article/details/77452716
IOS成长之路-使用系统默认声音、震动
https://blog.csdn.net/like7xiaoben/article/details/9001806
如何监听iOS设备静音按钮的状态
https://www.jianshu.com/p/6db6065b6b3d
【iOS知识学习】_如何判断手机是否为静音模式
https://blog.csdn.net/weasleyqi/article/details/11593313
iOS检测手机是否为振动模式(非铃声模式)
https://blog.csdn.net/hanhailong18/article/details/88313733
iOS中声音播放的各种方法总结
https://www.jianshu.com/p/548afbe49e67
iOS 音频-AVAudioSession
https://www.jianshu.com/p/fb0e5fb71b3c

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值