Using exportAsynchronouslyWithCompletionHandler - iphone

I try to export an audio file from the iPod-Library. I want to create with this iPod-Library file an new file. In the AV Foundation Programming Guide in chapter Reading and Writing Assets there is a little example. However this code doesn't work for me. 4 errors happens
Export Status 4 Error Domain=AVFoundationErrorDomain
Code=-11800 "The operation could not be completed"
UserInfo=0x1edfa0 {NSLocalizedFailureReason=An unknown error occurred (-12124),
NSUnderlyingError=0x1ebdc0 "The operation couldn’t be completed. (OSStatus error -12124.)",
NSLocalizedDescription=The operation could not be completed}
My code
AVURLAsset *objAvUrlAsset = [[AVURLAsset alloc] initWithURL:[tempArray objectAtIndex:0] options:nil];
NSLog(#"%s objAvUrlAsset %#", __FUNCTION__, objAvUrlAsset);
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:objAvUrlAsset];
NSLog(#"%s compatiblePresets %#", __FUNCTION__, compatiblePresets);
if ([compatiblePresets containsObject:AVAssetExportPresetAppleM4A]) {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:objAvUrlAsset presetName:AVAssetExportPresetAppleM4A];
NSString * exportPath = [NSString stringWithFormat:#"testTrack1.M4A"];
NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
exportSession.outputURL = exportURL;
exportSession.outputFileType = AVFileTypeAppleM4A;
exportSession.shouldOptimizeForNetworkUse = YES;
NSLog(#"%s export Session %#",__FUNCTION__, exportSession);
[exportSession exportAsynchronouslyWithCompletionHandler: ^(void) {
// export completed
NSLog(#"Export Status %d %#", exportSession.status, exportSession.error);
}];
[exportSession release];
}
the nslog message
-[MyLocalMusicLibrary getAllTracks] objAvUrlAsset AVURLAsset: 0x1dd5a0, URL = ipod-library://item/item.mp3?id=-212958261728896866
-[MyLocalMusicLibrary getAllTracks] compatiblePresets (
AVAssetExportPresetAppleM4A,
AVAssetExportPreset960x540,
AVAssetExportPresetLowQuality,
AVAssetExportPresetMediumQuality,
AVAssetExportPreset640x480,
AVAssetExportPresetHighestQuality,
AVAssetExportPreset1280x720
)
-[MyLocalMusicLibrary getAllTracks] export Session AVAssetExportSession: 0x1e85c0,
asset = AVURLAsset: 0x1dd5a0, URL = ipod-library://item/item.mp3?id=-212958261728896866,
presetName = AVAssetExportPresetAppleM4A, outputFileType = com.apple.m4a-audio
-[MyLocalMusicLibrary getAllTracks] Export Status 4 Error Domain=AVFoundationErrorDomain
Code=-11800 "The operation could not be completed"
UserInfo=0x1edfa0 {NSLocalizedFailureReason=An unknown error occurred (-12124),
NSUnderlyingError=0x1ebdc0 "The operation couldn’t be completed. (OSStatus error -12124.)",
NSLocalizedDescription=The operation could not be completed}
How can i fix this four errors. Do i need for this export the AVAssetReader and AVAssetWriter.

I got the same result from AVAssetExportSession, what the completely useless NSError is trying to tell you is that the path you're exporting to doesn't fully exist. You'll want to make sure that you create the path to the directory you're placing the file in using NSFileManager.

The problem for me was that I was trying to convert the file directly from the tmp directory after getting it from the UIImagePickerController
What I had to do was first save the file to the Library, then iterate over the ALAssetLibrary files to find the latest video saved. Then I converted that video to .mp4 and stored it int he application's local documents directory for use as I please.
Kind of ridiculous that this is necessary but it works.

Related

Parsing Local XML File Works, Downloaded XML File Doesn't

I have this problem when I fetch an XML file from the internet and then parse it, where I get this error:
Error while parsing the document: Error Domain=SMXMLDocumentErrorDomain Code=1 "Malformed XML document. Error at line 1:1." UserInfo=0x886e880 {LineNumber=1, ColumnNumber=1, NSLocalizedDescription=Malformed XML document. Error at line 1:1., NSUnderlyingError=0x886e7c0 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 5.)"}
Here is an extract from the code (I believe I am only showing the most relevant code, if you need more, please ask.)
// Create a URL Request and set the URL
NSURL *url = [NSURL URLWithString:#"http://***.xml"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// Display the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
// Perform the request on a new thread so we don't block the UI
dispatch_queue_t downloadQueue = dispatch_queue_create("Download queue", NULL);
dispatch_async(downloadQueue, ^{
NSError* err = nil;
NSHTTPURLResponse* rsp = nil;
// Perform the request synchronously on this thread
NSData *rspData = [NSURLConnection sendSynchronousRequest:request returningResponse:&rsp error:&err];
// Once a response is received, handle it on the main thread in case we do any UI updates
dispatch_async(dispatch_get_main_queue(), ^{
// Hide the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (rspData == nil || (err != nil && [err code] != noErr)) {
// If there was a no data received, or an error...
NSLog(#"No data received.");
} else {
// Cache the file in the cache directory
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString* path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"init.xml"];
//NSLog(#"%#",path);
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
[data writeToFile:path atomically:YES];
//NSString *sampleXML = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"xml"];
NSData *data = [NSData dataWithContentsOfFile:path];
// create a new SMXMLDocument with the contents of sample.xml
NSError *error;
SMXMLDocument *document = [SMXMLDocument documentWithData:data error:&error];
// check for errors
if (error) {
NSLog(#"Error while parsing the document: %#", error);
// return;
}
Firstly, I have connected the iPhone to an XML feed which it has fetched and written to the path of the variable path. Then I check for errors in the XML document and I get that error every time.
However, if I use a local XML file which I have placed in the main folder of my application there is no problem fetching all the data.
Using the code:
NSString *sampleXML = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"xml"];
So does anyone have an idea as to what I can have done wrong? It seems as if it doesn't download and store the XML file to the iPhone's cache, however NSLog(); seems to show it differently. Obviously the local file is the same as the file on the internet.
Furthermore, I already tried to save the file to the path without any results, though.
A couple of observations:
The key issue would appear to be that you retrieved the data in rspData, but when you write it to your temporary file, you're writing data, not rspData. So change the line that says:
[data writeToFile:path atomically:YES];
to
[rspData writeToFile:path atomically:YES];
Frankly, I don't even see the data variable defined at that point (do you have some ivar lingering about?). I'd be ruthless about getting rid of any ivars or other variables that you don't need, so that you don't accidentally refer to some unused variable. Anyway, just use the rspData that you retrieved rather than some other variable.
Why are you even writing that to a file, only to then read the file into another NSData that you pass to your XML parser? That seems entirely unnecessary. Just go ahead and use the rspData you initially retrieved. If you want to save the NSData to a file so you can examine it later for debugging purposes, that's fine. But there's no point in re-retrieving the NSData from the file, as you already have it in a rspData already.
If you encounter these errors in the future, feel free to examine the contents of the NSData variable with a debugging line of code, something like:
NSLog(#"rspData = %#", [[NSString alloc] initWithData:rspData encoding:NSUTF8StringEncoding]);
When you do that, you can look at the string rendition of the NSData, and usually the problem will become self evident.
As a complete aside, in your debugging error handler, you have a line that says:
NSLog(#"No data received.");
I might suggest you always include any errors that might be provided, e.g.:
NSLog(#"No data received: error = %#", err);
iOS provides useful error messages, so you should avail yourself of those.

XML Parse Error in Device not in Simulator - NSXMLParserErrorDomain Code=5

I load XML response from a server and parsed using NSXMLParser. No error in the simulator. But shows NSXMLParserErrorDomain Code=5 in iPhone.
NSString *settings = "http://website.com/settings";
NSURL *url = [NSURL URLWithString:settings];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
xmlParser.delegate = self;
BOOL success = [xmlParser parse];
if(success)
{
NSLog(#"Parse Success");
}else{
NSLog(#"Parse Failure");
NSLog(#"Parse Error: %#",[xmlParser parserError]);
}
XML Response
<?xml version="1.0" encoding="utf-8"?>
<Settings>
<AutoRefereshTime>10</AutoRefereshTime>
<CashierPasswordRequired>Y</CashierPasswordRequired>
<CheckoutTableColor>#FFFF00</CheckoutTableColor>
<CompanyLogo>http://website.com/UCS_WS/Images/Logo/Logo.png</CompanyLogo>
<CompanyName>UnoRestaurant</CompanyName>
<ConfirmedTableColor>008ED5</ConfirmedTableColor>
<Description>The Great Indian Restaurant</Description>
<DevelopedBy>Unipro</DevelopedBy>
<HoldTableColor>A02325</HoldTableColor>
<ImageURL>http://rwebsite.com/UCS_WS/Images/Dish/</ImageURL>
<isCategoryEnabled>Y</isCategoryEnabled>
<isOtherLanguageEnabled>Y</isOtherLanguageEnabled>
<NormalTableColor>#0000FF</NormalTableColor>
<OrderScreenView>POS View</OrderScreenView>
<OtherLanguage>Tamil</OtherLanguage>
<SharedTableColor>#00FFFF</SharedTableColor>
</Settings>
Parse Error:
Error Domain=NSXMLParserErrorDomain Code=5 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 5.)"
Refer the answer given by #mobibob here==> What is the meaning of NSXMLParserErrorDomain error 5.?
According to Dave DeLong,
That means it's having issues parsing your file.
I think it may be the XSLT reference in the XML - as it points to the webserver. I will review and get back to this question with an improved answer.
It was the path of the file. My code wasn't even close to the right location -- and I was missing a trailing letter 's'. The error code definition implies a "premature end of file", which caused me to truncate my file without any success. I then went back to basics and iterated on the file system to look for my file.
I debugged by using the NSFileManager to iterate to my file and then verified that it was loadable with the contentsAtPath method. I was able to dump it with NSLog(). Once I was convinced that the file was well-formed and loaded in raw form, I made certain that my NSURL was constructed with the same syntax and methods. Then it loaded correctly. Now I can load either a network file "full-featured" content or a local "sample" content.
NSDirectoryEnumerator *dirEnumerator = [[NSFileManager defaultManager] enumeratorAtPath: NSHomeDirectory()];
NSString *something;
NSString *f;
while( something = [dirEnumerator nextObject] ) {
f = [[[NSString alloc] initWithFormat: #"%#/%#", NSHomeDirectory(), something] autorelease];
if( [f hasSuffix :#"two_cookies.xml"] ){
NSData *nsData = (NSData*) [[NSFileManager defaultManager] contentsAtPath: f];
NSLog(#"%#", nsData );
}
}
Output
2009-10-22 00:47:40.147 MyApp[13843:20b]

ios not finding a txt file using stringWithContentsOfFile

I have a text file thetext.txt. Which is in my project and is copied on build, in build settings. In the same way that my GL shaders and textures are (which work fine.)
NSError *errorReading;
NSArray *linesOfText = [[NSString stringWithContentsOfFile:#"thetext.txt"
encoding:NSUTF8StringEncoding
error:&errorReading]
componentsSeparatedByString:#"\n"];
NSLog(#"Reading error %#",errorReading);
It prints the following to console.
Reading error Error Domain=NSCocoaErrorDomain Code=260 "The operation couldn’t be completed. (Cocoa error 260.)" UserInfo=0x896fff0 {NSFilePath=thetext.txt, NSUnderlyingError=0x896ff60 "The operation couldn’t be completed. No such file or directory"}
Have I missing something?
This fails because you are passing the file name and not the path to the file. Try something like this
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"thetext" ofType:#"txt"];
NSError *errorReading;
NSArray *linesOfText = [[NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:&errorReading]
componentsSeparatedByString:#"\n"];
NSLog(#"Reading error %#",errorReading);
Hopefully there will be no error!

"The operation couldn’t be completed. (Cocoa error 512.)"

I have this code, which should be working perfectly, but I can't udnerstand why it isn't:
+(NSString *)writeImageToFile:(UIImage *)image {
NSData *fullImageData = UIImageJPEGRepresentation(image, 1.0f);
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Images/"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
BOOL directoryExists = [fileManager fileExistsAtPath:path isDirectory:&isDirectory];
if (directoryExists) {
NSLog(#"isDirectory: %d", isDirectory);
} else {
NSError *error = nil;
BOOL success = [fileManager createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error];
if (!success) {
NSLog(#"Failed to create directory with error: %#", [error description]);
}
}
NSString *name = [NSString stringWithFormat:#"%#.jpg", [JEntry generateUuidString]];
NSString *filePath = [path stringByAppendingPathComponent:name];
NSError *error = nil;
BOOL success = [fullImageData writeToFile:filePath options:NSDataWritingAtomic error:&error];
if (!success) {
NSLog(#"Failed to write to file with error: %#", [error description]);
}
return filePath;
}
It passed the directoryExists without an error, but when it gets to writeToFile, it gives me this error:
Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0x5634ee0 {NSFilePath=/var/mobile/Applications/5E25F369-9E05-4345-A0A2-381EDB3321B8/Documents/Images/18DAE0BD-6CB4-4244-8ED1-9031393F6DAC.jpg, NSUnderlyingError=0x5625010 "The operation couldn’t be completed. Not a directory"}
Any ideas why this might be?
I was able to reproduce your error when writing a file first in the path #"Documents/Images/", then trying to write the image using your code.
I think there are two possible scenarios for this:
1) You created that file by mistake at a previous execution of your app. This will be solved if you reset the simulator using the menu: iOS Simulator > Reset Contents and Settings, and uninstalling the app from your device: Long press > click on the x symbol.
2) There is some code somewhere else in your app that creates this file. If this is the case, you should find this code and remove it.
From FoundationErrors.h:
NSFileWriteUnknownError = 512
Try using withIntermediateDirectories:YES.
In my case a period '.' in the directory name (e.g. ~/Documents/someDir.dir/somefile) was the cause of the problem. I removed the offending character and the error disappeared.

AVAudioPlayer -> not working

Audio Player works fine if I initiate it for 20 to 30 times but after that it shows the following error
Error Domain=NSOSStatusErrorDomain Code=-43 "The operation couldn’t be completed. (OSStatus error -43.)"
The code currently I am using is as follows
- (void)playShortSound:(NSString *)fileName type:(NSString *)type
{
if (!isSound) {
return;
}
NSString *soundFilePath =[[NSBundle mainBundle] pathForResource: fileName ofType: type];
NSURL *fileURL = [[[NSURL alloc] initFileURLWithPath: soundFilePath] autorelease];
NSError *error;
AVAudioPlayer *newPlayer =[[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
error: &error];
//newPlayer.numberOfLoops = 0;
newPlayer.volume=1.0;
if (newPlayer == nil){
NSLog(#"%#",[error description]);
//[self playShortSound:fileName type:type];
//return;
}
else{
[newPlayer play];
newPlayer.delegate=self;
}
}
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) player
successfully: (BOOL) completed {
if (completed == YES) {
NSLog(#"Sound Playing complete");
}else {
NSLog(#"error in completion of %#",player.url);
}
}
I was having the same problem and instead of init the player from url i did it from NSData.
NSString *soundFilePath =[[NSBundle mainBundle] pathForResource: fileName ofType: type];
NSData *soundData = [[NSData alloc] initWithContentsOfFile:soundFilePath];
NSError *error;
AVAudioPlayer *newPlayer =[[AVAudioPlayer alloc] initWithData: soundData
error: &error];
It seem to solved my problem hope it does yours.
By calling the method many times you are allocating the instance of AVAudioPlayer newPlayer many times. This will certainly cause you problems because of the memory allocated. Just make sure you release the objects that you own once you are done using them.
Did you set AudioSessionCategory?
{NSError *setCategoryError = nil;
BOOL success = [[AVAudioSession sharedInstance] setCategory: avaudiosessioncategoryplayandrecorderror: &setCategoryError];
}
I was trying to play files in my app by picking them from the iPod library when I got this error code. I found that in my iPod library on the device, I had a duplicate entry for the same song. Music player that comes with iOS was able to play one and not the other. That means one entry was not valid anyway. Probably removed from the device but iTunes/iOS did not do proper housekeeping.
It seems that the reference to the non-playable entry existed within the "Recently Added" playlist which is automatically created by the system. I had picked the same file from "Recently Added" playlist to play in the app.
Side Note: I had removed the file from the manually created playlist in which it existed (removed from the iOS device itself).
In short it seems that the file that I loaded into the AVAudioPlayer instance was not available on the device anymore or its referencing URL did not give back a proper file to play. So common reason for this error would be when the player does not get the file to load based on the URL given to it.