Unable to Save Video to Camera Roll (Objective C) - ios

So I've been trying to accomplish this for quite some time now, but unfortunately none of the solutions posted on stack, or the ones I tried to write myself seem to work. I am building an application that allows users to take pictures and videos, and other users to save these down. I am using AWS services to save the content. Although the returned URL using NSLog, shows me the video when copy/pasting it to a browser, it refuses to save to the camera roll. Saving pictures however works fine.
So far I tried the following:
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {
NSURL *movieUrl = [info objectForKey:UIImagePickerControllerMediaURL];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:movieUrl completionBlock:^(NSURL *assetURL, NSError *error){
if(error) {
NSLog(#"CameraViewController: Error on saving movie : %# {imagePickerController}", error);
} else {
NSLog(#"URL: %#", assetURL);
}
}];
}
}
and also:
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(self.post.mediaUrl)) {
UISaveVideoAtPathToSavedPhotosAlbum(self.post.mediaUrl, self, #selector(video:finishedSavingWithError:contextInfo:),#selector(video:finishedSavingWithError:contextInfo:));
} else {
NSLog(#"Incompatible File apparently");
}
Any advice? Thanks!

*Updated on April 6, 2016 to make use of modern frameworks
Import the following in wherever you place this method:
#import <AssetsLibrary/AssetsLibrary.h>
#import Photos
Then call method as following:
[yourClass saveMedia:(*your image*) video:(*your video url*)]
Hope this helps people, feel free to comment with questions.
+ (void)saveMedia:(UIImage *)image video:(NSURL *)video_url {
if(image) {
if(!image) {
return;
}
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
NSLog(#"%#", changeRequest.description);
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"saved down");
} else {
NSLog(#"something wrong");
}
}];
} else if (video_url) {
if([video_url absoluteString].length < 1) {
return;
}
NSLog(#"source will be : %#", video_url.absoluteString);
NSURL *sourceURL = video_url;
if([[NSFileManager defaultManager] fileExistsAtPath:[video_url absoluteString]]) {
[[[ALAssetsLibrary alloc] init] writeVideoAtPathToSavedPhotosAlbum:video_url completionBlock:^(NSURL *assetURL, NSError *error) {
if(assetURL) {
NSLog(#"saved down");
} else {
NSLog(#"something wrong");
}
}];
} else {
NSURLSessionTask *download = [[NSURLSession sharedSession] downloadTaskWithURL:sourceURL completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
if(error) {
NSLog(#"error saving: %#", error.localizedDescription);
return;
}
NSURL *documentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSURL *tempURL = [documentsURL URLByAppendingPathComponent:[sourceURL lastPathComponent]];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:tempURL error:nil];
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:tempURL];
NSLog(#"%#", changeRequest.description);
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"saved down");
[[NSFileManager defaultManager] removeItemAtURL:tempURL error:nil];
} else {
NSLog(#"something wrong %#", error.localizedDescription);
[[NSFileManager defaultManager] removeItemAtURL:tempURL error:nil];
}
}];
}];
[download resume];
}
}
}

