mop-flutter-sdk/ios/Classes/FinAppletExt/Common/Manager/FATExtAVManager.m

196 lines
7.2 KiB
Dart

//
// FATExtAVManager.m
// FinAppletExt
//
// Created by Haley on 2020/8/14.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtAVManager.h"
#import "FATExtFileManager.h"
#import <AVFoundation/AVFoundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <FinApplet/FinApplet.h>
@interface FATExtAVManager () <AVAudioRecorderDelegate>
@property (nonatomic, strong) AVAudioRecorder *recorder;
@property (nonatomic, copy) FATExtAVSuccess recordSuccess;
@property (nonatomic, copy) FATExtAVFail recordFail;
@end
@implementation FATExtAVManager
+ (instancetype)sharedManager {
static id _sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[FATExtAVManager alloc] init];
[_sharedInstance add_notifications];
});
return _sharedInstance;
}
- (void)add_notifications {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appletPageDisappear:) name:kFATPageDidDisappearNotification object:nil];
}
- (void)appletPageDisappear:(NSNotification *)notification
{
if (self.recorder) {
[self.recorder pause];
if (self.recordFail) {
self.recordFail(@"fail");
}
[self.recorder deleteRecording];
self.recorder = nil;
// 胶囊按钮
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
}
}
/**
开始录音
@param success 成功回调
@param fail 失败回调
*/
- (void)startRecordWithSuccess:(FATExtAVSuccess)success fail:(FATExtAVFail)fail {
if ([self.recorder isRecording]) {
fail(@"正在录音中...");
return;
}
self.recordSuccess = success;
self.recordFail = fail;
self.recorder = [self createAudioRecord];
[self.recorder prepareToRecord];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL];
[audioSession setActive:YES error:NULL];
[self.recorder recordForDuration:60];
// 胶囊按钮
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateMicroPhone animate:YES];
}
}
/**
停止录音
*/
- (void)stopRecord {
if (self.recorder) {
[self.recorder stop];
self.recorder = nil;
// 胶囊按钮
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
}
}
- (void)checkRecordState {
if ([self.recorder isRecording]) {
// 胶囊按钮
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateMicroPhone animate:YES];
}
}
}
#pragma mark - private method
- (AVAudioRecorder *)createAudioRecord {
// 使用此配置 录制1分钟大小200KB左右
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithFloat:16000.0], AVSampleRateKey,
[NSNumber numberWithInt:1], AVNumberOfChannelsKey,
nil];
// 使用当前时间戳的md5作为文件名
NSString *currentDt = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]];
NSData *data = [currentDt dataUsingEncoding:NSUTF8StringEncoding];
NSString *nameMD5 = [self fat_md5WithBytes:(char *)[data bytes] length:data.length];
NSString *fileName = [NSString stringWithFormat:@"tmp_%@.m4a", nameMD5];
NSString *filePath = [[self tmpDir] stringByAppendingPathComponent:fileName];
AVAudioRecorder *recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:filePath] settings:settings error:nil];
recorder.delegate = self;
return recorder;
}
- (NSString *)tmpDir {
FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
NSString *cacheDir = [FATExtFileManager appTempDirPath:appInfo.appId];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL flag = YES;
if (![fileManager fileExistsAtPath:cacheDir isDirectory:&flag]) {
[fileManager createDirectoryAtPath:cacheDir withIntermediateDirectories:YES attributes:nil error:nil];
}
return cacheDir;
}
- (NSString *)fat_md5WithBytes:(char *)bytes length:(NSUInteger)length {
unsigned char result[16];
CC_MD5(bytes, (CC_LONG)length, result);
return [NSString stringWithFormat:
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]];
}
#pragma mark - AVAudioRecord Delegate
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
NSString *filePath = recorder.url.lastPathComponent;
if (flag) {
if (self.recordSuccess) {
self.recordSuccess([@"finfile://" stringByAppendingString:filePath]);
}
} else {
[recorder deleteRecording];
if (self.recordFail) {
self.recordFail(@"fail");
}
}
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:NULL];
[audioSession setActive:YES error:NULL];
self.recorder = nil;
self.recordSuccess = nil;
self.recordFail = nil;
// 胶囊按钮
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
}
@end