Verifichiamo da programma la disponibilità delle risorse del nostro iPhone / iPod Touch
by Stefano Lo DucaQuesto breve articolo mostra come sia possibile conoscere alcuni fatti fondamentali riguardanti l’ambiente hardware all’interno del quale il nostro programma è in esecuzione:
- la quantità di memoria utilizzata dal programma e quella ancora disponibile sul dispositivo;
- se la rete WiFi è correntemente attiva;
- se il dispositivo ha la capacità di acquisire immagini o video.

troviamo le risorse ….
Tutte queste funzionalità sono implementate all’interno dell’applicazione AlliDator, un database per iPhone capace di memorizzare non solo informazioni testuali o numeriche ma anche immagini, audio, video ecc. Da qui la necessità di conoscere se il dispositivo può acquisire questo tipo di informazioni, funzionalità che, se presente, viene messa a disposizione dell’utente.
La connessione WiFi viene invece utilizzata per lo scambio di informazioni tra AlliDator e un computer dotato di browser Web, per effettuare un backup completo del database, oppure per esportare e importare singole tabelle e documenti associabili ai record. Verificando la presenza di una connessione WiFi attiva si abilitano queste funzionalità di trasferimento dati.
Nel caso specifico del programma AlliDator la capacità di memorizzare informazioni multimediali e documenti di vario tipo (pdf, rtf, ecc…) può portare il database interno a raggiungere dimensioni considerevoli. Ecco quindi l’importanza di gestire correttamente la memoria e di verificarne regolarmente la disponibilità.
In tutti e tre i casi si tratta comunque di operazioni che possono essere rilevanti per molte altre applicazioni ed abbiamo quindi ritenuto interessante condividere questo breve tutorial su iPhoneAndGo.
Memoria disponibile
Talvolta un programma può generare molti dati, e magari deve funzionare all’interno di un iPhone con 8GB di memoria carico di musica, applicazioni, video. Dovremmo quindi controllare che vi sia spazio sufficiente per i nostri dati.
Il frammento di programma che segue controlla la dimensione di un file (”db.sql”) e lo spazio libero sul dispositivo, e inserisce i due valori all’interno di due campi testuali (UILabel) di una view (usedLabel e spaceLabel, come mostrati in figura).