In Objective - C
Add this in .h/.m file
#import <Photos/Photos.h>
Save Video to Camera Roll:
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:videoUrl];
}
completionHandler:^(BOOL success, NSError *error) {
if (success)
{
NSLog(#"Video saved");
}else{
NSLog(#"%#",error.description);
}
}];

Related

Delete Image from Custom Album PHPhotoLibrary objective C

In my app I used edit pic and saved in custom folder in Gallery called "Fab". now is there anything to delete that image from folder? I have found different solution but they require asset URL. I used Photos framework so how to get asset url for particular image for deletion ?
PHAsset *tempPhasset = [_arrImageForAssetCameraRoll objectAtIndex:index]; // here pass your PHasset that you want to delete .
NSString *localStr=tempPhasset.localIdentifier;
NSRange range = [localStr rangeOfString:#"/"];
NSString *newString = [localStr substringToIndex:range.location];
NSString *appendedString=[NSString stringWithFormat:#"%#%#%#",#"assets-library://asset/asset.JPG?id=",newString,#"&ext=JPG"];
NSLog(#"%# phasset ",appendedString);
NSURL *deleteurl = [NSURL URLWithString:appendedString];
NSArray *arrDelete = [[NSArray alloc] initWithObjects:deleteurl , nil];
PHFetchResult *asset = [PHAsset fetchAssetsWithALAssetURLs:arrDelete options:nil];
[asset enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"%#",[obj class]);
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
BOOL req = [obj canPerformEditOperation:PHAssetEditOperationDelete];
if (req) {
NSLog(#"true");
[PHAssetChangeRequest deleteAssets:#[obj]];
}
} completionHandler:^(BOOL success, NSError *error) {
NSLog(#"Finished Delete asset. %#", (success ? #"Success." : error));
if (success) {
NSLog(#"delete successfully");
}else{
NSLog(#"delete Cancel");
}
}];
Any query about my code then put comment .
Happy Coding.
Try this below code
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeImageToSavedPhotosAlbum:[viewImage CGImage] orientation:(ALAssetOrientation)[viewImage imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
NSLog(#"error");
} else {
NSLog(#"url %#", assetURL);
}
}];
will return url for saved image.

iOS Sharing Extension : How to share both URL and Text together from Host app

I want to share both text and URL from host app using sharing extension.
- (BOOL)isContentValid {
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *itemProvider in item.attachments) {
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeURL ]) {//
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeURL options:nil completionHandler:^(NSURL *url, NSError *error) {
if(url ) {
self.linksURL= [url absoluteString];
}
}];
}
else if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeText ])
{
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeText options:nil completionHandler:^(NSURL *url, NSError *error) {
if(url ) {
self.linkTitleText= [url absoluteString];
}
}];
}
}
}
self.charactersRemaining=#85;
return YES;
}
Most of this is correct but the implementation of the method is wrong as you will return TRUE before anything has happened. Instead of doing it this way I suggest using a method with a completion handler like so...
-(void)contentURL:(NSExtensionItem *)extension completion:(void (^)(NSURL *url))completion {
for (NSItemProvider *items in self.shareItem.attachments) {
if ([items hasItemConformingToTypeIdentifier:(NSString *)kUTTypeURL]) {
[items loadItemForTypeIdentifier:(NSString *)kUTTypeURL options:nil completionHandler:^(NSURL *url, NSError *error) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
completion(url);
}];
}];
}
}
}
Then create a similar method for the text attribute.
P.S Don't forget to put the operation in a block

How to use PHPhotoLibrary like ALAssetsLibrary

