OralCavityManager.m 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. //
  2. // OralCavityManager.m
  3. // OralCavityFramework
  4. //
  5. // Created by ss on 2024/8/30.
  6. //
  7. #import "OralCavityManager.h"
  8. //#import <UIKit/UIKit.h>
  9. #import <Photos/Photos.h>
  10. #import <MobileCoreServices/MobileCoreServices.h>
  11. #import <AVFoundation/AVFoundation.h>
  12. #import "cf680SDK.h"
  13. #import "AAPLEAGLLayerCustom.h"
  14. #define WeakSelf __weak typeof(self) weakSelf = self;
  15. #define kSCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
  16. #define kSCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
  17. @interface OralCavityManager ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
  18. @property (nonatomic, strong) cf680SDK *sdk;
  19. @property (nonatomic, strong) UIView *videoView;
  20. @property (nonatomic, strong) AAPLEAGLLayerCustom *bfLayer;
  21. @property (nonatomic, copy) NSString *imageName;
  22. @property (nonatomic, copy) NSString *recordName;
  23. @property (nonatomic, assign) int connect;
  24. @end
  25. @implementation OralCavityManager
  26. + (instancetype)sharedInstance {
  27. static OralCavityManager *sharedInstance = nil;
  28. static dispatch_once_t onceToken;
  29. dispatch_once(&onceToken, ^{
  30. sharedInstance = [[self alloc] init];
  31. // [sharedInstance startVideo];
  32. });
  33. return sharedInstance;
  34. }
  35. - (cf680SDK *)sdk {
  36. WeakSelf;
  37. dispatch_async(dispatch_get_main_queue(), ^{
  38. if (!weakSelf.sdk) {
  39. //初始化视频view
  40. UIView *videoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kSCREEN_WIDTH, kSCREEN_WIDTH * 9 / 16)];
  41. weakSelf.videoView = videoView;
  42. weakSelf.sdk = [[cf680SDK alloc] init];
  43. //设置view w/h = 16 / 9
  44. [weakSelf.sdk SetVideoRect:weakSelf.videoView.frame viewlay:weakSelf.videoView.layer];
  45. [weakSelf.sdk SetVideoFullScreenRect:CGRectMake(0, 0, 16 / 9 * kSCREEN_HEIGHT, kSCREEN_HEIGHT)];
  46. [weakSelf.sdk ShowVideoRect:NO];
  47. static NSString *const notificationName = @"cf680SDK";
  48. NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
  49. [defaultCenter addObserver:weakSelf selector:@selector(handleNotification:) name:notificationName object:nil];
  50. NSString *filepath = [weakSelf MakeJPGFold:@"jpgimage"];
  51. const char *jpgfold = [filepath UTF8String];
  52. [weakSelf.sdk SetCapturePath:(char *)jpgfold];
  53. [[UIApplication sharedApplication] setIdleTimerDisabled: YES];
  54. //初始化相册名字
  55. weakSelf.imageName = @"";
  56. weakSelf.recordName = @"";
  57. // //获取pixelBuffer
  58. // _bfLayer = _videoView.layer.sublayers[0];
  59. // // 定时器,用于定时获取帧数据
  60. // CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkCallback:)];
  61. // [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
  62. if (weakSelf.getVideoView) {
  63. // self.getVideoView(weakSelf.videoView);
  64. weakSelf.getVideoView(weakSelf.videoView.layer.sublayers[0]);
  65. }
  66. //申请相册权限
  67. /*if (@available(iOS 14, *)) {
  68. [PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelReadWrite handler:^(PHAuthorizationStatus status) {
  69. dispatch_async(dispatch_get_main_queue(), ^{
  70. if (status == PHAuthorizationStatusLimited) {
  71. NSLog(@"status == %ld",(long)status);
  72. }
  73. else if (status == PHAuthorizationStatusDenied ||
  74. status == PHAuthorizationStatusRestricted){
  75. NSLog(@"status == %ld",(long)status);
  76. }
  77. else if(status == PHAuthorizationStatusAuthorized){
  78. NSLog(@"status == %ld",(long)status);
  79. }
  80. });
  81. }];
  82. }
  83. else {
  84. [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
  85. dispatch_async(dispatch_get_main_queue(), ^{
  86. if (status == PHAuthorizationStatusDenied ||
  87. status == PHAuthorizationStatusRestricted){
  88. NSLog(@"status == %ld",(long)status);
  89. }
  90. else if(status == PHAuthorizationStatusAuthorized){
  91. }
  92. });
  93. }];
  94. }*/
  95. }
  96. });
  97. return _sdk;
  98. }
  99. //照片路径
  100. - (NSString *)MakeJPGFold:(NSString *)jpgfoldname {
  101. NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  102. NSString *documentPath = [path objectAtIndex:0];
  103. NSFileManager *fileManager = [NSFileManager defaultManager];
  104. NSString *imageDocPath = [documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",jpgfoldname]];
  105. NSLog(@"====>name:%@",imageDocPath);
  106. [fileManager createDirectoryAtPath:imageDocPath withIntermediateDirectories:YES attributes:nil error:nil];
  107. return imageDocPath;
  108. }
  109. ////获取视频pixelBuffer
  110. //- (void)displayLinkCallback:(CADisplayLink *)sender {
  111. //
  112. // if (_bfLayer.pixelBuffer && self.getPixelBuffer) {
  113. // //block回调
  114. // self.getPixelBuffer(_bfLayer.pixelBuffer);
  115. // }
  116. //}
  117. //1: 成功 -4 10秒链接超时。-1 错误
  118. - (int)connectToServer {
  119. WeakSelf;
  120. //异步调用
  121. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  122. char Version[32];
  123. weakSelf.connect = [weakSelf.sdk GetDeviceVersion:Version];
  124. });
  125. return _connect;
  126. }
  127. //开始视频
  128. - (void)startVideo {
  129. [self stopVideo];
  130. char ipaddr[16];
  131. //[SDK FindDevice:ipaddr];
  132. memset(ipaddr,0,sizeof(ipaddr));
  133. strcpy(ipaddr,"192.168.1.1");
  134. int ret = [self.sdk StartVideo:ipaddr];
  135. if(ret != 0)
  136. {
  137. printf("connect device error!\n");
  138. return;
  139. }
  140. }
  141. //停止视频
  142. - (void)stopVideo {
  143. [self.sdk StopVideo];
  144. }
  145. //拍照
  146. - (void)takePhoto:(NSString *)str {
  147. //删除临时文件
  148. [self deleteTmpFileisPhoto:YES];
  149. //拍照
  150. char filename[255];
  151. struct tm *ptm;
  152. time_t timep;
  153. time(&timep);
  154. ptm = localtime(&timep);
  155. memset(filename,0,sizeof(filename));
  156. sprintf(filename,"%04d%02d%02d%02d%02d%02d.jpg", (ptm->tm_year+1900),ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
  157. [self.sdk ManualCapture:(char *)filename];
  158. // _imageName = str;
  159. _imageName = @"";
  160. }
  161. //拍照结果
  162. - (void)handleNotification:(NSNotification *)notify {
  163. NSString *param = notify.userInfo[@"content"];
  164. NSLog(@"recv: %@",param);
  165. //please handle result....
  166. // if ([param rangeOfString:@"jpg"].location == NSNotFound)
  167. //点击设备拍照按钮
  168. if (![param containsString:@"jpg"])
  169. {
  170. //device button key0
  171. // self.imageName = @"";
  172. //点击设备拍照按钮,通知flutter去拍照
  173. if (self.onDeviceTakePhoto) {
  174. self.onDeviceTakePhoto();
  175. }
  176. }
  177. //调用拍照方法
  178. else
  179. {
  180. // UIImage *image = [[UIImage alloc] initWithContentsOfFile:param];
  181. //1.保存照片
  182. // [self saveImgAndVideo:param isPhoto:YES];
  183. //2.检查文件是否存在 存在返回路径,不存在返回失败
  184. NSFileManager *fileManager = [NSFileManager defaultManager];
  185. if ([fileManager fileExistsAtPath:param]) {
  186. if (self.getPhotoPath) {
  187. self.getPhotoPath(param);
  188. }
  189. } else {
  190. if (self.getPhotoPath) {
  191. self.getPhotoPath(@"error:获取照片路径失败");
  192. }
  193. }
  194. }
  195. }
  196. //开始录像
  197. - (void)startRecord:(NSString *)str {
  198. //删除临时文件
  199. [self deleteTmpFileisPhoto:NO];
  200. //启动录像. 是否推送到相册 0: 不用 1:推送
  201. [self.sdk JPGStartRecord:0];
  202. _recordName = str;
  203. }
  204. //停止录像
  205. - (void)stopRecord {
  206. [self.sdk JPGStopRecord];
  207. //1.保存视频
  208. // [weakSelf saveImgAndVideo:@"" isPhoto:NO];
  209. //2.返回视频地址 延迟1.0s,以防没有获取完整视频地址
  210. WeakSelf;
  211. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  212. // 获取应用沙盒中的 Documents 目录路径
  213. NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  214. // 拼接目标文件夹的路径
  215. NSString * targetFolderPath = [documentsPath stringByAppendingPathComponent:@"jpgvideo/"];
  216. // 创建文件管理器实例
  217. NSFileManager *fileManager = [NSFileManager defaultManager];
  218. // 获取目标文件夹中的所有内容
  219. NSError *error = nil;
  220. NSArray *contents = [fileManager contentsOfDirectoryAtPath:targetFolderPath error:&error];
  221. if (error) {
  222. NSLog(@"Error accessing folder contents: %@", error.localizedDescription);
  223. if (weakSelf.getVideoPath) {
  224. weakSelf.getVideoPath(@"error:获取视频路径失败");
  225. }
  226. }
  227. else {
  228. //从document中获取路径,找到不带下划线的
  229. NSString *tmpPath = [targetFolderPath stringByAppendingPathComponent:contents.lastObject];
  230. for (NSString *tmpStr in contents) {
  231. if (![tmpStr containsString:@"_"]) {
  232. tmpPath = [targetFolderPath stringByAppendingPathComponent:tmpStr];
  233. }
  234. }
  235. // 检查文件是否存在
  236. if ([fileManager fileExistsAtPath:tmpPath]) {
  237. if ([tmpPath containsString:weakSelf.recordName]) {
  238. NSLog(@"无需重命名");
  239. } else {
  240. //重命名
  241. NSRange range = [tmpPath rangeOfString:@"jpgvideo/"];
  242. NSMutableString *mutableString = [NSMutableString stringWithString:tmpPath];
  243. [mutableString insertString:weakSelf.recordName atIndex:range.location + range.length];
  244. NSString *newFilePath = [mutableString copy];;
  245. // 使用 moveItemAtPath:toPath:error: 方法重命名文件
  246. BOOL success = [fileManager moveItemAtPath:tmpPath toPath:newFilePath error:&error];
  247. if (success) {
  248. NSLog(@"文件重命名成功: %@ -> %@", tmpPath, newFilePath);
  249. tmpPath = newFilePath;
  250. //返回视频地址
  251. if (weakSelf.getVideoPath) {
  252. weakSelf.getVideoPath(tmpPath);
  253. }
  254. } else {
  255. NSLog(@"文件重命名失败: %@", error.localizedDescription);
  256. if (weakSelf.getVideoPath) {
  257. weakSelf.getVideoPath(@"error:文件重命名失败");
  258. }
  259. }
  260. }
  261. } else {
  262. NSLog(@"文件不存在: %@", tmpPath);
  263. if (weakSelf.getVideoPath) {
  264. weakSelf.getVideoPath(@"error:文件不存在");
  265. }
  266. }
  267. }
  268. });
  269. }
  270. //保存照片 数组,两个元素,0:临时视频路径,1:编辑后视频路径
  271. - (void)savePhoto:(NSArray *)arr {
  272. [self newSaveImgAndVideo:arr isPhoto:YES];
  273. }
  274. //保存视频 数组,两个元素,0:临时视频路径,1:编辑后视频路径
  275. - (void)saveRecord:(NSArray *)arr {
  276. [self newSaveImgAndVideo:arr isPhoto:NO];
  277. }
  278. //保存照片,视频到相册
  279. - (void)newSaveImgAndVideo:(NSArray *)path isPhoto:(BOOL)isPhoto {
  280. WeakSelf;
  281. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  282. //删除临时的
  283. if (path[0]) {
  284. if ([path[0] isEqualToString:path[1]]) {
  285. }
  286. //链接不一致时删除
  287. else {
  288. [weakSelf deleteFile:path[0]];
  289. }
  290. }
  291. if (path[1]) {
  292. //保存新的 检查文件是否存在
  293. NSString * tmpPath = path[1];
  294. // 获取自定义相册的集合
  295. NSString *albumName = @"dental";
  296. PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
  297. subtype:PHAssetCollectionSubtypeAlbumRegular
  298. options:nil];
  299. __block PHAssetCollection *customAlbum = nil;
  300. [collections enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
  301. if ([collection.localizedTitle isEqualToString:albumName]) {
  302. customAlbum = collection;
  303. *stop = YES;
  304. }
  305. }];
  306. // 如果相册不存在,创建一个新相册
  307. if (!customAlbum) {
  308. [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
  309. [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:albumName];
  310. } completionHandler:^(BOOL success, NSError * _Nullable error) {
  311. if (success) {
  312. NSLog(@"Successfully created album: %@", albumName);
  313. [weakSelf newSaveImgAndVideo:path isPhoto:isPhoto]; // 重新调用自己保存
  314. } else {
  315. NSLog(@"Error creating album: %@", error.localizedDescription);
  316. if (isPhoto) {
  317. if (weakSelf.getSavePhotoPath) {
  318. weakSelf.getSavePhotoPath(@"error:创建相册失败");
  319. }
  320. }
  321. else{
  322. if (weakSelf.getSaveRecordPath) {
  323. weakSelf.getSaveRecordPath(@"error:创建相册失败");
  324. }
  325. }
  326. }
  327. }];
  328. return;
  329. }
  330. // 相册存在 开始保存文件到相册
  331. [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
  332. PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:customAlbum];
  333. // 图片文件
  334. if (isPhoto) {
  335. UIImage *image = [UIImage imageWithContentsOfFile:tmpPath];
  336. if (image) {
  337. PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
  338. [albumChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
  339. }
  340. }
  341. //视频文件
  342. else {
  343. NSURL *fileURL = [NSURL fileURLWithPath:tmpPath];
  344. PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:fileURL];
  345. [albumChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
  346. }
  347. } completionHandler:^(BOOL success, NSError * _Nullable error) {
  348. if (success) {
  349. NSLog(@"Successfully saved images to album: %@", albumName);
  350. //回到主线程回传
  351. dispatch_async(dispatch_get_main_queue(), ^{
  352. if (isPhoto) {
  353. if (weakSelf.getSavePhotoPath) {
  354. weakSelf.getSavePhotoPath(@"保存相册成功");
  355. }
  356. }
  357. else {
  358. if (weakSelf.getSaveRecordPath) {
  359. weakSelf.getSaveRecordPath(@"保存相册成功");
  360. }
  361. }
  362. });
  363. } else {
  364. NSLog(@"Error saving images: %@", error.localizedDescription);
  365. if (isPhoto) {
  366. if (weakSelf.getSavePhotoPath) {
  367. weakSelf.getSavePhotoPath(@"error:保存相册失败");
  368. }
  369. }
  370. else {
  371. if (weakSelf.getSaveRecordPath) {
  372. weakSelf.getSaveRecordPath(@"error:保存相册失败");
  373. }
  374. }
  375. }
  376. }];
  377. }
  378. });
  379. }
  380. //保存照片,视频到相册
  381. - (void)saveImgAndVideo:(NSString *)path isPhoto:(BOOL)isPhoto {
  382. WeakSelf;
  383. __block NSString *tmpPath = path;
  384. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  385. //重命名 保存照片
  386. if (isPhoto) {
  387. //替换文件名添加前缀
  388. // 创建文件管理器实例
  389. NSFileManager *fileManager = [NSFileManager defaultManager];
  390. // 获取目标文件夹中的所有内容
  391. NSError *error = nil;
  392. // 检查文件是否存在
  393. if ([fileManager fileExistsAtPath:tmpPath]) {
  394. if ([tmpPath containsString:weakSelf.imageName]) {
  395. NSLog(@"无需重命名");
  396. } else {
  397. //插入文件名
  398. NSRange range = [tmpPath rangeOfString:@"jpgimage/"];
  399. NSMutableString *mutableString = [NSMutableString stringWithString:tmpPath];
  400. [mutableString insertString:weakSelf.imageName atIndex:range.location + range.length];
  401. NSString *newFilePath = [mutableString copy];;
  402. // 使用 moveItemAtPath:toPath:error: 方法重命名文件
  403. BOOL success = [fileManager moveItemAtPath:tmpPath toPath:newFilePath error:&error];
  404. if (success) {
  405. NSLog(@"文件重命名成功: %@ -> %@", tmpPath, newFilePath);
  406. tmpPath = newFilePath;
  407. } else {
  408. NSLog(@"文件重命名失败: %@", error.localizedDescription);
  409. }
  410. }
  411. } else {
  412. NSLog(@"文件不存在: %@", tmpPath);
  413. }
  414. }
  415. //重命名 保存视频
  416. else {
  417. // 获取应用沙盒中的 Documents 目录路径
  418. NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  419. // 拼接目标文件夹的路径
  420. NSString * targetFolderPath = [documentsPath stringByAppendingPathComponent:@"jpgvideo/"];
  421. // 创建文件管理器实例
  422. NSFileManager *fileManager = [NSFileManager defaultManager];
  423. // 获取目标文件夹中的所有内容
  424. NSError *error = nil;
  425. NSArray *contents = [fileManager contentsOfDirectoryAtPath:targetFolderPath error:&error];
  426. if (error) {
  427. NSLog(@"Error accessing folder contents: %@", error.localizedDescription);
  428. if (weakSelf.getVideoPath) {
  429. weakSelf.getVideoPath(@"error:获取视频路径失败");
  430. }
  431. return;
  432. }
  433. //从document中获取路径
  434. tmpPath = [targetFolderPath stringByAppendingPathComponent:contents.firstObject];
  435. // 检查文件是否存在
  436. if ([fileManager fileExistsAtPath:tmpPath]) {
  437. if ([tmpPath containsString:weakSelf.recordName]) {
  438. NSLog(@"无需重命名");
  439. } else {
  440. //重命名
  441. NSRange range = [tmpPath rangeOfString:@"jpgvideo/"];
  442. NSMutableString *mutableString = [NSMutableString stringWithString:tmpPath];
  443. [mutableString insertString:weakSelf.recordName atIndex:range.location + range.length];
  444. NSString *newFilePath = [mutableString copy];;
  445. // 使用 moveItemAtPath:toPath:error: 方法重命名文件
  446. BOOL success = [fileManager moveItemAtPath:tmpPath toPath:newFilePath error:&error];
  447. if (success) {
  448. NSLog(@"文件重命名成功: %@ -> %@", tmpPath, newFilePath);
  449. tmpPath = newFilePath;
  450. } else {
  451. NSLog(@"文件重命名失败: %@", error.localizedDescription);
  452. }
  453. }
  454. } else {
  455. NSLog(@"文件不存在: %@", tmpPath);
  456. }
  457. }
  458. // 获取自定义相册的集合
  459. NSString *albumName = @"dental";
  460. PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
  461. subtype:PHAssetCollectionSubtypeAlbumRegular
  462. options:nil];
  463. __block PHAssetCollection *customAlbum = nil;
  464. [collections enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
  465. if ([collection.localizedTitle isEqualToString:albumName]) {
  466. customAlbum = collection;
  467. *stop = YES;
  468. }
  469. }];
  470. // 如果相册不存在,创建一个新相册
  471. if (!customAlbum) {
  472. [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
  473. [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:albumName];
  474. } completionHandler:^(BOOL success, NSError * _Nullable error) {
  475. if (success) {
  476. NSLog(@"Successfully created album: %@", albumName);
  477. [weakSelf saveImgAndVideo:tmpPath isPhoto:isPhoto]; // 重新调用自己保存
  478. } else {
  479. NSLog(@"Error creating album: %@", error.localizedDescription);
  480. if (isPhoto) {
  481. if (weakSelf.getPhotoPath) {
  482. weakSelf.getPhotoPath(@"error:创建相册失败");
  483. }
  484. }
  485. else{
  486. if (weakSelf.getVideoPath) {
  487. weakSelf.getVideoPath(@"error:创建相册失败");
  488. }
  489. }
  490. }
  491. }];
  492. return;
  493. }
  494. // 开始保存文件到相册
  495. [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
  496. PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:customAlbum];
  497. // 图片文件
  498. if (isPhoto) {
  499. UIImage *image = [UIImage imageWithContentsOfFile:tmpPath];
  500. if (image) {
  501. PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
  502. [albumChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
  503. }
  504. }
  505. //视频文件
  506. else {
  507. NSURL *fileURL = [NSURL fileURLWithPath:tmpPath];
  508. PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:fileURL];
  509. [albumChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
  510. }
  511. } completionHandler:^(BOOL success, NSError * _Nullable error) {
  512. if (success) {
  513. NSLog(@"Successfully saved images to album: %@", albumName);
  514. //回到主线程回传
  515. dispatch_async(dispatch_get_main_queue(), ^{
  516. if (isPhoto) {
  517. //获取照片路径
  518. if (weakSelf.getPhotoPath) {
  519. weakSelf.getPhotoPath(tmpPath);
  520. }
  521. }
  522. else {
  523. //返回视频路径
  524. if (weakSelf.getVideoPath) {
  525. weakSelf.getVideoPath(tmpPath);
  526. }
  527. }
  528. });
  529. } else {
  530. NSLog(@"Error saving images: %@", error.localizedDescription);
  531. if (isPhoto) {
  532. if (weakSelf.getPhotoPath) {
  533. weakSelf.getPhotoPath(@"error:保存相册失败");
  534. }
  535. }
  536. else {
  537. if (weakSelf.getVideoPath) {
  538. weakSelf.getVideoPath(@"error:保存相册失败");
  539. }
  540. }
  541. }
  542. }];
  543. });
  544. }
  545. //获取图片列表
  546. - (NSArray *)getPhotoList {
  547. return [self fetchPhotosAndVideosFromAlbum:@"jpgimage"];
  548. }
  549. //获取视频列表
  550. - (NSArray *)getVideoList {
  551. return [self fetchPhotosAndVideosFromAlbum:@"jpgvideo"];
  552. }
  553. //获取照片视频文件列表
  554. - (NSArray *)fetchPhotosAndVideosFromAlbum:(NSString *)str {
  555. // 获取应用沙盒中的 Documents 目录路径
  556. NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  557. // 拼接目标文件夹的路径
  558. NSString * targetFolderPath = [documentsPath stringByAppendingPathComponent:str];
  559. // 创建文件管理器实例
  560. NSFileManager *fileManager = [NSFileManager defaultManager];
  561. // 获取目标文件夹中的所有内容
  562. NSError *error = nil;
  563. NSArray *contents = [fileManager contentsOfDirectoryAtPath:targetFolderPath error:&error];
  564. //删除临时文件
  565. for (NSString *str in contents) {
  566. if ([str containsString:@"_"]) {
  567. }else {
  568. [fileManager removeItemAtPath:[targetFolderPath stringByAppendingPathComponent:str] error:&error];
  569. }
  570. }
  571. //重新获取目标文件夹下内容
  572. contents = [fileManager contentsOfDirectoryAtPath:targetFolderPath error:&error];
  573. //拼接完整地址
  574. NSMutableArray *tmpArr = [NSMutableArray new];
  575. for (NSString *tmpStr in contents) {
  576. [tmpArr addObject:[targetFolderPath stringByAppendingPathComponent:tmpStr]];
  577. }
  578. if (error) {
  579. NSLog(@"Error accessing folder contents: %@", error.localizedDescription);
  580. return @[];
  581. }
  582. return tmpArr.copy;
  583. }
  584. //删除临时文件
  585. - (void)deleteTmpFileisPhoto:(BOOL)isPhoto {
  586. // 获取应用沙盒中的 Documents 目录路径
  587. NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  588. // 拼接目标文件夹的路径
  589. NSString * targetFolderPath = [documentsPath stringByAppendingPathComponent: isPhoto == YES ? @"jpgimage/" : @"jpgvideo/"];
  590. // 创建文件管理器实例
  591. NSFileManager *fileManager = [NSFileManager defaultManager];
  592. // 获取目标文件夹中的所有内容
  593. NSError *error = nil;
  594. NSArray *contents = [fileManager contentsOfDirectoryAtPath:targetFolderPath error:&error];
  595. //删除临时文件
  596. for (NSString *str in contents) {
  597. if ([str containsString:@"_"]) {
  598. }else {
  599. [fileManager removeItemAtPath:[targetFolderPath stringByAppendingPathComponent:str] error:&error];
  600. }
  601. }
  602. }
  603. //删除指定文件
  604. - (BOOL)deleteFile:(NSString *)filePath {
  605. //1.删除沙盒中照片
  606. // 创建NSFileManager实例
  607. NSFileManager *fileManager = [NSFileManager defaultManager];
  608. // 删除文件
  609. NSError *error;
  610. [fileManager removeItemAtPath:filePath error:&error];
  611. if (error) {
  612. NSLog(@"Error: %@", [error localizedDescription]);
  613. return NO;
  614. } else {
  615. NSLog(@"File deleted successfully.");
  616. return YES;
  617. }
  618. }
  619. //横屏
  620. - (void)getLandscapeView:(NSArray *)arr {
  621. [self.sdk SetVideoFullScreenRect:CGRectMake(0, 0, [arr[0] floatValue], [arr[1] floatValue])];
  622. [self.sdk SetVideoWindows:1];
  623. }
  624. //竖屏
  625. - (void)getPortraitView {
  626. [self.sdk SetVideoWindows:0];
  627. }
  628. @end