设置后台播放模式
1:
2:在info 里面添加
Required background modes
App plays audio or streams audio/video using AirPlay
App downloads content in response to push notifications
代码
class MainTabBarController: UITabBarController //windo 的rootview,但是是没有导航栏的
//收到呼叫设备
@objc func receivedCallDevices(notifi: Notification) {
switch callState {
case .stateDefault:
if let list = notifi.object as? [DeviceInfo] {
deviceInfo = list.last
self.callState = .statetalking
if canTransition == true{
// performSegue(withIdentifier: "MainToPlayVC", sender: nil) //直接用persent playView第二次调起的时候会闪现
let sb = UIStoryboard.init(name: "Community", bundle: nil)
let playView = sb.instantiateViewController(withIdentifier: "PlayViewController") as! PlayViewController
playView.deviceInfo = deviceInfo
playView.callType = CallType.incoming
let nav = UINavigationController.init(rootViewController: playView)
self.present(nav, animated: true, completion: nil) // 给playView 一个UINavigationController,present这个UINavigationController,就不会闪现,palyView 被push出现第二次调起是么有出现闪现的,所以怀疑时 persent的不同引起。
}else{
return
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------
@interface PlayViewController ()
- (void)viewDidLoad {
[super viewDidLoad];
_dPlayManager = [DPlayManager manager];
_dPlayManager.delegate = self;
[self addNoti];
self.roomNameLabel.text = _deviceInfo.deviceName;
self.nowTimeLabel.text = [Utilities currentDateWithFormat:@"yyyy-MM-dd HH:mm:ss"];
// [self initButtons];
//有主线程堵塞
[_dPlayManager createPlayDevice:_deviceInfo viewType:ViewTypeRealtime isLan:[_isLan boolValue]];
[self initActivityView];
//开启摇动感应
UIApplication.sharedApplication.applicationSupportsShakeToEdit = true;
[self canBecomeFirstResponder];
UIApplication.sharedApplication.statusBarStyle = UIStatusBarStyleLightContent;
_isAccept = false;
}
//开始摇
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
AudioServicesPlaySystemSound(1109);
NSLog(@"开始摇动");
}
//取消摇动
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{
NSLog(@"取消摇动");
}
//摇动结束
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{
[_dPlayManager doControl];
NSLog(@"结束摇动");
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:nil];//更换模式,消除red statuBar persent
[self.navigationController.navigationBar setHidden:NO];
[self.navigationController.tabBarController.tabBar setHidden:NO];
self.navigationController.navigationBar.barStyle = UIBarStyleDefault;
UIApplication.sharedApplication.statusBarStyle = UIStatusBarStyleDefault;
[_dPlayManager realtimeStop:2];
[_dPlayManager realtimeStop:1];
[_dPlayManager realtimeStop:4];
[[RingManager shareManager] stopRing];
}
- (void)dealloc{
[_dPlayManager destoryPlayDevice];
_dPlayManager.delegate = nil;
[self removeNoti];
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//打开免提,这里要先设置category,之后再设置switch里面的,音视频,否则麦克风调不起
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
[self.navigationController.navigationBar setHidden:YES];
[self.navigationController.tabBarController.tabBar setHidden:YES];
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
UIApplication.sharedApplication.statusBarStyle = UIStatusBarStyleLightContent;
switch (self.callType) {
case CallTypeIncoming:
[[RingManager shareManager] playRing];
[_dPlayManager realtimePlay:2];
[self.hundUpButton setHidden:YES];
[self.btnTalkOpen setHidden:YES];
[self updateButtonsViewFrameWithSubViewCount:2];
break;
case CallTypeOutCalling:
//视频,一般管理处是没有视频的
[_dPlayManager realtimePlay:2];
//音频
[_dPlayManager realtimePlay:1];
// [self onHandsFreeButton:self.hundUpButton];
//对讲
[_dPlayManager realtimePlay:4];
[[RingManager shareManager] stopRing];
[self.acceptButton setHidden:YES];
[self.rightHundUpButton setHidden:YES];
[self.hundUpButton setHidden:NO];
//四个操作按钮直接隐藏,打开对讲
self.buttonsView.hidden = YES;
self.hundUpButton.imageView.image = [UIImage imageNamed:@"spmj_icon_default_fuangduan"];//修改了selected,图片显示反了,这里修正过来
//关闭摇一摇开门功能
_yao_yaoLabel.text = @"";
UIApplication.sharedApplication.applicationSupportsShakeToEdit = false;
[self canResignFirstResponder];
[self.activityIndicator startAnimating];
break;
case CallTypeMonitoring:
[_dPlayManager realtimePlay:1];
[_dPlayManager realtimePlay:2];
[self btnAudioAction:self.btnAudioOpen];
[self.handsFreeButton setSelected:YES];
[self.acceptButton setHidden:YES];
[self.rightHundUpButton setHidden:YES];
[self updateButtonsViewFrameWithSubViewCount:3];
[self.activityIndicator startAnimating];
break;
default:
break;
}
}
-(void) initActivityView{
self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleWhiteLarge)];
[self.view addSubview:self.activityIndicator];
self.activityIndicator.backgroundColor = [UIColor clearColor];
//设置小菊花颜色
self.activityIndicator.color = [UIColor whiteColor];
self.activityIndicator.layer.cornerRadius = 5.0;
//刚进入这个界面会显示控件,并且停止旋转也会显示,只是没有在转动而已,没有设置或者设置为YES的时候,刚进入页面不会显示
self.activityIndicator.hidesWhenStopped = NO;
}
//
-(void) updateViewConstraints{
_playImageView.translatesAutoresizingMaskIntoConstraints = NO;
[_playImageView addConstraint:[NSLayoutConstraint constraintWithItem:_playImageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.view.frame.size.width]];
[_playImageView addConstraint:[NSLayoutConstraint constraintWithItem:_playImageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_playImageView attribute:NSLayoutAttributeWidth multiplier:0.627 constant:0]]; //0.627=(235/375)
[super updateViewConstraints];
//在视频页面转动,这里需要调整,在self.view中转动不用调整,width 用self.view.frame.size.width/2,用self.playImageView.frame.size不能动态匹配
self.activityIndicator.frame= CGRectMake((self.view.frame.size.width/2)-40,(self.playImageView.frame.size.height/2)-40+54 , 80, 80);
}
#pragma mark - Notification
- (void)addNoti{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismiss) name:@"HeieJiaIncomingCall" object:nil];
}
- (void)removeNoti{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"HeieJiaIncomingCall" object:nil];
}
- (IBAction)btnVideoAction:(id)sender {
// 打开视频
if (![sender isSelected])
[_dPlayManager realtimePlay:2];
// 关闭视频
else
[_dPlayManager realtimeStop:2];
[sender setSelected:![sender isSelected]];
}
- (IBAction)btnAudioAction:(id)sender {
// 打开音频
if (![sender isSelected])
[_dPlayManager realtimePlay:1];
// 关闭音频
else {
[_dPlayManager realtimeStop:1];
if (_btnTalkOpen.isSelected)
[self btnTalkAction:_btnTalkOpen];
}
[sender setSelected:![sender isSelected]];
}
- (IBAction)btnTalkAction:(id)sender {
// 打开对讲
if (![sender isSelected])
[_dPlayManager realtimePlay:4];
// 关闭对讲
else
[_dPlayManager realtimeStop:4];
[sender setSelected:![sender isSelected]];
}
- (IBAction)btnUnlockAction:(id)sender {
[_dPlayManager doControl];
}
- (IBAction)onHandsFreeButton:(UIButton *)sender {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
if (sender.isSelected == YES) {
[sender setSelected:!sender.isSelected];
//关闭免提
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDuckOthers error:nil];
// [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil]; //这种无效
}else{
[sender setSelected:!sender.isSelected];
//打开免提
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
// [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil]; //这种无效
}
}
- (IBAction)getPicture:(UIButton *)sender {
[self saveToThumb];
}
- (IBAction)onHungUpButton:(UIButton *)sender {
[[RingManager shareManager] stopRing];
self.hundUpButton.imageView.image = [UIImage imageNamed:@"pressed_fuangduan"];//修改了selected,图片显示反了,这里修正过来
[self dismiss];
}
- (IBAction)onAcceptButton:(UIButton *)sender {
[self btnAudioAction:self.btnAudioOpen];
[self onHandsFreeButton:self.hundUpButton];
[self.handsFreeButton setSelected:YES];
[self btnTalkAction:self.btnTalkOpen];
[[RingManager shareManager] stopRing];
[UIView animateWithDuration:.25 animations:^{
[self.acceptButton setHidden:YES];
[self.rightHundUpButton setHidden:YES];
[self.hundUpButton setHidden:NO];
[self updateButtonsViewFrameWithSubViewCount:3];
self.hundUpButton.imageView.image = [UIImage imageNamed:@"spmj_icon_default_fuangduan"];//修改了selected,图片显示反了,这里修正过来
}];
_isAccept = true;
}
#pragma mark - init
- (void)initButtons{
[self adjustTitleAndImageFrameForInButton:self.openDoorButton];
[self adjustTitleAndImageFrameForInButton:self.handsFreeButton];
[self adjustTitleAndImageFrameForInButton:self.btnTalkOpen];
[self adjustTitleAndImageFrameForInButton:self.takePictures];
[self adjustTitleAndImageFrameForInButton:self.hundUpButton];
}
#pragma mark - private Methods
- (void)adjustTitleAndImageFrameForInButton:(UIButton*)button{
// [button setImageEdgeInsets:UIEdgeInsetsMake(-button.currentImage.size.height, 0, 0, -button.titleLabel.intrinsicContentSize.width)];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, -button.currentImage.size.width, -button.titleLabel.intrinsicContentSize.height - button.frame.size.height-10, 0)];
}
- (void)dismiss{
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
// [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:nil];//更换模式,消除red statuBar persent
[[NSNotificationCenter defaultCenter] postNotificationName:@"HeieJiaHungUpCall" object:nil];
switch (self.callType) {
case CallTypeMonitoring:
{
// MainTabBarController* mainVC = (MainTabBarController*)self.navigationController.topViewController.tabBarController;
// mainVC.callState = CallStateDefault;
[self.navigationController popViewControllerAnimated:YES];
}
break;
case CallTypeIncoming:
{
// MainTabBarController* mainVC = (MainTabBarController*)self.presentingViewController.tabBarController;
// mainVC.callState = CallStateDefault;
// [self.navigationController popViewControllerAnimated:YES];
if (_isAccept == false) {
[self performSelector:@selector(dismissViewController) withObject:nil afterDelay:0.3];
}else{
//发送挂断指令
[self performSelector:@selector(dismissViewController) withObject:nil afterDelay:0.3];
[self sendHangupInfo];
}
}
break;
case CallTypeOutCalling:
{
// MainTabBarController* mainVC = (MainTabBarController*)self.navigationController.topViewController.presentingViewController.tabBarController;
// mainVC.callState = CallStateDefault;
[self performSelector:@selector(dismisstopViewController) withObject:nil afterDelay:0.3];
}
break;
}
}
-(void)dismissViewController{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)dismisstopViewController{
// [self.navigationController.topViewController dismissViewControllerAnimated:YES completion:nil];
NSArray *arr = [NSArray arrayWithArray:self.navigationController.childViewControllers];
for (UIViewController *vc in arr) {
if ([[vc class] isSubclassOfClass:[CommunityViewController class]]) {
[self.navigationController popToViewController:vc animated:NO];
}
}
}
/**
更新buttonsView的frame
@param subViewCount 子视图的个数
*/
- (void)updateButtonsViewFrameWithSubViewCount:(NSInteger)subViewCount{
CGFloat space = 8;
CGFloat buttonsViewWidth = Main_Screen_Width - 16*2;
CGFloat buttonHeight = (buttonsViewWidth - space*(subViewCount-1))/subViewCount;
self.buttonsView.spacing = space;
self.buttonsViewWidthLayoutConstraint.constant = buttonsViewWidth;
self.buttonsViewHeightLayoutConstraint.constant = buttonHeight;
}
//保存到相册
- (void)saveToThumb{
UIImageWriteToSavedPhotosAlbum(_playImageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
AudioServicesPlaySystemSound (1108);//播放拍照声音
}
-(void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
NSString *msg = nil ;
if(error){
msg = NSLocalizedString(@"saveImageFailer", nil) ;
}else{
msg = NSLocalizedString(@"saveImageOK", nil) ;
}
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"保存图片结果提示" message:msg delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
// [alert show];
// 实现提示,自定义Alert
[MyAlertLabel initWithSize:CGSizeMake(150, 35) andMessage:msg andViewController:self];
}
//发送挂断来电信息
-(void) sendHangupInfo{
NSString * strId = _deviceInfo.serialNo;
if (strId != nil) {
[NetworkAPI hangupCallWithServer:NetworkConstants.server cameraID:strId callback:^(id _Nullable obj) {
if (obj == nil) {
// [self performSelector:@selector(dismissViewController) withObject:nil afterDelay:0.3];
return ;
}
if ([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary* dic = (NSDictionary*)obj;
NSInteger resCode = [[dic objectForKey:@"resCode"] integerValue];
BOOL isHaveZone = NO;
switch (resCode) {
case 0:
DDLogDebug(@"发送挂断来电信息 成功");
isHaveZone = YES;
break;
default:
DDLogDebug(@"发送挂断来电信息 失败");
break;
}
// [self performSelector:@selector(dismissViewController) withObject:nil afterDelay:0.3];
}
}];
}
}