Multiple music file in document directory in iOS device - objective-c

I am developing an application in iPhone .This application need to store 3 music file (.mp3) to iOS device (the files are from a webserver). The downloading function working perfectly (Using ASIHTTPrRequest). Some time the music saving not working perfectly, that means I am using a checking before the music file go to music player.
playpath=#"/Users/company/Library/Application Support/iPhone Simulator/5.0/Applications/3D5AD723-F18E-4F44-B3CB-FAEF2EA4963B/Documents/329/25-06-2012/330217/work25-06-2012330217.mp3"
NSFileManager*fileM=[NSFileManager defaultManager];
if([fileM isReadableFileAtPath:playpath])
{
}
The playpath (directory path) change with each downloading. some time the downloading paths playing the music and some time this not playing ie this path can not satisfied the above condition .
My questions are
What is reason for the above problem?
What is the exact functionality of isReadableFileAtPath?

Instead of explicitly writing out the file path, have the device find the path for you. Here's what I do:
- (NSString*) saveFilePath: (NSString *) add
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = [path stringByAppendingPathComponent:add];
return filename;
}
Add this to whatever class needs to save or load data. Then you'll be able to get the location of your file with:
[self saveFilePath:#"Name of file you want to load or write to"]

Related

My OSX app is sandboxed and I am not able to read data from file by specifying the absolute path

I am completely new to objective C and currently I am trying to advance the functionality of an already existing project.
There is a finder extension in the project which on getting clicked performs an action inside (IBAction) Share(id) sender.
Inside this action , I want to read a file from a particular location (the file contains the port number) and using that port I want to connect to the server.
But what I found was when I click on this extension , nothing happens because it tries to go and read data from the file and is not able to read anything.
I tried to debug this by printing out whatever it has read to some other file but all it printed was blank confirming that it is not able to read the data. Below is my code trying to read the port from a temporary location :
- (IBAction)privateShareAction:(id)sender {
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: #"/var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties" ] == YES)
{
//create file handle
NSFileHandle *file;
file = [NSFileHandle fileHandleForReadingAtPath:#"/var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties"];
//read data into file in NSData format
NSData *filedata;
filedata = [file readDataToEndOfFile];
NSLog(#"fileDATA = %#", filedata);
//convert NSData to NSString
NSString *string;
string = [[NSString alloc] initWithData:filedata encoding:NSASCIIStringEncoding];
NSMutableString *directoryPath1 = [NSMutableString stringWithString: #"share1>"];
[directoryPath1 appendString: string];
NSData *dataToWrite3 = [directoryPath1 dataUsingEncoding: NSUTF8StringEncoding];
NSFileHandle* outputFile = [NSFileHandle fileHandleForWritingAtPath:#"/Users/yp/Downloads/a.txt"];
[outputFile seekToEndOfFile];
[outputFile writeData:dataToWrite3];
//convert from string to array
NSArray *lines = [string componentsSeparatedByString:#"="];
NSLog(#"arrau = %#", lines);
//take one of the string and store it in sword
NSString *sword = [lines objectAtIndex:1];
NSLog(#"port : %#", sword);
int port1=[sword intValue];
Communicator *c = [[Communicator alloc ]init];
c.host=#"http:127.0.0.1";
c.port=port1;
[c setup];
}
else
{
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:#"Error"];
[alert setInformativeText:#"You are not logged in.Kindly login to start performing the operations"];
[alert setAlertStyle:NSWarningAlertStyle];
[alert runModal];
}
}
The above code, on the action performed first tries to check if the file is present at the /var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties location or not.
This works perfectly fine , If the file is present , it shows a popup alert (which happens).
But if the file is present , it goes inside the if condition and tries to read the file where it fails .It always prints a blank string showing that nothing is being read.
So then I went and checked the entitlements in App Sandbox.
I tried to add an entitlement named com.apple.security.temporary-exception.files.absolute-path.read-only with a string value set to /var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties so that it gets the permission to read the file from this location but still it doesn't solve my problem.
Could anyone please suggest how to get this file reading permission accessible in my app because the same code works completely fine in a newly created test project.
Following steps : Original client app running -login with user name and password Once logged in -it writes the port in a file At the same time ,once you are logged in with your application , if now you right click on any file in your system you will see certain extra extensions like share ,grant access etc. (This is because a finder project used to add extensions is merged with the original client) Now when I click on say share (on right clicking a file) , I want an action to be performed.The logic for action is written in (IBAction)Share (id) sender method This app used to add extensions is sandboxed because of which the permissions are restricted. So while I clicked on share , my logic was to read that file ,get the port and then connect to server using that port. I want to do everything inside action but I am unable to do so . It is not able to find the file data from /var/folder/y3/jv117_755fdlvfldsvgr/T/com.aprivacy.xmlcorePort.properties
Sandboxed apps (all in iOS) are only allowed access to specific directories. Use NSSearchPathForDirectoriesInDomainsto obtain paths to available directories.
Ex:
Objective-C:
NSArray *documentDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSError *error;
BOOL status = [string writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (status == NSError) {
NSLog(#"error: %#", error)
}
Swift:
let filePath = "path/file.txt";
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as! String
let path = documentDirectoryPath + filePath
Note: Sandboxed paths is not consistent across clean builds.
Don't use absolute paths in sandboxed applications.
In OS X there is the NSTemporaryDirectory() function to have access to the temporary directory for this specific application in the container. Entitlements are not needed.
From the documentation
Some path-finding APIs (above the POSIX layer) refer to app-specific
locations outside of the user’s home directory. In a sandboxed app,
for example, the NSTemporaryDirectory function provides a path to a
directory that is outside of the user’s home directory but specific to
your app and within your sandbox; you have unrestricted read/write
access to it for the current user. The behavior of these path-finding
APIs is suitably adjusted for App Sandbox and no code change is
needed.
Source: App Sandbox in Depth

Downloading a file from Dropbox for documents directory deletes all my files

My app shows dropbox files, and the documents directory. when viewing dropbox files i can press a button that shows a list of all my document folders, and subdirectories in those folders so they can chose the folder they want to put that file in the documents. when doing this i used dropbox's objective c API they say to use in the documentation to download a file into a path on the system.
NSString *DocumentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
for (NSIndexPath *indexPath in [dropboxFilesTable indexPathsForSelectedRows]) {
DBMetadata *fileMetadata = [[dropboxFolderMetadata contents] objectAtIndex:indexPath.row];
[[self restClient] loadFile:fileMetadata.path intoPath:DocumentsPath];
}
the delegate for the dropbox says it is successfully put inside, but when i went back in, every folder and downloaded file has been deleted and that file is still not in the folder. i thought it would need the final path like "path to documents"/"filename", but then dropbox gives a error for that. Anyone know why its deleting all my files and not putting it in my documents?
The intoPath parameter needs to be a full filename path, not a directory. You need to update the last line to something like:
NSString *filename = [fileMetadata.path lastPathComponent];
NSString *destPath = [DocumentsPath stringByAppendingPathComponent:filename];
[[self restClient] loadFile:fileMetadata.path intoPath:destPath];
Also make sure that you are only doing this will files and not folders.

Cydia App Documents Folder Not Created

I have been working on a Core Data iOS app that works perfectly through Apple's "channels" – iOS simulator & Xcode installing, yet when I try to manually install it onto a device, the application crashes. My main goal is to put the app on Cydia.
A guide to preparing an app for Cydia
I read this article, and I at the bottom it said
Appstore app has a Documents folder that is created by the installation process. Jailbroken app does not. It is up to the app to create its own folder. Should you need this type of folder, you must create this with a simple mkdir command in your applicationDidFinishLaunching function. Just add a simple function: mkdir(“/var/mobile/Library/YOURAPPNAME”, 0755); If the folder already exists, no harm done. You want to do this because the install process runs as user root and the app runs as user mobile. If Cydia does this for you then the folder will have the incorrect permissions.
I do not know much about how exactly Core Data works, but I know the Core Data "database" is stored in the Documents folder, and I now believe this is the cause of the crash of my app.
The mkdir function did not work in creating a Documents folder.
How would I go about creating a Documents folder, and how would I get it to work with Core Data, ensuring the database is loaded from this folder I created?
Thanks in advance
Most likely you are still using the AppStore friendly Documents path in the methods which create and load the CoreData database file (I think Xcode will put these in your AppDelegate by default).
Check the method which loads the persistentStorageCoordinator and look for a line like this:
NSURL *storeUrl = [NSURL fileURLWithPath: [docPath stringByAppendingPathComponent:#"my_cool_app.sqlite"]];
And make sure that docPath is "/var/mobile/Library/My_Cool_App" and not originating from the standard AppStore friendly:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [documentPaths objectAtIndex:0];
You might want to create a method which returns the proper Documents directory depending on what target you compile the app for:
+(NSString *)documentsDirectoryPath
{
#ifdef JAILBREAK
NSString *documentPath = #"/var/mobile/Library/My_Cool_App";
if (![[NSFileManager defaultManager] fileExistsAtPath:documentPath])
{
[[NSFileManager defaultManager] createDirectoryAtPath:documentPath
withIntermediateDirectories:NO
attributes:nil
error:NULL];
}
return documentPath;
#else
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [documentPaths objectAtIndex:0];
#endif
}

Why does my data successfully write to a file on the iPhone simulator, but not my device?

I have the following code that saves the users sketch data to a file...
//Auto Save the sketch
NSString *filename = [NSString stringWithFormat:#"%#.png", sketchID];
CGImageRef imageRef = CGBitmapContextCreateImage(paintView.canvas.mBitmapContext);
UIImage* image = [[UIImage alloc] initWithCGImage:imageRef];
NSData* imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filename atomically:YES];
CGImageRelease(imageRef);
[image release];
the SketchID is a unique alphanumeric value, so an example of the filename I'm saving to is "p1.png". The code I use to read the file is...
//Load the sketch where the user left off, if there is one
if(fileName != nil)
{
UIImage* image = [UIImage imageWithContentsOfFile:fileName];
if(image != nil)
{
.
.
This code seems to work fine when running on the simulator, but when I run it on the device, the fails to load the image. I new to iOS development and I'm still learning how files are stored. My questions are...
Why would saving/loading the file work on the simulator, but not the device?
When I create the filename that I want to save the data to, do I need to also include a path to a specific directory on the iPhone where the data should be properly stored? Or should "p1.png" work fine when I call the writeToFile: method? And what about the imageWithContentsOfFile: method?
Why would saving/loading the file work
on the simulator, but not the device?
There are tons of reasons, but the most common is trying to write to a location that isn't writable on the device, and the most common reason for that is writing to the application bundle itself.
All iPhone apps are "sandboxed" on the device, meaning they cannot access the filesystem outside of the directory the application is installed into.
When I create the filename that I want
to save the data to, do I need to also
include a path to a specific directory
on the iPhone where the data should be
properly stored? Or should "p1.png"
work fine when I call the writeToFile:
method? And what about the
imageWithContentsOfFile: method?
You can write to your application's temp directory (if you just need a temporarily place to put something during a run) or the Documents directory (if you need to store something more permanently, and also have it backed up by iTunes).
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
I found that the simulator is very forgiving in writing files but the devices of course are not. My problem was that I was creating filePath incorrectly that the simulator did not catch. Simulator should have caught this one.
Here was my wrong and correct swift code
docsDir!+"filename.dat" // wrong does not have path separator between dir and file
docsDir!.stringByAppendingPathComponent("filename.dat") // works since it puts the "/" in between the two.

Document Directory in iPod Touch and iPhone

I'm designing an application that reads data to the iPod touch/iPhone that is sent to it via multicast sockets with UDP and I need to store it as a file in a document directory. Does that exist on on the iPhone or iPod Touch? I know there is NSFileHandle and NSFileManager, which is what I plan on using, to take care of reading and writing to the file, but I'm not sure where the "My Documents" section of the iPod touch is if you know what I'm saying. I am not familiar with the iPod/iPhone file directory that well yet, so any help is appreciated! Is there some kind of "general" directory that all developers use to store their files in if they have any involved in their application?
You should use your application's Documents directory to store persistent files. You can get the path to the directory using this function, which Apple includes in their template for an application using Core Data:
/**
Returns the path to the application's documents directory.
*/
- (NSString *)applicationDocumentsDirectory {
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
More recently, the template for a Core Data application provides code like this:
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
If the returned NSArray from NSSearchPathForDirectoriesInDomains is empty, lastObject returns nil, so as a result, the code is shorter and cleaner.
One thing you should be aware of -- as of iOS 5, you shouldn't put non-user-generated-data to Documents directory. Your app may be rejected. Instead you should think of putting such logs in Caches directory. To get path of this one, you need to replace NSDocumentDirectory with NSCachesDirectory in the above example code.