Pārlūkot izejas kodu

录播权限获取前置

Steven 4 gadi atpakaļ
vecāks
revīzija
e1d39e00cf

+ 4 - 4
MusicGradeExam/MusicGradeExam.xcodeproj/project.pbxproj

@@ -3576,7 +3576,7 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_ENTITLEMENTS = "MusicGradeExam/酷乐秀.entitlements";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1.3.0;
+				CURRENT_PROJECT_VERSION = 1.4.0;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = P664H7S5LL;
 				ENABLE_BITCODE = NO;
@@ -3598,7 +3598,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/MusicGradeExam/RongCloud/IMLib",
 				);
-				MARKETING_VERSION = 1.3.0;
+				MARKETING_VERSION = 1.4.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.JMCloudMusic.MusicGradeExam;
 				PRODUCT_NAME = "酷乐秀";
 				TARGETED_DEVICE_FAMILY = "1,2";
@@ -3612,7 +3612,7 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_ENTITLEMENTS = "MusicGradeExam/酷乐秀.entitlements";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1.3.0;
+				CURRENT_PROJECT_VERSION = 1.4.0;
 				DEVELOPMENT_TEAM = P664H7S5LL;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -3633,7 +3633,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/MusicGradeExam/RongCloud/IMLib",
 				);
-				MARKETING_VERSION = 1.3.0;
+				MARKETING_VERSION = 1.4.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.JMCloudMusic.MusicGradeExam;
 				PRODUCT_NAME = "酷乐秀";
 				TARGETED_DEVICE_FAMILY = "1,2";

+ 10 - 10
MusicGradeExam/MusicGradeExam/Define/PrefixHeader.pch

@@ -85,11 +85,11 @@
 
 //#ifdef DEBUG
 
-//#define hostURL (@"https://test.kj.colexiu.com")
-//#define SEALCLASSHOST (@"https://test.kj.colexiu.com/api-im")
-//#define WEBHOST (@"https://test.m.kj.colexiu.com")
-//#define JSPUSH_ENVIRONMENT (NO)
-//#define RCIM_KEY (@"mgb7ka1nme0yg")
+#define hostURL (@"https://test.kj.colexiu.com")
+#define SEALCLASSHOST (@"https://test.kj.colexiu.com/api-im")
+#define WEBHOST (@"https://test.m.kj.colexiu.com")
+#define JSPUSH_ENVIRONMENT (NO)
+#define RCIM_KEY (@"mgb7ka1nme0yg")
 
 //#define hostURL (@"http://192.168.3.28:8000")
 //#define SEALCLASSHOST (@"http://192.168.3.28:8000/api-im")
@@ -105,11 +105,11 @@
 
 //#else    // 线上
 
-#define hostURL (@"https://kj.colexiu.com")
-#define SEALCLASSHOST (@"https://kj.colexiu.com/api-im")
-#define WEBHOST (@"https://m.kj.colexiu.com")
-#define JSPUSH_ENVIRONMENT (YES)
-#define RCIM_KEY (@"8w7jv4qb8zuyy")
+//#define hostURL (@"https://kj.colexiu.com")
+//#define SEALCLASSHOST (@"https://kj.colexiu.com/api-im")
+//#define WEBHOST (@"https://m.kj.colexiu.com")
+//#define JSPUSH_ENVIRONMENT (YES)
+//#define RCIM_KEY (@"8w7jv4qb8zuyy")
 
 //#endif
 

+ 9 - 0
MusicGradeExam/MusicGradeExam/KSRequestManager.h

@@ -65,7 +65,16 @@ NS_ASSUME_NONNULL_BEGIN
  @param faliure 失败
  */
 + (void)videoFileUpload:(NSString *)post fileData:(NSData *)fileData progress:(void(^)(int64_t bytesWritten,int64_t totalBytes))progress success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+/**
+ 多视频文件上传
 
+ @param post post
+ @param fileDataArray 文件data
+ @param progress 进度
+ @param success 成功
+ @param faliure 失败
+ */
++ (void)mutiVideoFileUpload:(NSString *)post fileDataArray:(NSArray *)fileDataArray progress:(void(^)(int64_t bytesWritten,int64_t totalBytes))progress success:(void(^)(NSArray *dics))success faliure:(void(^)(NSError *error))faliure;
 
 #pragma mark ---- 文件下载
 // 单文件下载