Naturalmente, questa informazione potremo utilizzarla non solo per mostrarla all’utente, ma anche per controllare se possiamo effettuare delle operazioni che consumano molta memoria, come la copia di files.
1. NSFileManager *fileManager = [NSFileManager defaultManager];
2. NSError *error;
3. NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@”db.sql”];
4. float u = [[[fileManager attributesOfItemAtPath:filePath error:&error]
objectForKey:NSFileSize] floatValue]/1048576;
5. usedLabel.text = [NSString stringWithFormat:@"%.2f MB", u];
6. float m = [[[fileManager attributesOfFileSystemForPath:filePath error:&error]
objectForKey:NSFileSystemFreeSize] floatValue]/1073741824;
7. if (m >= 1.0) spaceLabel.text = [NSString stringWithFormat:@"%.2f GB",m];
8. else spaceLabel.text = [NSString stringWithFormat:@"%.2f MB",m*1024];
Le prima linea di codice dà l’accesso al gestore della memoria permanente; la terza genera la stringa che rappresenta il cammino del file di cui vogliamo conoscere le dimensioni, che è ottenuto attraverso la modalità standard di richiedere il nome della directory dei files di utente di una applicazione, e quindi di concatenarlo con il nome del file.
Nella quarta riga si calcola la dimensione del file in MBytes, chiedendo prima al gestore del file system gli attributi del file che ci interessa (filePath). Questi vengono restituiti come un dizionario, un oggetto di tipo NSDictionary, le cui chiavi descrivono i vari attributi di un file. La costante NSFileSize è la chiave che restituisce la dimensione in caratteri del file, sotto forma di un oggetto NSNumber, che contiene un numero a 64 bit. Questo numero viene convertito a numero reale con floatValue, e il risultato viene diviso per 220 per convertirlo a MBytes. La riga 5 assegna al testo dell’etichetta il valore trovato, formattandolo opportunamente: solo due cifre dopo la virgola, e la stringa “MB” dopo il numero.
Nella riga 6 si richiede invece lo spazio libero disponibile sul dispositivo. Più precisamente, si richiedono gli attributi del file system all’interno del quale si trova il file che ci interessa. In maniera simile al caso precedente, dal dizionario che viene restituito si trova il valore associato alla chiave NSFileSystemFreeSize. Dato che l’ordine di grandezza della memoria dell’iPhone/iPod touch è in GBytes, questa volta si divide per 230 per ottenere il valore in GBytes. Nella riga 7 c’è una piccola raffinatezza: si controlla se il valore dello spazio disponibile è maggiore di 1 GByte, nel qual caso si usa come unità di misura il GByte. Altrimenti, per migliorare la visualizzazione, se lo spazio è minore si converte il numero in MB (così invece di 0.3 GB, ad esempio, apparirà 300 MB) (riga 8).
Presenza della rete WiFi
In questo frammento di programma si verifica la disponibilità della rete WiFi verificando l’accesso allo speciale indirizzo IP 169.254.0.0 che è valido in una rete locale (vedi IPV4 su Wikipedia). Al termine la variabile booleana WiFiIsActive ha valore YES se il dispositivo è all’interno di una rete WiFi, NO altrimenti.
01. BOOL WiFiIsActive = NO;
02. struct sockaddr_in sin;
03. bzero(&sin, sizeof(sin));
04. sin.sin_len = sizeof(sin);
05. sin.sin_family = AF_INET;
06. sin.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
07. SCNetworkReachabilityFlags selfAssignedAddressFlags;
08. SCNetworkReachabilityRef adHocWiFiNetworkReachability =
SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin);
09. if (SCNetworkReachabilityGetFlags(adHocWiFiNetworkReachability,
&selfAssignedAddressFlags)) {
10. WiFiIsActive = ((selfAssignedAddressFlags &
kSCNetworkReachabilityFlagsReachable) &&
11. (selfAssignedAddressFlags & kSCNetworkReachabilityFlagsIsDirect));
12. }
13. CFRelease(adHocWiFiNetworkReachability);
Le righe dalla 2 alla 6 creano una struttura sockaddr_in per rappresentare un indirizzo di rete, e gli assegnano l’indirizzo locale IN_LINKLOCALNETNUM definito uguale a 169.254.0.0 in netinet/in.h (per questo motivo è necessario usare #import nel file in cui metteremo queste righe). Nella riga 8 l’indirizzo viene passato alla funzione SCNetworkReachabilityCreateWithAddress, che restituisce in adHocWiFiNetworkReachability il riferimento ad una struttura che rappresenta la raggiungibilità di un indirizzo di rete o un nome di host (e che poi verrà rilasciata nella riga 13). Quindi nella riga 9 la funzione SCNetworkReachabilityGetFlags, se ha successo, ritorna nella variabile selfAssignedAddressFlags una serie di flag che descrivono la raggiungibilità dell’indirizzo trovato precedentemente. Infine, nelle righe 10 e 11 si interrogano le due proprietà che indicano che l’indirizzo è effettivamente raggiungibile (kSCNetworkReachabilityFlagsReachable) e in maniera diretta (kSCNetworkReachabilityFlagsIsDirect).
Possibilità di fare foto e video
L’ultimo esempio riguarda la disponibilità o meno della camera digitale (iPhone o iPod touch?), e, nel caso in cui questa sia disponibile, se è in grado di effettuare riprese video (iPhone/iPhone 3G oppure iPhone 3GS?).
La classe UIImagePickerController gestisce l’interfaccia per catturare foto e video sui dispositi dotati di questa possibilità. Oltre a questo possiede una serie di metodi di utilità che fanno al caso al nostro. L’espressione:
[UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]
restituisce YES se il dispositivo possiede la camera; non ci dice, però, di che tipo sia. Il frammento di codice seguente risponde allo scopo.
1. BOOL canShotVideo = NO;
2. BOOL canShotPhoto = [UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera];
3. NSArray *mediaTypes;
4. if (canShotPhoto) {
5. mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:
UIImagePickerControllerSourceTypeCamera];
6. canShotVideo = [mediaTypes containsObject:@"public.movie"];
7. }
Nella seconda riga si verifica la disponibilità della camera, quindi canShotPhoto diventa YES in caso positivo, NO altrimenti. Se positivo, nella riga 5 viene chiamato il metodo availableMediaTypesForSourceType che restituisce un array contenente tutti i tipi di “media” disponibili per la camera. Nella riga 6, infine, si controlla se fra questi è compreso il tipo di nome “public.movie”, che denota la possibilità di catturare video. Alla fine di questo frammento, quindi, le due variabili booleane canShotPhoto e canShotVideo ci permetteranno di sapere se il dispositivo in cui il programma è in esecuzione dispone di queste possibilità.
Grazie da iPhone and Go per questo tutorial di Marco Orsini.
Per voi Sir. Lodux !



One Comment. Subscribe to this post comments or trackback.
Novembre 14th, 2009
[...] Leggi il seguito [...]