How to retrieve storage info in iOS - ios

I would like to retrieve the storage information programmatically like capacity, available storage, total number of apps, videos, pics etc.. Thanks in advance..

Try these. Not guaranteed to work on non-jailbroken devices though.
- (NSNumber *) totalDiskSpace
{
NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil];
return [fattributes objectForKey:NSFileSystemSize];
}
- (NSNumber *) freeDiskSpace
{
NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil];
return [fattributes objectForKey:NSFileSystemFreeSize];
}
To count number of files in a directory (including it's sub directories, I've used this (which isn't the most efficient way):
-(NSString *)numberOfSongs
{
NSString *musicPath = #"/var/mobile/Media/iTunes_Control/Music/";
NSArray *dirs = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:musicPath error:nil];
NSArray *subs = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:musicPath error:nil];
int totalFiles;
int subT = [subs count];
int dirT = [dirs count];
totalFiles = subT - dirT;
return [NSString stringWithFormat:#"%i", totalFiles];
}

Looks like WrightsCS answered disk space question.
If you want number of images, check out ALAssetsLibrary of the AssetsLibrary.framework (you'll have to include this framework in your "Link Binary With Libraries" section of the Target settings) and then:
#import <AssetsLibrary/AssetsLibrary.h>
// get the image assets
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSAssert(library, #"Unable to open ALAssetsLibrary");
NSUInteger __block images = 0;
[library enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:^(ALAssetsGroup *group, BOOL *stop){
NSLog(#"%#", group);
images += group.numberOfAssets;
dispatch_async(dispatch_get_main_queue(), ^{
// update my UI with the number of images
});
}
failureBlock:^(NSError *err){
NSLog(#"err=%#", err);
}];
If you want to access the iTunes library on non-jailbroken devices, check out the iPod Library Access Programming Guide, which shows you how to use MPMediaQuery (remember to include the MediaPlayer.framework in your project), and then:
#import <MediaPlayer/MediaPlayer.h>
MPMediaQuery *everything = [[MPMediaQuery alloc] init];
NSAssert(everything, #"Unable to open MPMediaQuery");
iTunesMediaCount = [[everything items] count];
I don't know if there's a published API for getting the number of apps. There are solutions for jailbroken devices, but I don't know about the rest of us.
You didn't ask about this, but if you want available RAM (not flash storage, but memory available for apps), you can get it via:
#import <mach/mach.h>
#import <mach/mach_host.h>
- (void)determineMemoryUsage
{
mach_port_t host_port;
mach_msg_type_number_t host_size;
vm_size_t pagesize;
host_port = mach_host_self();
host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
host_page_size(host_port, &pagesize);
vm_statistics_data_t vm_stat;
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS)
NSLog(#"Failed to fetch vm statistics");
/* Stats in bytes */
natural_t mem_used = (vm_stat.active_count +
vm_stat.inactive_count +
vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize;
natural_t mem_total = mem_used + mem_free;
// do whatever you want with mem_used, mem_free, and mem_total
}

Related

storage greater than system

I want to simulate a shortage of storage, so I try to copy files util the storage is full, but I found it will never get to that, and I found the occuped storage is greater than system, how can this happen?
the code is as follows:
+ (void)copeFiles
{
NSString *srcPath = [self cloudStorageCacheFolderPath];
NSLog(#"copy: src path:%# ,size:%f", srcPath, [self sizeOfcloudStorageCacheFolder]);
int base = 300;
int i = base;
while (1) {
i++;
if (i > base + 100) {
break;
}
NSInteger freeSizeM = [self freeFileStorageSize];
if (freeSizeM > 1024) {
NSString *newFilePath = [NSString stringWithFormat:#"%#-%d", srcPath, i];
[self copyFolderContentFromSrc:srcPath toDestPath:newFilePath];
NSLog(#"copy: i:%d, freeSizeM:%li", i, (long)freeSizeM);
}else {
break;
}
}
}
+ (void)copyFolderContentFromSrc:(NSString *)srcPath toDestPath:(NSString *)dstPath
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSLog(#"copy: src:%# dst:%#", srcPath, dstPath);
BOOL isDir;
if (![fileManager fileExistsAtPath:dstPath isDirectory:&isDir] || !isDir) {
BOOL sucess = [fileManager createDirectoryAtPath:dstPath withIntermediateDirectories:YES attributes:nil error:nil];
NSLog(#"copy: isDir:%d sucess:%d", isDir, sucess);
}
NSArray* array = [fileManager contentsOfDirectoryAtPath:srcPath error:nil];
int i = 0;
for (NSString *fileName in array) {
i++;
NSString *srcFullPath = [srcPath stringByAppendingPathComponent:fileName];
NSString *toFullPath = [dstPath stringByAppendingPathComponent:fileName];
NSError *error;
BOOL isSucess = [fileManager copyItemAtPath:srcFullPath toPath:toFullPath error:&error];
NSLog(#"copy:%d", i);
if (!isSucess) {
NSLog(#"copy:error:%#", error);
}
}
}
image1
image2
The images may be invisible, so I describe the phenomenon simply in advance.My iphone is 32GB in total, but the available storage is 93GB showed in setting.
Yes, It will also increase if you run it again :)
The reason behind it is that It will store the reference only not an actual file. and I have done the same in my mac system to fill the space for simulator and I have ended up with same 256GB system showing 4.3 TB of space
In Device, you can fill space using record a video and still you can not get that error because Apple will manage it like this way.
1) Delete all temporary files that were stored in All App directory.
2) And then Clear cache memory.
Apple will manage the storage space management very well and there is still some mystery about it.

How to get panoramas from ALAsset objects

We have about 2k objects, which are instance of class ALAsset, and we need to know, which files are panoramic images.
We have tried to get CGImageRef from ALAsset instance and check width/height ratio.
ALAsset *alasset = ...
CFImageRef = alasset.thumbnail; // return square thumbnail and not suitable for me
CFImageRef = alasset.aspectRationThumbnail; //return aspect ration thumbnail, but very slowly
It isn't suitable for us, because it works slowly for many files.
Also we have tried to get metadata from defaultRepresentation and check image EXIF, but it works slowly to.
NSDictionary *dictionary = [alasset defaultRepresentation] metadata]; //very slowly to
Is there any way to make it better?
Thanks
Finaly, I've found this solution for ALAsset:
ALAssetsLibrary *assetsLibrary = ...;
NSOperation *queue = [NSoperationQueue alloc] init];
static NSString * const kAssetQueueName = ...;
static NSUInteger const kAssetConcurrentOperationCount = ...; //I use 5
queue.maxConcurrentOperationCount = kAssetConcurrentOperationCount;
queue.name = kAssetQueueName;
dispatch_async(dispatch_get_main_queue(), ^{
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
/*You must check the group is not nil */
if (!group)
return;
/*Then you need to select group where you will search panoramas: for iPhone-Simulator it's #"Saved Photos" and "Camera Roll" for iPhone. It's actuality only for iOS 7 or early. */
static NSString * const kAssetGroupName = ...;
if ([[group valueForProperty:ALAssetsGroupPropertyName] kAssetGroupName]) {
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
if (!asset)
return;
[queue addOperationWithBlock:^{
//I use #autoreleasepool for instant memory release, after I find panoramas asset url
#autoreleasepool {
ALAssetRepresentation *defaultRepresentation = asset.defaultRepresentation;
if ([defaultRepresentation.UTI isEqualToString:#"public.jpeg"]) {
NSDictionary *metadata = defaultRepresentation.metadata;
if (!metadata)
return;
if (metadata[#"PixelWidth"] && metadata[#"PixelHeight"]) {
NSInteger pixelWidth = [metadata[#"PixelWidth"] integerValue];
NSInteger pixelHeight = [metadata[#"PixelHeight"] integerValue];
static NSUInteger const kSidesRelationshipConstant = ...; //I use 2
static NSUInteger const kMinimalPanoramaHeight = ...; //I use 600
if (pixelHeight >= kMinimalPanoramaHeight && pixelWidth/pixelHeight >= kSidesRelationshipConstant) {/*So, that is panorama.*/}
}
}];
}];
}
} failureBlock:^(NSError *error) {
//Some failing action, you know.
}];
};
That is. So, I think that is not the best solution. However, for today I have not found any better.

Calculating documents and data storage used IOS7

I am trying to find the total size of the documents directory of my IOS app. I believe it is the value that I see in the Settings app under usage (documents and data, this value now is 40MB). By using this method:
-(int)sizeOfFolder:(NSString *)folderPath
{
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:nil];
NSEnumerator *contentsEnumurator = [contents objectEnumerator];
NSString *file;
unsigned long long int folderSize = 0;
while (file = [contentsEnumurator nextObject]) {
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:file] error:nil];
folderSize += [[fileAttributes objectForKey:NSFileSize] intValue];
}
//This line will give you formatted size from bytes ....
//NSString *folderSizeStr = [NSByteCountFormatter stringFromByteCount:folderSize countStyle:NSByteCountFormatterCountStyleFile];
NSLog(#"size: %llu", folderSize);
return folderSize;
}
I get always the same value. This is the path I pass onto the method:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* rootPath = [paths objectAtIndex:0];
int space = [self sizeOfFolder:rootPath];
First of all you should be careful with file types. You should use long long to be able to calculate the total size:
unsigned long long folderSize = 0; // remove int here
// ...
folderSize += [[fileAttributes objectForKey:NSFileSize] longLongValue]; // note longLongValue
Next you should skip directories to get more accurate results
if (![fileAttirbutes[NSFileType] equalsToString:NSFileTypeDirectory]) {
folderSize += ...
}
I would recommend you to look at another directory enumeration approach. Using - (NSDirectoryEnumerator *)enumeratorAtURL:(NSURL *)url includingPropertiesForKeys:(NSArray *)keys options:(NSDirectoryEnumerationOptions)mask errorHandler:(BOOL (^)(NSURL *url, NSError *error))handler will allow you to perform deeper directory enumeration and list all directory contents recursively
unsigned long long count = 0;
NSNumber *value = nil;
for (NSURL *url in [[NSFileManager defaultManager] enumeratorAtURL:directoryURL includingPropertiesForKeys:#[NSURLFileSizeKey] options:0 errorHandler:NULL]) {
if ([url getResourceValue:&value forKey:NSURLFileSizeKey error:outError]) {
count += [value longLongValue];
} else {
return nil;
}
}
return #(count);
NSFileManager has no capabilities of returning the size of a folder(a folder + contents). Found this on Internet.
- (unsigned long long) fastFolderSizeAtFSRef:(FSRef*)theFileRef {
FSIterator thisDirEnum = NULL;
unsigned long long totalSize = 0;
// Iterate the directory contents, recursing as necessary
if (FSOpenIterator(theFileRef, kFSIterateFlat, &thisDirEnum) == noErr)
{
const ItemCount kMaxEntriesPerFetch = 256;
ItemCount actualFetched;
FSRef fetchedRefs[kMaxEntriesPerFetch];
FSCatalogInfo fetchedInfos[kMaxEntriesPerFetch];
// DCJ Note right now this is only fetching data fork sizes... if we decide to include
// resource forks we will have to add kFSCatInfoRsrcSizes
OSErr fsErr = FSGetCatalogInfoBulk(thisDirEnum, kMaxEntriesPerFetch, &actualFetched,
NULL, kFSCatInfoDataSizes | kFSCatInfoNodeFlags, fetchedInfos,
fetchedRefs, NULL, NULL);
while ((fsErr == noErr) || (fsErr == errFSNoMoreItems))
{
ItemCount thisIndex;
for (thisIndex = 0; thisIndex < actualFetched; thisIndex++)
{
// Recurse if it's a folder
if (fetchedInfos[thisIndex].nodeFlags & kFSNodeIsDirectoryMask)
{
totalSize += [self fastFolderSizeAtFSRef:&fetchedRefs[thisIndex]];
}
else
{
totalSize += fetchedInfos [thisIndex].dataLogicalSize;
}
}
if (fsErr == errFSNoMoreItems)
{
break;
}
else
{
// get more items
fsErr = FSGetCatalogInfoBulk(thisDirEnum, kMaxEntriesPerFetch, &actualFetched,
NULL, kFSCatInfoDataSizes | kFSCatInfoNodeFlags, fetchedInfos,
fetchedRefs, NULL, NULL);
}
}
FSCloseIterator(thisDirEnum);
}
return totalSize; }

Get System Information such as OS Version, battery, storage, memory and so on [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am working on an app which needs to display some device information, Could some one help me to verify if that's legal to pull this information and maybe some code snippets would be very helpful.
Thanks in advance !
Device information:
Remain Battery Status
Is phone charging
Device OS version
Current App version
Available Memory
Available Storage
I think all those information are legal to pull. and here are some code for each of them
Remain battery:
UIDevice *device = [UIDevice currentDevice];
[device setBatteryMonitoringEnabled:YES];
float remainBatteryLife = [myDevice batteryLevel];
Phone charging status
//same device object as the previous one
UIDevice *device = [UIDevice currentDevice];
[device setBatteryMonitoringEnabled:YES];
int i=[myDevice batteryState];
switch (i)
{
case UIDeviceBatteryStateUnplugged:
//Unplugged
break;
case UIDeviceBatteryStateCharging:
//Charging
break;
case UIDeviceBatteryStateFull:
//full
break;
default:
break;
}
OS version
NSString *OSVersion = [[UIDevice currentDevice] systemVersion];
App version
NSString *majorVersion = [infoDictionary objectForKey:#"CFBundleShortVersionString"];
NSString *minorVersion = [infoDictionary objectForKey:#"CFBundleVersion"];
Available Memory (For this question, i used some C codes instead of Objective-C, but that returns exactly like itunes would tell you, inspired by https://sites.google.com/site/iphonedevnote/Home/get-available-memory)
//import some C libraries first
#import <mach/mach.h>
#import <mach/mach_host.h>
//then put these code in whichever method it needs to be
mach_port_t host_port;
mach_msg_type_number_t host_size;
vm_size_t pagesize;
host_port = mach_host_self();
host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
host_page_size(host_port, &pagesize);
vm_statistics_data_t vm_stat;
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS)
NSLog(#"Failed to fetch vm statistics");
/* Stats in bytes */
natural_t mem_used = (vm_stat.active_count +
vm_stat.inactive_count +
vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize;
natural_t mem_total = mem_used + mem_free;
natural_t memoryFactor = 1024;
NSLog(#"used: %u MB free: %u MB total: %u MB", (mem_used / memoryFactor) / memoryFactor, (mem_free / memoryFactor) /memoryFactor, (mem_total /memoryFactor) /memoryFactor);
Disk space (code source From Code Warrior on https://stackoverflow.com/a/8036586/3276557)
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
NSLog(#"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
} else {
NSLog(#"Error Obtaining System Memory Info: Domain = %#, Code = %#", [error domain], [error code]);
}
You are looking for the UIDevice class. Some code sni
UIDevice *currentDevice = [UIDevice currentDevice];
NSString * batteryLevel = [currentDevice batteryLevel];
NSString *systemVersion = [currentDevice systemVersion];

iOS SoundTouch framework BPM Detection example

I have searched all over the web and cannot find a tutorial on how to use the SoundTouch library for beat detection.
(Note: I have no C++ experience prior to this. I do know C, Objective-C, and Java. So I could have messed some of this up, but it compiles.)
I added the framework to my project and managed to get the following to compile:
NSString *path = [[NSBundle mainBundle] pathForResource:#"song" ofType:#"wav"];
NSData *data = [NSData dataWithContentsOfFile:path];
player =[[AVAudioPlayer alloc] initWithData:data error:NULL];
player.volume = 1.0;
player.delegate = self;
[player prepareToPlay];
[player play];
NSUInteger len = [player.data length]; // Get the length of the data
soundtouch::SAMPLETYPE sampleBuffer[len]; // Create buffer array
[player.data getBytes:sampleBuffer length:len]; // Copy the bytes into the buffer
soundtouch::BPMDetect *BPM = new soundtouch::BPMDetect(player.numberOfChannels, [[player.settings valueForKey:#"AVSampleRateKey"] longValue]); // This is working (tested)
BPM->inputSamples(sampleBuffer, len); // Send the samples to the BPM class
NSLog(#"Beats Per Minute = %f", BPM->getBpm()); // Print out the BPM - currently returns 0.00 for errors per documentation
The inputSamples(*samples, numSamples) song byte information confuses me.
How do I get these pieces of information from a song file?
I tried using memcpy() but it doesn't seem to be working.
Anyone have any thoughts?
After hours and hours of debugging and reading the limited documentation on the web, I modified a few things before stumbling upon this: You need to divide numSamples by numberOfChannels in the inputSamples() function.
My final code is like so:
NSString *path = [[NSBundle mainBundle] pathForResource:#"song" ofType:#"wav"];
NSData *data = [NSData dataWithContentsOfFile:path];
player =[[AVAudioPlayer alloc] initWithData:data error:NULL];
player.volume = 1.0; // optional to play music
player.delegate = self;
[player prepareToPlay]; // optional to play music
[player play]; // optional to play music
NSUInteger len = [player.data length];
soundtouch::SAMPLETYPE sampleBuffer[len];
[player.data getBytes:sampleBuffer length:len];
soundtouch::BPMDetect BPM(player.numberOfChannels, [[player.settings valueForKey:#"AVSampleRateKey"] longValue]);
BPM.inputSamples(sampleBuffer, len/player.numberOfChannels);
NSLog(#"Beats Per Minute = %f", BPM.getBpm());
I've tried this solution to read the BPM from mp3 files (using the TSLibraryImport class to convert to wav) inside the iOS Music Library:
MPMediaItem *item = [collection representativeItem];
NSURL *urlStr = [item valueForProperty:MPMediaItemPropertyAssetURL];
TSLibraryImport* import = [[TSLibraryImport alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSURL* destinationURL = [NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:#"temp_data"]];
[[NSFileManager defaultManager] removeItemAtURL:destinationURL error:nil];
[import importAsset:urlStr toURL:destinationURL completionBlock:^(TSLibraryImport* import) {
NSString *outPath = [documentsDirectory stringByAppendingPathComponent:#"temp_data"];
NSData *data = [NSData dataWithContentsOfFile:outPath];
AVAudioPlayer *player =[[AVAudioPlayer alloc] initWithData:data error:NULL];
NSUInteger len = [player.data length];
int numChannels = player.numberOfChannels;
soundtouch::SAMPLETYPE sampleBuffer[1024];
soundtouch::BPMDetect *BPM = new soundtouch::BPMDetect(player.numberOfChannels, [[player.settings valueForKey:#"AVSampleRateKey"] longValue]);
for (NSUInteger i = 0; i <= len - 1024; i = i + 1024) {
NSRange r = NSMakeRange(i, 1024);
//NSData *temp = [player.data subdataWithRange:r];
[player.data getBytes:sampleBuffer range:r];
int samples = sizeof(sampleBuffer) / numChannels;
BPM->inputSamples(sampleBuffer, samples); // Send the samples to the BPM class
}
NSLog(#"Beats Per Minute = %f", BPM->getBpm());
}];
The strangeness is that the calculated BMP is always the same value:
2013-10-02 03:05:36.725 AppTestAudio[1464:1803] Beats Per Minute = 117.453835
No matter which track was i.e. number of frames or the buffer size (here I used 2K buffer size as for the SoundTouch example in the source code of the library).
For Swift 3:
https://github.com/Luccifer/BPM-Analyser
And use it like:
guard let filePath = Bundle.main.path(forResource: "TestMusic", ofType: "m4a"),
let url = URL(string: filePath) else {return "error occured, check fileURL"}
BPMAnalyzer.core.getBpmFrom(url, completion: nil)
Feel free to comment!

Resources