+ 20 - 2
MusicGradeExam/MusicGradeExam/KSRequestManager.m

@@ -187,13 +187,16 @@
                                 type:(NSString *)type
                                 name:(NSString *)name
                             mimeType:(NSString *)mimeType
-                            progress:(void(^)(NSProgress * _Nonnull uploadProgress))progress
+                            progress:(void(^)(int64_t bytesWritten,
+                                              int64_t totalBytes))progress
                              success:(void(^)(NSMutableArray *dics))success
                              faliure:(void(^)(NSError *error))faliure {
     
     __block NSMutableArray *dics = [NSMutableArray array];
     [[KSNetworking shareManager] uploadMultFileWithUrl:myUrl parameters:parameters fileDatas:datas type:type name:name mimeType:mimeType progressBlock:^(int64_t bytesWritten, int64_t totalBytes) {
-        
+        if (progress) {
+            progress(bytesWritten, totalBytes);
+        }
     } successBlock:^(NSArray *responses) {
         for (id response in responses) {
             NSDictionary *subDic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
@@ -332,6 +335,21 @@
     [self uploadFileWithFileData:fileData andWithUrl:url parameters:nil type:@".mp4" name:@"file" mimeType:[NSString stringWithFormat:@"Image/.mp4"] progress:progress success:success faliure:faliure];
 }
 
+/**
+ 多视频文件上传
+
+ @param post post
+ @param fileDataArray 文件data
+ @param progress 进度
+ @param success 成功
+ @param faliure 失败
+ */
++ (void)mutiVideoFileUpload:(NSString *)post fileDataArray:(NSArray *)fileDataArray progress:(void(^)(int64_t bytesWritten,int64_t totalBytes))progress success:(void(^)(NSArray *dics))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString* url = [NSString stringWithFormat:@"%@%@",hostURL,@"/api-student/uploadFile"];
+    [self uploadMultiFileWithFileArray:fileDataArray andWithUrl:url parameters:nil type:@".mp4" name:@"file" mimeType:[NSString stringWithFormat:@"Image/.mp4"] progress:progress success:success faliure:faliure];
+}
+
 #pragma mark ---- 文件下载
 + (void)downloadFileRequestWithFileUrl:(NSString *)url progress:(void (^)(int64_t, int64_t))progress success:(void (^)(NSURL * _Nonnull))success faliure:(void (^)(NSError * _Nonnull))faliure {
     [self downloadTaskWithUrl:url progress:progress success:success faliure:faliure];

+ 1 - 0
MusicGradeExam/MusicGradeExam/Tools/Custom/KSMediaManager.m

@@ -407,6 +407,7 @@
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#pragma clang diagnostic ignored "-Wdeprecated-implementations"
 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
     if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

+ 1 - 0
MusicGradeExam/MusicGradeExam/UI/Classroom/View/TitleView/ClassTitleView.m

@@ -417,6 +417,7 @@
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#pragma clang diagnostic ignored "-Wdeprecated-implementations"
 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
     if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

+ 4 - 0
MusicGradeExam/MusicGradeExam/UI/Exam/Controller/WaitExamViewController.m

@@ -52,6 +52,8 @@
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
         RecordExamViewController *ctrl = [[RecordExamViewController alloc] init];
         ctrl.examRegistrationId = self.examRegistrationId;
+        ctrl.subjectName = self.sourceModel.subjectName;
+        ctrl.leverName = [self.bodyView getLevelName:self.sourceModel.level];
         [self.navigationController pushViewController:ctrl animated:YES];
     });
 }
@@ -293,6 +295,8 @@
                         RecordExamViewController *ctrl = [[RecordExamViewController alloc] init];
                         ctrl.examRegistrationId = self.examRegistrationId;
                         ctrl.sourceModel = sourceModel;
