How to save video with my custom album .
I found one link but it don't work Custom file manager
It gives the url value is null.
[VideoAlbumManager addVideoWithAssetURL:outputFileUrl toAlbumWithName:#"Video Maker"];//outputfileurl is my video url from document directory
Give any suggestion for this..
-(void)SaveToalbum{
NSString *finalFileName=[NSString stringWithFormat:#"Documents/video.mov"];
NSString *videoOutputPath = [NSHomeDirectory()
stringByAppendingPathComponent:finalFileName];
NSString* webStringURL = [videoOutputPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL* url =[NSURL URLWithString:webStringURL];
ALAssetsLibrary* library = [[ALAssetsLibrary alloc]init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:url])
{
NSURL *clipURl = url;
[library writeVideoAtPathToSavedPhotosAlbum:clipURl completionBlock:^(NSURL *assetURL, NSError *error)
{
}];
}
}
You can try with it. It will be helpful for you. Just go through "http://www.touch-code-magazine.com/ios5-saving-photos-in-custom-photo-album-category-for-download/" link and download the sample project.
Drag-drop two file "ALAssetsLibrary+CustomPhotoAlbum.h" and "ALAssetsLibrary+CustomPhotoAlbum.m" into your project and add "AssetsLibrary.framework". Now you are ready for coding.Just go on your ViewController.h Class and import the <AssetsLibrary/AssetsLibrary.h> and "ALAssetsLibrary+CustomPhotoAlbum.h" file.
Create a object for ALAssetsLibrary and write a block for saving the video file in custom album,just like this,
[ALAssetsLibraryObject addAssetURL:clipURl toAlbum:AlbumName withCompletionBlock:^(NSError *error)
{
if (error!=nil) {
NSLog(#"Big error: %#", [error description])
}
}];
You can use this link to save the video..
GitHub Link
Import this two files into your project.
ALAssetsLibrary+CustomPhotoAlbum.h
ALAssetsLibrary+CustomPhotoAlbum.m
Then in your save IBAction method write this lines..
if(UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(outputFilePath)){
NSURL *muyrl=[NSURL fileURLWithPath:outputFilePath];
[library saveVideo:muyrl toAlbum:albumName withCompletionBlock:^(NSError *error)
{
if (error!=nil) {
NSLog(#"Big error: %#", [error description]);
}
}];
Where.. outputfilepath is your videopath and if you have url then save it with URL name.
library is ALAssetLibrary that define in .h file
albumName is your Album name what do you want..I hope this will help you.
Related
I can't find a similar method to ALAssetsLibrary->writeImageDataToSavedPhotosAlbum in the new PHPhotoLibrary since ALAssetsLibrary deprecated in iOS 9 I can't save GIF probably I'm using this code
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[UIImage imageWithData:gifdata]];
placeholder = [assetRequest placeholderForCreatedAsset];
photosAsset = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection
assets:photosAsset];
[albumChangeRequest addAssets:#[placeholder]];
} completionHandler:^(BOOL success, NSError *error) {
if (success)
{
}
else
{
NSLog(#"%#", error);
}
}];
I used NSData to save the gif image, ALAssetsLibrary method UIImageWriteToSavedPhotosAlbum deprecated after iOS8,The api says we can use
PHAssetCreationRequestmethod [[PHAssetCreationRequest creationRequestForAsset] addResourceWithType:PHAssetResourceTypePhoto data:data options:options]; to save this gif image data, so you can use url request to save gifs as well
codes are follows:
NSString *path = [[NSBundle mainBundle] pathForResource:#"1" ofType:#"gif"];
NSData *data = [NSData dataWithContentsOfFile:path];
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
[[PHAssetCreationRequest creationRequestForAsset] addResourceWithType:PHAssetResourceTypePhoto data:data options:options];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
NSLog(#":%d",success);
}];
I've save gif file successfully to Photos Gallery by using Photos Framework
PHPhotoLibrary.shared().performChanges ({
let url = URL(fileURLWithPath: "your file path")
PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: url)
}) { saved, error in
if saved {
print("Your image was successfully saved")
}
}
Hope this help!
I solved my issue by creating temp file and using :
creationRequestForAssetFromImageAtFileURL
i use the sample codes from apple for recording and playing the last recording
but i can't play the last recording
here are the codes
- (IBAction)playLastRecording {
// Present the media player controller for the last recorded URL.
NSDictionary *options = #{
WKMediaPlayerControllerOptionsAutoplayKey : #YES
};
[self presentMediaPlayerControllerWithURL:self.lastRecordingURL options:options completion:^(BOOL didPlayToEnd, NSTimeInterval endTime, NSError * __nullable error) {
if (!didPlayToEnd) {
NSLog(#"The player did not play all the way to the end. The player only played until time - %.2f.", endTime);
}
if (error) {
NSLog(#"There was an error with playback: %#.", error);
}
}];
}
and here is the error
i think we need to use the NSbundle and nsurl connection but how
to use for self.lastRecordingURL
please writing the correct codes for this problems
Optional(Error Domain=com.apple.watchkit.errors Code=4 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (1), NSUnderlyingError=0x17d9bf50 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}, NSLocalizedDescription=The operation could not be completed})
I had this problem. Make sure that the audio data is saved to the Apps Group correctly with the correct extension of the file.
If you are trying to record the audio file use the following codes.
- (void)startRecording
{
// Creating a path for saving the recorded audio file.
// We have to write the files to the shared group folder, as this is the only place both the app and extension can see.
NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_IDENTIFIER];
NSURL *outputURL = [container URLByAppendingPathComponent:#"AudioFile.m4a"];
// Setting the recorder options.
NSDictionary *dictMaxAudioRec = #{#"WKAudioRecorderControllerOptionsMaximumDurationKey":MAX_REC_DURATION};
// Presenting the default audio recorder.
[self presentAudioRecorderControllerWithOutputURL:outputURL preset:WKAudioRecorderPresetWideBandSpeech options:dictMaxAudioRec completion:^(BOOL didSave, NSError * error) {
if(didSave)
{
// Successfully saved the file.
NSURL *extensionDirectory = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
NSUInteger timeAtRecording = (NSUInteger)[NSDate timeIntervalSinceReferenceDate];
NSString *dirName = [NSString stringWithFormat:#"AudioFile%d/",timeAtRecording];
NSURL *outputExtensionURL = [extensionDirectory URLByAppendingPathComponent:dirName];
// Move the file to new directory.
NSError *moveError;
BOOL success = [[NSFileManager defaultManager] moveItemAtURL:outputURL toURL:outputExtensionURL error:&moveError];
if (!success) {
NSLog(#"Failed to move the outputURL to the extension's documents direcotry: %#", moveError);
}
else {
NSData *audioData = [NSData dataWithContentsOfURL:outputExtensionURL];
NSLog(#"Actual Audio Data length: %lu", (unsigned long)audioData.length);
if(audioData.length)
{
// We have a valid audio data,do what ever you want to do with this data
}
}
}
else
{
// Something went wrong.
NSLog(#"%s - %#",__PRETTY_FUNCTION__,error);
}
}];
}
Or if you are trying to play a video that you have downloaded from other source or passed from the paired phone, write the audio data first to the App Groups with file extension. The following codes may help you for that.
- (void)writeAudioToAppGroupsWithData:(NSData *)audioData
{
// Writing the audio data to the App Groups
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_IDENTIFIER];
containerURL = [containerURL URLByAppendingPathComponent:[NSString stringWithFormat:DIRECTORY_PATH]];
[audioData writeToURL:containerURL atomically:YES];
}
In this case make sure that your DIRECTORY_PATH is Library/Caches/filename.extension.
Eg: Library/Caches/Audio.mp3
For playing the saved audio use the following codes.
- (void)playAudio
{
// Playing the audio from the url using the default controller
[self presentMediaPlayerControllerWithURL:[self getAudioUrl] options:nil completion:^(BOOL didPlayToEnd, NSTimeInterval endTime, NSError * _Nullable error) {
NSLog(#"Error = %#",error);
}];
}
You can get the audio url from the App Groups.
- (NSURL *)getAudioUrl
{
// Getting the audio url from the App Groups
NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_IDENTIFIER];
NSURL *outputURL = [container URLByAppendingPathComponent:[NSString stringWithFormat:DIRECTORY_PATH]];
return outputURL;
}
Hope this will fix your issue.
Does OS X have a place within the application to save files like how you save files to the documents folders in iOS. I have .plist files to save for my app but I only want to be able to access them form within the app. Don't want do have a folder in the users documents folder or anything.
Primarily an iOS guy so apologies if this is obvious.
I'm not exactly sure what you want here.
To get a directory to store files in an out of the way location, you can use the Application Support directory (~/Library/Application Support/[APP_NAME]/).
To get the name of this directory, you pass NSApplicationSupportDirectory to -URLsForDirectory:inDomains: (see: Managing Files and Directories).
To prevent the user from reading a file, you can encrypt it (see: Encrypting and Hashing Data).
This worked for me:
-(void) setupApp {
NSString * myAppPath = [[Configurations createApplicationDirectoryWithPathComponent:MY_APP_DIR_NAME] path];
self.plistPath = [myAppPath stringByAppendingString:CONFIG_FILE_NAME];
[self createNewConfigFileWithDictionary:yourDictionary];
}
-(void) createNewConfigFileWithDictionary:(NSDictionary*)dictionary {
#try {
NSFileManager * fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:self.plistPath]) {
[dictionary writeToFile:self.plistPath atomically:YES];
}
} #catch (NSException *exception) {
NSLog(#"[MyClass createNewConfigFileWithDictionary] Problem:%# Description: %#", [exception name],[exception reason]);
} #finally {}
}
+ (NSURL*) createApplicationDirectoryWithPathComponent:(NSString*)path {
NSFileManager*fm = [NSFileManager defaultManager];
NSURL* dirPath = nil;
// Find the application support directory in the home directory.
NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask];
if ([appSupportDir count] > 0) {
// Append the bundle ID to the URL for the
// Application Support directory
dirPath = [[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:path];
// If the directory does not exist, this method creates it.
// This method is only available in macOS 10.7 and iOS 5.0 or later.
NSError* theError = nil;
if (![fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES attributes:nil error:&theError]) {
#throw [NSException exceptionWithName:#"CreateApplicationDirectoryWithPathComponentException"
reason:theError.localizedDescription
userInfo:nil];
return nil;
}
}
return dirPath;
}
Source:
I am trying to download a pdf file. earlier when i used the completion handler block i was able to see the file in the tmp location. I then wanted to show download progress so i implemented the delegate methods. But i can now see the progress bar working and the file being downloaded. but once the download is complete (bytes written/total bytes = 1) the error delegate is called and there is no file in the tmp location. what am i missing ? below is my code. I have uploaded the project at https://www.dropbox.com/s/vn5zwfwx9izq60a/trydownload.zip
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:#"http://aayudham.com/URLLoadingSystem.pdf"]];
[downloadTask resume];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(#"%#",[error localizedDescription]);
}
-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
dispatch_async(dispatch_get_main_queue(), ^{
_progressBar.progress = (double)totalBytesWritten/(double)totalBytesExpectedToWrite;
double value =(double)totalBytesWritten/(double)totalBytesExpectedToWrite;
NSLog(#"%f",value);
});
}
-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSError *error;
//getting docs dir path
NSArray * tempArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [tempArray objectAtIndex:0];
//adding folder path
NSString *appDir = [docsDir stringByAppendingPathComponent:#"/Reader/"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:appDir])
{
[fileManager createDirectoryAtPath:appDir withIntermediateDirectories:NO attributes:nil error:&error];
}
BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:[appDir stringByAppendingString:#"/demo.pdf"] error:&error];
NSLog(fileCopied ? #"Yes" : #"No");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
#Rob thank you for your prompt replies and that helped me a lot. Here is my code that worked. Hope it helps someone. I am able to get the actual file name and move the file to my documents directory using the original name.
-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
//getting application's document directory path
NSArray * tempArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [tempArray objectAtIndex:0];
//adding a new folder to the documents directory path
NSString *appDir = [docsDir stringByAppendingPathComponent:#"/Reader/"];
//Checking for directory existence and creating if not already exists
if(![fileManager fileExistsAtPath:appDir])
{
[fileManager createDirectoryAtPath:appDir withIntermediateDirectories:NO attributes:nil error:&error];
}
//retrieving the filename from the response and appending it again to the path
//this path "appDir" will be used as the target path
appDir = [appDir stringByAppendingFormat:#"/%#",[[downloadTask response] suggestedFilename]];
//checking for file existence and deleting if already present.
if([fileManager fileExistsAtPath:appDir])
{
NSLog([fileManager removeItemAtPath:appDir error:&error]?#"deleted":#"not deleted");
}
//moving the file from temp location to app's own directory
BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:appDir error:&error];
NSLog(fileCopied ? #"Yes" : #"No");
}
In didFinishDownloadingToURL you should move the file from location to some place more permanent (e.g. your Documents folder). If you're looking for that file in the temporary location later, I'm not surprised it's no longer there.
As the documentation says, the location is defined as such:
A file URL for the temporary file. Because the file is temporary, you must either open the file for reading or move it to a permanent location in your app’s sandbox container directory before returning from this delegate method.
You must move the file to its new location before returning from didFinishDownloadingToURL.
Just in case someone had the same issue that I did I thought I would post my solution here.
My problem was that the predicate methods are firing on a background thread so I was dispatching to my "file io" thread which handles any Writing to files, deleting etc within the app.
The problem with this is that the temporary file gets deleted as soon as the delegate method ends which was occurring at the exact moment I switched threads. So when I tried to access the file in my file io thread it had already been deleted.
My solution was to parse the file into NSData in the delegate method, then use the NSData to write to the filesystem in my file io thread.
NSString *songNameEscaped = [songName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *songURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", #"http://somerootpath/Music/", songNameEscaped]];
NSLog(#"songURL = %#", songURL);
NSError *avPlayerError = nil;
AVAudioPlayer *avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:songURL error:&avPlayerError];
if (avPlayerError)
{
NSLog(#"Error: %#", [avPlayerError description]);
}
else
{
[avPlayer play];
}
If I copy the NSLog output from NSLog(#"songURL = %#", songURL); and paste it in safari, Quicktime plugin plays the files no problem so I know the URLs are valid. I've tried with .m4a and .mp3 files and have tried removing the spaces from songName but not matter what I always get Error:
Error Domain=NSOSStatusErrorDomain Code=-43 "The operation couldn’t be completed. (OSStatus error -43.)".
But they are just standard .m4a / .mp3 files created in iTunes.
Apparently AVAudioPlayer doesn't support streaming. Apple recommends AVPlayer for this although it is not as conveinient for finding things like current time and duration .
Error -43 indicates an inability to find the data. This could be because the url was in fact malformed, or because the server doesn't support streaming. You should try to pre-load the song data with an NSData object.
NSString *songNameEscaped = [songName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *songURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", #"http://somerootpath/Music/", songNameEscaped]];
NSLog(#"songURL = %#", songURL);
NSError *avPlayerError = nil;
NSData* songData = [NSData dataWithContentsOfURL:songURL error:&avPlayerError];
if (songData)
{
AVAudioPlayer *avPlayer = [[AVAudioPlayer alloc] initWithData error:&avPlayerError];
if (avPlayer)
{
[avPlayer prepareToPlay];
[avPlayer play];
}
else
{
NSLog(#"Error initializing data for AVAudioPlayer. Possibly an Unsupported Format");
NSLog(#"Error: %#", [avPlayerError description]);
}
}
else
{
NSLog(#"Error initializing data for AVAudioPlayer. Possibly Malformed URL");
NSLog(#"Error: %#", [avPlayerError description]);
}
I had the same problem yesterday. Turns out my url was wrong.
I had something like you here:
NSURL *songURLID = [NSURL URLWithString:[NSString stringWithFormat:#"%#%d", #"http://somerootpath/Music/", songNameEscaped]];
NSLog(#"songURL = **%d**", songURL**ID**);
But, my songURL was of NSString type. My NSLog wrote it correctly but when I put %d in url it turn out wrong. I suggest you try to check out your AVAudioPlayer url again.
try something like described here to see the players url.
You may want to try checking the targets on your audio file. I had a similar issue and fixed it by making sure that my mp4 file target membership check box was checked. I must not have checked it when I was importing the file originally.
in Apple documentation
An instance of the AVAudioPlayer class, called an audio player,
provides playback of audio data from a file or memory.
Apple recommends that you use this class for audio playback unless you
are playing audio captured from a network stream or require very low
I/O latency.