For iOS9, ALAssetsLibrary is deprecated. So how to change it as PHPPhotoLibrary instead of ALAssets?
if (RecordedSuccessfully && recording == NO) {
//----- RECORDED SUCESSFULLY -----
NSLog(#"didFinishRecordingToOutputFileAtURL - success");
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL])
{
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
}
}];
}
// i have tried this, but didnt work
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:outputFileURL];
NSParameterAssert(createAssetRequest);
}
completionHandler:^(BOOL success, NSError *error) {}];
}
}
// Save to the album
__block PHObjectPlaceholder *placeholder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:outputFileURL];
placeholder = [createAssetRequest placeholderForCreatedAsset];
} completionHandler:^(BOOL success, NSError *error) {
if (success)
{
NSLog(#"didFinishRecordingToOutputFileAtURL - success for ios9");
}
else
{
NSLog(#"%#", error);
}
}];

Can we upload photos in Adobe Assets using Abode Creative SDK for iOS and Android?

Using this chunk of code only for accessing the Adobe files in my iOS project, but how can I upload my pictures in Adobe Assets cloud and save it.
[[AdobeUXAssetBrowser sharedBrowser]popupFileBrowser:^(AdobeSelectionAssetArray *itemSelections) {
NSLog(#"Selected a file");
for(id item in itemSelections) {
AdobeAsset *it = ((AdobeSelectionAsset *)item).selectedItem;
NSLog(#"File name %#", it.name);
[_statuslabel setText:fileDesc];
//If an image, let's draw it locally
NSString *fileType = ((AdobeAssetFile *)it).type;
if([fileType isEqualToString:#"image/jpeg" ] || [fileType isEqualToString:#"image/png" ]) {
NSLog(#"Going to download the image");
[((AdobeAssetFile *)it) getData:NSOperationQueuePriorityHigh
onProgress:^(double fractionCompleted) {
}
onCompletion:^(NSData *data, BOOL fromcache) {
NSLog(#"Done downloaded");
UIImage *preview = [UIImage imageWithData:data];
}
onCancellation:^(void){
}
onError:^(NSError *error) {
}
];
}
}
} onError:^(NSError *error)
{
//do nothing
NSLog(#"Error");
}];
You can find a tutorial on how to upload and download files from Creative Cloud using the CreativeSDK here:
https://creativesdk.adobe.com/docs/ios/#/articles/files/index.html
The code in particular that deals with file uploads is below:
NSData *imgData = UIImageJPEGRepresentation( yourImage, 0.8f );
NSString *dataPath = [NSTemporaryDirectory() stringByAppendingPathComponent:#"foo.jpg"];
NSURL *dataURL = [NSURL fileURLWithPath:dataPath];
NSError *err;
BOOL success = [imgData writeToFile:dataPath options:NSDataWritingAtomic error:&err];
if (success) {
AdobeAssetFolder *root = [AdobeAssetFolder getRootOrderedByField:AdobeAssetFolderOrderByName orderDirection:AdobeAssetFolderOrderDescending];
[AdobeAssetFile create:#"foo.jpg"
inFolder:root
withDataPath:dataURL
withType:kMimeTypeJPEG
withCollisionPolicy:AdobeAssetFileCollisionPolicyAppendUniqueNumber
onProgress:^(double fractionCompleted) {
NSLog(#"Percent complete %f", fractionCompleted);
}
onCompletion:^(AdobeAssetFile *file) {
NSLog(#"Uploaded");
}
onCancellation:nil
onError:^(NSError *error) {
NSLog(#"error uploading %#", error);
}];
}

AvSession Fail with Bad_Access_Code

Im trying to save an AvAsset with multiple videos and merging them into a single video.
That part is taken care of though when the block completes it gives me an error.
My block:
-(void)exportDidFinish:(AVAssetExportSession*)session withCompletionBlock:(void(^)(BOOL success))completion {
self.exportSession = nil;
__block id weakSelf = self;
//delete stored pieces
[self.assets enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(AVAsset *asset, NSUInteger idx, BOOL *stop) {
NSURL *fileURL = nil;
if ([asset isKindOfClass:AVURLAsset.class])
{
AVURLAsset *urlAsset = (AVURLAsset*)asset;
fileURL = urlAsset.URL;
}
if (fileURL)
[weakSelf removeFile:fileURL];
NSLog(#"File Url: %#", fileURL);
}];
[self.assets removeAllObjects];
//[self.delegate removeProgress];
if (session.status == AVAssetExportSessionStatusCompleted) {
NSURL *outputURL = session.outputURL;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:outputURL completionBlock:^(NSURL *assetURL, NSError *error){
//delete file from documents after saving to camera roll
[weakSelf removeFile:outputURL];
if (error) {
completion (NO);
} else {
completion (YES);
}
}];
}
}
//Upload service
completion(YES);
[self.assets removeAllObjects];
}
This is the exact error I am receiving:
I would like to say I have a lot of experience with AVFoundation and the Assets though I do not and cant figure out why the completion block is failing.
What could be the issue and if you need anymore information let me know and i can update the question.
Turns out i had named my IBAction for the save button the name of the completionBlock so it was calling itself and failing.
Changed the name, and now it all works very good.

Resources