+                        ctrl.subjectName = self.sourceModel.subjectName;
+                        ctrl.leverName = [self.bodyView getLevelName:self.sourceModel.level];
                         [self.navigationController pushViewController:ctrl animated:YES];
                     }
                     else {

+ 1 - 0
MusicGradeExam/MusicGradeExam/UI/Exam/View/WaitExamBodyView.h

@@ -35,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (void)operationCallback:(JoinRoomAction)callback;
 
+- (NSString *)getLevelName:(NSUInteger)level;
 @end
 
 NS_ASSUME_NONNULL_END

+ 0 - 3
MusicGradeExam/MusicGradeExam/UI/Home/SimulationExam/Controller/SimulationExamRecordController.m

@@ -11,7 +11,6 @@
 #import "RecordListCell.h"
 #import "RecordBottomView.h"
 #import "RecordTipsView.h"
-#import "KSMediaManager.h"
 #import "WMPlayer.h"
 #import "SongModel.h"
 #import "KSGuideMaskView.h"
@@ -38,8 +37,6 @@
 
 @property (nonatomic, strong) NSMutableArray *songArray;
 
-@property (nonatomic, strong) KSMediaManager *mediaManager;
-
 @property (strong, nonatomic) MBProgressHUD *HUD;
 
 @property (nonatomic, strong) NSMutableArray *fileUrlArray;

+ 42 - 1
MusicGradeExam/MusicGradeExam/UI/RecordAction/KSVideoRecordViewController.m

@@ -15,7 +15,7 @@
 #import "SubjectImageModel.h"
 #import "TZImageManager.h"
 
-@interface KSVideoRecordViewController ()<AVCaptureFileOutputRecordingDelegate>
+@interface KSVideoRecordViewController ()<AVCaptureFileOutputRecordingDelegate,UIAlertViewDelegate>
 
 @property (nonatomic, strong) AVAudioPlayer *audioPlayer;
 
@@ -118,8 +118,39 @@
     [UIDevice switchNewOrientation:UIInterfaceOrientationLandscapeRight];
     [self configUI];
     [self.timer setFireDate:[NSDate distantPast]];
+    [self checkAuthStatus];
 }
 
+// 权限检测
+- (void)checkAuthStatus {
+    
+    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+    if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) && IS_IOS7_OR_LATER) {
+        // 无权限 做一个友好的提示
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
+        [alert show];
+#define push clang diagnostic pop
+    }
+    else if (authStatus == AVAuthorizationStatusNotDetermined) {
+        // 防止用户首次拍照拒绝授权时相机页黑屏
+        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
+
+        }];
+        
+    }
+    if ([PHPhotoLibrary authorizationStatus] == 2) { // 已被拒绝,没有相册权限,将无法保存拍的照片
+        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法访问相册" message:@"请在iPhone的""设置-隐私-相册""中允许访问相册" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
+        [alert show];
+    }
+    else if ([PHPhotoLibrary authorizationStatus] == 0) { // 未请求过相册权限
+        [[TZImageManager manager] requestAuthorizationWithCompletion:^{
+        }];
+    }
+}
+
+
 - (void)configMessage {
     self.prepareTime = 10;
     self.currentRecordIndex = 0;
@@ -677,7 +708,17 @@
     }];
 }
 
