【问题标题】:iOS listen to the if the user takes a photo [closed]iOS 监听用户是否拍照 [关闭]
【发布时间】:2017-09-04 09:09:39
【问题描述】:

有没有办法在 iPhone 应用程序处于后台时监听文件系统的变化?我想创建一个云托管应用,如果您添加新文件而无需先打开应用,该应用会自动将您的照片上传到云端。

例如,如果用户拍摄新照片、截屏或录音。是否可以通知我某个项目已添加到文件系统中?

【问题讨论】:

  • 您是否也要对用户 SMS 和 Apple 支付进行云备份?
  • 无法在后台访问应用程序。尝试替代品
  • @Sneak 不,我想对存储密集型照片和视频进行云备份。与 Google Drive 和 iCloud 的工作方式完全相同……你明白我的意思吗?谢谢
  • 哦,我的错,我只是好奇,因为我看到你最近的问题是在应用程序外部模拟拍摄设备屏幕截图和在后台同步联系人,我想也许你也想同步其他服务。祝我的朋友好运
  • @Gagan_iOS 那么 Google Drive for iOS 是如何工作的呢?它允许在后台自动备份您的照片和视频?

标签: ios objective-c iphone swift


【解决方案1】:

您可以使用 iOS8 发布的 Photos Framework 来做到这一点。

阅读关于变更观察者 Link

的文档

苹果样品sample

改变观察。使用共享 PHPhotoLibrary 对象为您获取的资产和集合注册更改处理程序。每当另一个应用程序或设备更改资产的内容或元数据或集合中的资产列表时,照片都会告诉您的应用程序。 PH变化 对象在每次更改之前和之后提供有关对象状态的信息,其语义使更新集合视图或类似界面变得容易

如果照片应用有任何更新,您可以使用 **photos 框架拍照

首先你需要注册照片观察者

- (void)applicationWillTerminate:(UIApplication *)application {
    [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
}



 - (void)applicationDidBecomeActive:(UIApplication *)application {
        [FBSDKAppEvents activateApp];
        [[UIApplication sharedApplication] endBackgroundTask:UIBackgroundTaskInvalid];
        [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
        //    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        //        //Background Thread
        //        isBackgroundOrForeground = YES;
        //        [self getGreenEvent];
        //        dispatch_async(dispatch_get_main_queue(), ^(void){
        //            //Run UI Updates
        //        });
        //    });

    }
- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"=== DID ENTER BACKGROUND ===");
    bgTask = [[UIApplication  sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    }];

    if (bgTask == UIBackgroundTaskInvalid) {
        NSLog(@"This application does not support background mode");
    } else {
        //if application supports background mode, we'll see this log.
        NSLog(@"Application will continue to run in background");
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized) {
                [PHPhotoLibrary.sharedPhotoLibrary registerChangeObserver:self];
            }
        }];
        [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
        isBackgroundOrForeground = NO;
        NSString *oAuthToken = [[NSUserDefaults standardUserDefaults]stringForKey:KEY_ACCESS_TOKEN];
        if(oAuthToken.length!=0 || oAuthToken!=nil)
            [self getGreenEvent];
    }
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

编译指示标记 - PHPhotoLibraryChangeObserver

- (void)photoLibraryDidChange:(PHChange *)changeInstance {
    NSLog(@"content being changed");
    /*
     Change notifications may be made on a background queue. Re-dispatch to the
     main queue before acting on the change as we'll be updating the UI.
     */
    __block BOOL reloadRequired = NO;
    __block NSIndexSet *removedIndex;
    __block NSIndexSet *insertedIndexes;
    dispatch_async(dispatch_get_main_queue(), ^{
        // Loop through the section fetch results, replacing any fetch results that have been updated.
        NSMutableArray *updatedSectionFetchResults = [self.sectionFetchResults mutableCopy];
        //        __block BOOL reloadRequired = NO;
        [self.sectionFetchResults enumerateObjectsUsingBlock:^(PHFetchResult *collectionsFetchResult, NSUInteger index, BOOL *stop) {
            PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:collectionsFetchResult];
            removedIndex = changeDetails.removedIndexes;
            insertedIndexes = changeDetails.insertedIndexes;
            if (changeDetails != nil) {
                [updatedSectionFetchResults replaceObjectAtIndex:index withObject:[changeDetails fetchResultAfterChanges]];
                reloadRequired = YES;
                self.sectionFetchResults = updatedSectionFetchResults;
                if(insertedIndexes != nil){
                    [self backgroundUpload];
                }else{
                }

            }

        }];
        if (reloadRequired) {
            self.sectionFetchResults = updatedSectionFetchResults;

        }

    });

}
-(void)getAllPhotosFromCamera{
    PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init];
    allPhotosOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
    PHFetchResult *allPhotos = [PHAsset fetchAssetsWithOptions:allPhotosOptions];
    PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    PHFetchResult *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
    // Store the PHFetchResult objects and localized titles for each section.
    self.sectionFetchResults = @[allPhotos, smartAlbums, topLevelUserCollections];
}
-(NSMutableArray *)getNumberOfPhotoFromCameraRoll:(NSArray *)array{
    PHFetchResult *fetchResult = array[1];
    int index = 0;
    unsigned long pictures = 0;
    for(int i = 0; i < fetchResult.count; i++){
        unsigned long temp = 0;
        temp = [PHAsset fetchAssetsInAssetCollection:fetchResult[i] options:nil].count;
        if(temp > pictures ){
            pictures = temp;
            index = i;
        }
    }
    PHCollection *collection = fetchResult[index];

    if (![collection isKindOfClass:[PHAssetCollection class]]) {
        // return;
    }
    // Configure the AAPLAssetGridViewController with the asset collection.
    PHAssetCollection *assetCollection = (PHAssetCollection *)collection;
    PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    self. assetsFetchResults = assetsFetchResult;
    self. assetCollection = assetCollection;
    self.numberOfPhotoArray = [NSMutableArray array];
    for (int i = 0; i<[assetsFetchResult count]; i++) {
        PHAsset *asset = assetsFetchResult[i];
        [self.numberOfPhotoArray addObject:asset];
    }
    NSLog(@"%lu",(unsigned long)[self.numberOfPhotoArray count]);
    return self.numberOfPhotoArray;
}

其中 bgTask 是

的全局对象

UIBackgroundTaskIdentifier bgTask;

@property (nonatomic, strong) NSArray *sectionFetchResults;
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
@property (nonatomic, strong) PHAssetCollection *assetCollection;
@property (nonatomic, strong) NSMutableArray *numberOfPhotoArray;

【讨论】:

  • 谢谢。这对我有用。一个问题。我收到“loadDatabase 后台任务断言已过期”。我的日志中出现异常(这意味着它在后台运行了超过 3 分钟)。这是否意味着我的应用将被应用商店拒绝?或者也许这无关紧要?
  • 它与应用商店的应用拒绝无关,但我不确定这个异常。你最好再问一个问题
  • 一个应用只能在后台运行 3 分钟。这就是它这么说的原因。询问您是否曾经因为在后台听超过 3 分钟而被拒绝。但是,好的,我将创建另一个问题。再次感谢!你帮了大忙!
  • 欢迎,我从来没有被应用商店拒绝过,你最好阅读一下后台任务限制这里有一些关于BG任务的解释stackoverflow.com/questions/22679845/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多