+#pragma mark - UIAlertViewDelegate
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#pragma clang diagnostic ignored "-Wdeprecated-implementations"
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
+    if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
+        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
+    }
+}
+#define push clang diagnostic pop
 /*
 #pragma mark - Navigation
 

+ 4 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/Controller/RecordExamViewController.h

@@ -17,6 +17,10 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, strong) RecordExamModel *sourceModel;
 
+@property (nonatomic, strong) NSString *subjectName;
+
+@property (nonatomic, strong) NSString *leverName;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 100 - 16
MusicGradeExam/MusicGradeExam/UI/RecordExam/Controller/RecordExamViewController.m

@@ -11,11 +11,12 @@
 #import "RecordListCell.h"
 #import "RecordBottomView.h"
 #import "RecordTipsView.h"
-#import "KSMediaManager.h"
 #import "WMPlayer.h"
 #import "SongModel.h"
 #import "KSGuideMaskView.h"
 #import "KSNormalAlertView.h"
+#import "KSVideoRecordViewController.h"
+#import "TZImageManager.h"
 
 @interface RecordExamViewController ()<UITableViewDelegate, UITableViewDataSource,WMPlayerDelegate>
 {
@@ -36,8 +37,6 @@
 
 @property (nonatomic, strong) NSMutableArray *songArray;
 
-@property (nonatomic, strong) KSMediaManager *mediaManager;
-
 @property (strong, nonatomic) MBProgressHUD *HUD;
 
 @property (nonatomic, strong) NSMutableArray *fileUrlArray;
@@ -179,31 +178,75 @@
     RecordListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"RecordListCell"];
     MJWeakSelf;
     [cell configCellWithSource:model examRegistrationId:self.examRegistrationId operationCallback:^(RECORDTYPE type, NSString *fileKey) {
-        [weakSelf opreationCellType:type fileKey:fileKey];
+        [weakSelf opreationCellType:type fileKey:fileKey index:indexPath.row];
     }];
     return cell;
 }
 
-- (void)opreationCellType:(RECORDTYPE)type fileKey:(NSString *)fileKey {
+- (void)opreationCellType:(RECORDTYPE)type fileKey:(NSString *)fileKey index:(NSInteger)cellIndex {
     if (type == RECORDTYPE_RECORD) { // 录像
-        self.mediaManager = [[KSMediaManager alloc] init];
-        self.mediaManager.mediaType = MEDIATYPE_VIDEO;
-        self.mediaManager.maxPhotoNumber = 1;
-        self.mediaManager.baseCtrl = self;
-        self.mediaManager.maxDuration = self.sourceModel.singleSongRecordMinutes * 60;
-        MJWeakSelf;
-        [self.mediaManager noAlertCallback:^(NSString * _Nullable videoUrl, NSMutableArray * _Nullable imageArray, NSMutableArray * _Nullable imageAsset) {
-            NSLog(@"%@", videoUrl);
-            // 上传视频
-            [weakSelf uploadVideoWithUrl:videoUrl fileKey:fileKey];
+        NSMutableArray *songNameArray = [NSMutableArray array];
+        for (NSInteger i = 0; i < self.songArray.count; i++) {
+            if (i >= cellIndex) {
+                // 从选择的开始->后面未录制的添加到待录制里
+                SongModel *model = self.songArray[i];
+                NSString *fileKey = [NSString stringWithFormat:@"%@%@", self.examRegistrationId, model.songName];
+                NSDictionary *fileMessage = UserDefault(fileKey);
+                if (fileMessage == nil) {
+                    [songNameArray addObject:model.songName];
+                }
+
+            }
+        }
+        KSVideoRecordViewController *recordCtrl = [[KSVideoRecordViewController alloc] init];
+        recordCtrl.subjectName = self.subjectName;
+        recordCtrl.leverName = self.leverName;
+        recordCtrl.songMessageArray = songNameArray;
+        recordCtrl.singleSongRecordMinutes = self.sourceModel.singleSongRecordMinutes;
+        [recordCtrl configTime:self.topView.duration recordFinishBlock:^(VIDEORECORDACTION action, NSMutableArray *videoArray) {
+            [self uploadVideoWithVideoArray:videoArray songArray:songNameArray];
         }];
-        [self.mediaManager takePhoto];
+        recordCtrl.modalPresentationStyle = UIModalPresentationFullScreen;
+        [self presentViewController:recordCtrl animated:YES completion:nil];
+        
     }
     else { // 删除
         [self deleteFileWithKey:fileKey];
     }
 }
 
+- (void)uploadVideoWithVideoArray:(NSMutableArray *)videoArray songArray:(NSArray *)songArray {
+    dispatch_main_async_safe(^{
+        [MBProgressHUD ksShowHUDWithText:@"视频处理中..."];
+    });
+    NSMutableArray *urlArray = [NSMutableArray array];
+    NSMutableArray *fileKeyArray = [NSMutableArray array];
+    MJWeakSelf;
+    for (NSInteger index = 0 ;index < videoArray.count; index++) {
+        PHAsset *assset = videoArray[index];
+        [[TZImageManager manager] getVideoOutputPathWithAsset:assset presetName:AVAssetExportPresetMediumQuality success:^(NSString *outputPath) {
+            NSLog(@"视频导出到本地完成,沙盒路径为:%@",outputPath);
+            NSData *outputData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:outputPath]]; //压缩后的视频
+            NSLog(@"导出后的视频:%@",[NSString stringWithFormat:@"%.2fM",(CGFloat)outputData.length/(1024*1024)]);
+            NSString *fileKey = [NSString stringWithFormat:@"%@%@", self.examRegistrationId, songArray[index]];
+            [urlArray addObject:outputPath];
+            [fileKeyArray addObject:fileKey];
+            if (index == videoArray.count - 1) {
+                [MBProgressHUD ksHideHUD];
+                // 批量上传
+                [weakSelf mutilUploadVideoWithUrl:urlArray fileKeyArray:fileKeyArray];
+            }
+            
+        } failure:^(NSString *errorMessage, NSError *error) {
+            dispatch_main_async_safe(^{
+                [MBProgressHUD ksShowMessage:@"视频导出失败"];
+                [MBProgressHUD ksHideHUD];
+            });
+        }];
+    }
+    
+}
+
 - (void)deleteFileWithKey:(NSString *)fileKey {
     NSDictionary *parm = UserDefault(fileKey);
     NSString *localUrl = [parm stringValueForKey:@"localFileUrl"];
@@ -365,6 +408,47 @@
 }
 
 #pragma mark ------ 上传视频文件
+- (void)mutilUploadVideoWithUrl:(NSMutableArray *)videoUrlArray fileKeyArray:(NSMutableArray *)fileKeyArray {
+    [self hudTipWillShow:YES];
+    NSMutableArray *fileDataArray = [NSMutableArray array];
+    for (NSString *videoUrl in videoUrlArray) {
+        [fileDataArray addObject:[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoUrl]]];
+    }
+    [KSRequestManager mutiVideoFileUpload:KS_POST fileDataArray:fileDataArray progress:^(int64_t bytesWritten, int64_t totalBytes) {
+        dispatch_main_async_safe(^{
+            // 显示进度
+            if (self.HUD) {
+                self.HUD.progress = bytesWritten / totalBytes;// progress是回调进度
+            }
+        });
+        
+    } success:^(NSArray * _Nonnull dics) {
+        [self hudTipWillShow:NO];
+        for (NSInteger index = 0; index < dics.count; index++) {
+            NSDictionary *dic = [dics objectAtIndex:index];
+            if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+                NSString *fileUrl = [[dic dictionaryValueForKey:@"data"] stringValueForKey:@"url"];
+                NSString *fileName = [[fileUrl componentsSeparatedByString:@"/"] lastObject];
+                NSString *videoUrl = [fileDataArray objectAtIndex:index];
+                NSString *fileKey = [fileKeyArray objectAtIndex:index];
+                // 保存文件路径
+                NSDictionary *parm = @{@"localFileUrl":videoUrl,
+                                       @"remoteUrl":fileUrl,
+                                       @"fileName": fileName};
+                UserDefaultSet(parm, fileKey);
+                [self.fileUrlArray addObject:fileUrl];
+                [self checkSubmitButtonEnable];
+            }
+            else {
+                [self MBPShow:MESSAGEKEY];
+            }
+        }
+        [self.tableView reloadData];
+        
+    } faliure:^(NSError * _Nonnull error) {
+        [self hudTipWillShow:NO];
+    }];
+}
 
 - (void)uploadVideoWithUrl:(NSString *)videoUrl fileKey:(NSString *)fileKey {
     [self hudTipWillShow:YES];