Archivi categoria: Titanium

Debug e profilazione di un’applicazione Titanium (e non solo) su Android Studio

Di recente mi è capitato di dover fare un po’ di profilazione di un’applicazione mobile scritta con Titanium per Android, principalmente per accertarmi dell’assenza di memory leaks in alcuni punti.
Su iOS è facile, perché Xcode mette a disposizione tutto il necessario (tempo fa scrissi un articoletto al riguardo), su Android non avevo mai provato.

Avevo notato che aprendo Android Studio e usando l’applicazione in oggetto sul logcat (console dei log) di Android Studio veniva sparato l’output, ma sul fronte RAM e CPU era tutto fermo.
È stato sufficiente mettere a true il flag android:debuggable sul file tiapp.xml e come per magia riavviando l’applicazione e selezionandola sull’Android Monitor i diagrammi sull’utilizzo delle risorse hanno preso vita.
Questa cosa funziona con tutte le applicazioni in cui si può abiltare il flag debuggable sul manifest Android, quindi per esempio anche usando Xamarin.

Il flag incriminato

Il flag incriminato

I pannelli sull'utilizzo delle risorse

I pannelli sull’utilizzo delle risorse

Per completezza aggiungo un articolo sulla documentazione di Titanium che spiega come ricercare i memory leaks su iOS e Android, ma senza menzionare l’opzione Android Studio.
https://wiki.appcelerator.org/display/guides2/Managing+Memory+and+Finding+Leaks#ManagingMemoryandFindingLeaks-MonitoringallocationsonAndroid

Niente di trascendentale ma magari qualcun altro non aveva mai provato.

Set di icone monocromatiche? Praticamente un font…

inkscape-icon

Purtroppo è da parecchio che non sto più tanto dietro allo sviluppo web, e quindi alcune “novità” tendono ad arrivarmi tardi (leggero eufemismo). La tendenza di usare icone monocromatiche su applicazioni web non è cosa recente, e la somiglianza tra la lettera di un font e un’icona monocromatica è stata notata da tempo, tanto che almeno dal 2010 c’è chi ha avuto l’idea di realizzare “font di icone” per utilizzarle come “icone vettoriali” sul web.
A me questa cosa è arrivata soltanto cinque o sei mesi fa quando mi è stato mostrato Font-Awesome. Mea culpa.

Set di font come se piovesse

Non è mai facile stabilire se sia nato prima l’uovo o la gallina, di certo c’è che le icone sono sempre più monocromatiche, e di set di font con icone di ogni genere ce ne sono ormai una marea. Purtroppo regala’ è morto, e l’utilizzo della maggior parte di questi pacchetti impone il pagamento di licenze o l’inserimento degli autori nei credits/ringraziamenti, a meno di non utilizzare quei set rilasciati con licenza Creative commons che sono originali come l’acqua calda.

Font custom, Inkscape e Icomoon

Tra gli strumenti per realizzare immagini vettoriali uno dei più usati è Inkscape (gratuito e open-source), ma non tutti sanno che in Inkscape è presente anche un editor di font con cui è possibile “raggruppare” dei glifi assegnando a ciascuno un “carattere”, realizzando di fatto un font.
Qui una bella guida sul tema, mentre qui si può trovare un progetto Github con risorse utili per crearsi i propri font.
inkscape-font-editor

Ricapitolando: con Inkscape – partendo da immagini vettoriali – si può arrivare a creare un “font svg” convertibile poi in TrueType (ttf) tramite strumenti esterni. E se non si ha voglia di fare tutti questi passaggi? Come è logico aspettarsi ci sono delle alternative.
Una strada è quella di installarsi un editor di font come FontForge, importarsi i propri glifi svg (opportunamente modificati), e crearsi il font a mano.
Strada più semplice è quella di rivolgersi a un servizio online. Ne ho provati alcuni (tra cui Fontastic), e alla fine l’unico che mi ha sempre importato gli svg e esportato i font correttamente senza distorsioni o ridimensionamenti strani è stato IcoMoon.
icomoon
IcoMoon è di una semplicità disarmante: si selezionano delle icone prese da librerie gratuite/a pagamento messe a disposizione dal sito o tra quelle importate da noi stessi e le si esportano in un pacchetto contenente il font in vari formati più tutte le risorse utili, con possibilità di configurarne anche i codici/nomi delle classi css e adattarne le dimensioni.

“Icone vettoriali” in Titanium

Veniamo alle origini di quest’articolo, visto che come dicevo all’inizio lo sviluppo web purtroppo l’ho abbandonato da un po’ di tempo.
Nel mondo dello sviluppo mobile un problema piuttosto sentito è quello della preparazione di icone e immagini alle varie risoluzioni per una buona resa su tutti i dispositivi che si ha intenzione di gestire. Il problema è ancora più marcato nello sviluppo multipiattaforma perché android e ios (per dirne due) seguono convenzioni dei nomi che non c’entrano niente l’una con l’altra, oltre a girare su dispositivi che gestiscono risoluzioni diverse.
Da un’esigenza nasce (quasi) sempre una soluzione, e in Titanium una parziale soluzione l’ha proposta uno degli sviluppatori di riferimento per questa piattaforma – Fokke Zandbergen – che ha dato alla luce TiCons.
Con TiCons si possono generare le icone dell’app e gli splash screens per tutti i dispositivi, ma la gestione delle immagini usate “all’interno” dell’app resta responsabilità nostra. Per far questo bisogna solitamente ingegnarsi con ImageMagick, che permette di fare velocemente elaborazioni anche complesse a grosse quantità di immagini tramite scripts. Questa cosa però è noiosa e così spesso si finisce per usare immagini con risoluzioni non adatte.

In una delle applicazioni di esempio corporate-directory si vede come sia possibile utilizzare “icone vettoriali” al posto di quelle raster semplicemente aggiungendo il nostro “font contenente le icone” all’interno della directory app/assets/fonts, impostando la proprietà font.fontFamily uguale al nome del font che abbiamo aggiunto e settando la proprietà testuale (es: “text” per le Label o “value” per i TextField) uguale al codice del carattere che rappresenta la nostra icona… più difficile a dirsi che a farsi, basta guardare l’esempio.

Un "esempio riepilogativo" con tutti i pezzi

Un “esempio riepilogativo” con tutti i pezzi

Gli effetti positivi di questa soluzione sono evidenti:

  • miglior renderizzazione delle immagini
  • minor dimensione delle applicazioni
  • possibilità di modificare dimensioni e colori delle icone velocemente e anche a runtime
  • nessun problema in caso di installazione su dispositivi non previsti inizialmente
  • possibilità di cambiare tutto il set di icone anche a runtime semplicemente modificando il nome del font in una classe tss
  • probabilmente ce ne saranno altri che non mi vengono

Un limite è che questa cosa si può fare solo su quel tipo di componenti dove il font (e quindi il font-family) è modificabile, questo significa che per i Tab e forse anche altrove purtroppo bisogna continuare a usare delle immagini raster.

Imparata questa tecnica mi è venuta voglia di usarla dappertutto… non appena sbatterò il muso da qualche parte aggiornerò quest’articolo, per il momento mi godo tutti i punti di cui sopra.

Da Appcelerator Studio a Atom: passaggio abbastanza indolore

Chi sviluppa con Titanium sa che in questo mondo – che poi è solo un sottoinsieme del mondo Javascript – c’è chi utilizza la command line e l’editor/ide di preferenza, e chi preferisce rimanere al calduccio utilizzando tutti e solo gli strumenti messi a disposizione da dalla casa-madre Appcelerator, ovvero Appcelerator Studio.
Appcelerator Studio in se non sarebbe troppo male, il problema è che una versione modificata (e neanche troppo bene) di Eclipse si porta quindi dietro la sua estensibilità ma anche la sua pesantezza. In più a volte ti si blocca mentre stai facendo operazioni banali come aggiungendo stringhe al file strings.xml costringendoti a buttare giù tutto e facendoti perdere del lavoro (le bestemmie che ho tirato giù a causa di questo problema sono veramente tante).
A volte succede anche che l’integrazione con gli stessi servizi di Appcelerator smettano di funzionare, ed è noto come la recente impossibilità di fare build su iOS abbia seminato il caos e costretto molti a un utilizzo più consapevole della CLI.

Sublime? No, Atom

Buona parte dei migliori sviluppatori che conosco, e che hanno a che fare con Titanium, si affidano a Sublime Text, un editor (termine riduttivo) veramente veloce e ben fatto. Per Sublime ci sono plugin di ogni genere, e Titanium non fa eccezione:
https://github.com/AoDev/ti-alloy-in-sublime-text-2
https://github.com/MattTuttle/sublime-ti-build
A me però non va di pagare per utilizzare un editor non open-source, e il simpatico messaggio che compare sempre più spesso con cui invitano ad acquistare una licenza mi da abbastanza fastidio.
sublime-purchase-alert

Chi non usa Sublime ha due grosse alternative: Atom e Visual Studio Code. L’editor di Microsoft (ancora in preview) è molto bello e funziona bene specialmente con linguaggi della galassia Microsoft (vedi Typescript), ma per il resto forse gli è preferibile Atom, giunto da poco alla versione 1.0 e con una miriade di plugins che aumentano e migliorano giorno dopo giorno.

Configurare Atom con il minimo necessario per sviluppare con Titanium

atom
Scelta fatta. Per programmare in Javascript potenzialmente basterebbe un blocco note, e per fare le build con Titanium c’è la CLI, però magari utilizzare qualche aiuto potrebbe non essere una cattiva idea.
Per avere un minimo di auto-completamento ho installato questo plugin che funziona bene:
https://atom.io/packages/titanium-alloy
che ha anche un’integrazione con hyperclick:
https://atom.io/packages/hyperclick

Auto-completamenti e auto-formattazioni non mi hanno mai fatto impazzire, ma un check statico del codice in tempo reale che segnali eventuali imprecisioni ma anche errori e pratiche di cattiva programmazione mi è sempre piaciuto averlo, e su Appcelerator Studio i linter latitano o funzionano male. Un linter è prezioso nel mondo javascript specialmente quando si lavora in squadra, perché sebbene in questi casi si tenda a scrivere in modo simile spesso non lo si fa abbastanza.

In Atom non solo si può installare ESLint, ma si può creare un file di configurazione del linter per ogni progetto.
https://atom.io/packages/linter
https://atom.io/packages/linter-eslint

{
	"globals": {
		"Ti": false,
		"Titanium": false,
		"Alloy": false,
		"$": false,
		"_": false,
		"L": false,
		"arguments": false,
		"require": false,
		"module": false,
		"exports": true,
		"OS_ANDROID": false,
		"OS_IOS": false,
		"ENV_PRODUCTION": false,
		"ENV_DEV": false,
		"setInterval": false,
		"clearInterval": false,
		"setTimeout": false,
		"clearTimeout": false,
		"alert": false,
		"describe": false,
		"it": false,
		"beforeEach": false,
		"afterEach": false
	},
	"rules": {
		"strict": [2, "never"],
		"new-cap": [2, {"capIsNewExceptions": ["L"]}],
		"no-trailing-spaces": [1, { "skipBlankLines": true }],
		"space-infix-ops": [1, {"int32Hint": false}],
		"comma-spacing": [1, {"before": false, "after": true}],
		"key-spacing": [1, {"beforeColon": false, "afterColon": true}],
		"semi-spacing": [1, {"before": false, "after": true}],
		"dot-notation": 1,
		"no-underscore-dangle": 1,
		"no-unused-vars": 1,
		"no-multi-spaces": 1,
		"quotes": [1, "double"],
		"eol-last": 0,
		"no-alert": 0
	}
}

In “globals” si elencano le variabili globali, specificando anche se possono essere assegnate oppure no.
In “rules” si specificano le regole di validazione, indicando se eventuali infrazioni vanno segnalate in rosso come errori (con il 2) o in giallo come warnings (con l’1). Lo 0 le disabilita.
Qui sono elencate tutte le regole di validazione di ESLint.

Altri plugins utili per Atom

Di estensioni ce ne sono una marea, e ognuno ha le sue esigenze, ma finora che mi sono piaciute ce ne sono due in particolare.
Un terminale integrato:
https://atom.io/packages/Termrk
E un project-manager che facilita il passaggio da un progetto all’altro:
https://atom.io/packages/project-manager

Titanium CLI

Come tutti sanno dalla CLI si può fare tutto quello che si fa con Appcelerator Studio. In teoria.
Una cosa che da quanto ne so funziona su Studio ma non sulla CLI è il LiveView, o almeno a me funziona solo su Studio, quando funziona.

Per fare le build io nella mia quasi totale incapacità di scrivere per bash mi sono creato questo script, semplice ma abbastanza efficace. Non è gestito il –liveview perché tanto non funziona.

# The platform: ios or android
PLATFORM=$1
if [ "$PLATFORM" == "" ]; then
	PLATFORM="android"
fi

# The target: device, simulator (ios) or emulator (android)
TARGET=$2
if [ "$TARGET" == "" ]; then
	TARGET="device"
fi

# Y for choosing destination, N for the default
CHOICE=$3
if [ "$CHOICE" == "" ]; then
	CHOICE="N"
fi

if [ "$CHOICE" == "Y" ]; then
	appc ti build --platform $PLATFORM --log-level debug --target $TARGET --skip-js-minify --device-id
else
	appc ti build --platform $PLATFORM --log-level debug --target $TARGET --skip-js-minify
fi

Per fare i deploy (ipa e apk) invece mi sono fatto questo script, forse anche più brutto del precedente:

SRC_PROJECT_NAME="My Project"
DEST_FILE_NAME="MyProject"
OUTPUT_DIR=~/Documents/$DEST_FILE_NAME
ANDROID_OUTPUT_DIR=build/android/bin
IOS_DIST_NAME="My company"
IOS_DIST_UUID="................"

mkdir -p $OUTPUT_DIR

appc ti build --platform ios --build-only --force --log-level info --device-family ipad --target dist-adhoc --distribution-name $IOS_DIST_NAME --pp-uuid $IOS_DIST_UUID --output-dir $OUTPUT_DIR
mv $OUTPUT_DIR"/$SRC_PROJECT_NAME.ipa" $OUTPUT_DIR"/$DEST_FILE_NAME.ipa"

appc ti build --platform android --build-only --force --log-level info
cp $ANDROID_OUTPUT_DIR"/$SRC_PROJECT_NAME.apk" $OUTPUT_DIR"/$DEST_FILE_NAME.apk"

Conclusioni

Appcelerator sembra sulla via del tramonto, opinione diffusa anche nella community. L’aumento di stabilità su Android negli ultimi mesi/anni è evidente e le prestazioni non sono malaccio, ma l’esperienza di sviluppo è pessima rispetto ad altre piattaforme, e il quasi totale abbandono della “gratuità” di sei mesi fa le hanno fatto fare dei passi indietro tra le preferenze degli sviluppatori.
Forse si riprenderanno o forse no, resta il fatto che iniziare a utilizzare con profitto strumenti più generici e utilizzabili anche in altri ambiti può non essere una cattiva idea.
Magari dobbiamo continuare a usare l’SDK di Titanium sui nostri progetti, ma fortunatamente (ancora) nessuno ci obbliga a utilizzare tutti gli strumenti di sviluppo di Appcelerator.

Snellire la libreria google-play-services.jar con Android ProGuard

L’altro giorno stavo cercando di gestire i Google Analytics in una semplice applicazione mobile che sto sviluppando per conto mio con Titanium, ma quando sono andato ad aggiungere il modulo ti.ga non sono più riuscito a compilare niente a causa di un errore dovuto evidentemente a dei conflitti tra librerie.

L’errore di compilazione era questo:
[ERROR] : UNEXPECTED TOP-LEVEL EXCEPTION:
[ERROR] : java.lang.IllegalArgumentException: already added:Lcom/google/android/gms/maps/LocationSource;

Cercando in giro ho avuto la conferma che il problema era dovuto all’inclusione di una libreria google-play-services.jar all’interno del modulo, che faceva a cazzotti con quelle usate in un altro modulo importato nel mio progetto: ti.map.
Per completezza è necessario dire che la libreria ti.map – insieme alle altre native di Titanium – è accessibile in /Utenti/m.piccotti/Library/Application Support/Titanium/modules/android.

Classi duplicate, che fare

Il problema è comune e in molti sul web se ne lamentano, non solo parlando di Titanium e di questi moduli. Ovviamente non si può pensare di eliminare la libreria contenente le implementazioni delle api necessarie al modulo, ma lì per lì non sapevo che fare, finché non ho guardato meglio un altro modulo che mi serviva: ti.admob.
A differenza di ti.map il modulo ti.admob va tirato giù da GitHub e importato nel progetto, quindi mi è balzata all’occhio la presenza delle librerie google-play-services-base.jar e google-play-services-ads.jar; guardando il log ho notato il messaggio che mi interessava:
[DEBUG] : Skipping duplicate jar file: project_directory/modules/android/ti.admob/2.1.6/lib/google-play-services-base.jar

In sostanza Titanium evita l’importazione di librerie duplicate, ma la google-play-services.jar presente all’interno del modulo ti.ga non risultava duplicata ai controlli di Titanium, e il risultato era una duplicazione delle classi Android in fase di compilazione in presenza del modulo all’interno del progetto.

La soluzione

Quando non si sa dove sbattere la testa conviene sempre fare come gli altri, ho quindi preso la libreria google-play-services_base.jar dal modulo ti.admob (sviluppato da quelli di Appcelerator), e mi sono andato a cercare un jar contenente solo le librerie di Google Analytics. Naturalmente non ho trovato niente di simile, ma ero sulla strada giusta.

Pulizie manuali del jar

Mi serviva un jar contenente solo le classi necessarie al funzionamento di Google Analytics. Da ignorante nello sviluppo nativo Android ho fatto quello che avrebbe fatto qualunque altro bimbominkia, scompattando il jar e ricompattandolo solo dopo aver eliminato tutti i package fuori da “analytics”.

Forse un po' troppo drastico

Forse un po’ troppo drastico


Non ha funzionato, per la cronaca comunque un jar si può decomprimere con qualunque utility di decompressione file o con il comando:
jar xf google-play-services-analytics.jar
e si può ricreare con:
jar cf google-play-services-analytics.jar ./com.
Qui si spiega come funziona il comando per la creazione dei jar, questa cosa mi è comunque servita alla fine.

Android ProGuard

Effettivamente ripulire a mano le classi di una libreria sconosciuta aveva probabilità di successo pari a 0.00001, e io non sono così fortunato. Ho trovato però nel giro di poco la soluzione: ProGuard.
ProGuard è un tool che serve per ottimizzare e offuscare il codice Android. A me interessava eliminare dalla libreria google-play-services.jar inclusa nel modulo non funzionante tutto il superfluo lasciando solo la parte di analytics, e questa cosa si fa abbastanza agevolmente.

-injars google-play-services.jar
-outjars google-play-services-analytics.jar

-libraryjars /usr/local/Android/sdk/extras/android/support/v4/android-support-v4.jar
-libraryjars /usr/local/Android/sdk/platforms/android-21/android.jar

-dontoptimize
-dontobfuscate
-dontwarn com.google.**.R
-dontwarn com.google.**.R$*
-dontnote

-keep public class com.google.android.gms.analytics.**  {
    public protected *;
}

Vittoria in (quasi) quattro mosse:

  • includere questi comandi in un file di configurazione (chiamato ad esempio proguard.cfg)
  • copiare il file di configurazione appena creato e la libreria “onnicomprensiva” google-play-services.jar all’interno di /usr/local/Android/sdk/tools/proguard/lib (o comunque all’interno della directory dove si trova proguard.jar)
  • installare android-support-v4.jar se mancante, con l’Android SDK manager
  • eseguire il comando java -jar proguard.jar @proguard.cfg

ga-android-tools-proguard
… e il file salvifico compare magicamente all’interno della stessa directory.

Conclusioni

Ovviamente non è vero che il file risultante funzionava, infatti ho dovuto eliminare a mano tre o quattro classi da quest’ultimo come spiegato nella sezione “Pulizie manuali del jar”.
Il risultato è stato che finalmente quello che doveva funzionare ha funzionato, ma anche che le due librerie “base” e “analytics” pesano insieme meno della metà di quella unica, cosa non di poco conto nel mondo Android.

Appcelerator Titanium, licenza indie e sviluppo enterprise

È passato poco più di un mese da quando Jeff Haynie ha annunciato in pompa magna le grandi novità in casa Appcelerator.
Una di queste – la “monetizzazione” dell’sdk Titanium da parte dell’azienda – non è stata accolta con grande entusiasmo, e qualche giorno dopo andando a leggere sul loro sito il dettaglio delle licenze mi sono allarmato leggendo queste parole: “You may choose to purchase multiple Indie plans, but the users of these seats cannot see or share work with one another”.

Dicitura alquanto preoccupante che spiega le limitazioni della licenza Indie

Dicitura alquanto preoccupante che spiega le limitazioni della licenza Indie


Quel “share work” mi ha fatto preoccupare un po’, perché è vero che come utilizzatore precedente ho diritto a una licenza indie gratuita e permanente, ma è altrettanto vero che lavoro in un’azienda insieme ad altra gente, e lì per lì ci ho visto nero. Un mio tweet al veleno ha attirato l’attenzione di Ricardo Alcocer (Director of Developer Relations and Training), il quale preoccupato si è affrettato a chiarire i miei dubbi spiegandomi che “the Indie account will not allow you to share app’s backend data with other Indie developers”. In pratica a detta sua l’unico limite sarebbe stato nella condivisione di backend e analytics tra utenti non registrati come parte di un’unica organizzazione.

Il test con il doppio account

L’altro giorno finalmente mi è arrivato l’invito per utilizzare in anteprima la versione 4.0 (ancora alla RC2) con l’account registrato a nome dell’azienda, e dal momento che avevo già un invito sul mio account personale sono riuscito a fare i test di lavoro con più account sullo stesso progetto. Ho quindi importato uno dei progetti sviluppati in azienda con l’account aziendale, ho fatto qualche test e poi sono uscito da Appcelerator Studio eseguendo il login seguente con il mio account personale, per vedere cosa sarebbe successo.

…e quando invece si esegue il login con un account diverso da quello con cui si è registrata l’app

…e quando invece si esegue il login con un account diverso da quello con cui si è registrata l’app

…e quando invece si esegue il login con un account diverso da quello con cui si è registrata l’app

…e quando invece si esegue il login con un account diverso da quello con cui si è registrata l’app


Aprendo il tiapp.xml si nota il messaggio di warning in cui si spiega che l’applicazione è associate a un’organizzazione di cui non si fa parte e in cui si consiglia di farsi aggiungere in tale organizzazione… facendo pagare a quell’organizzazione delle (costose) licenze Team o Enterprise.

In Appcelerator controllano e registrano tutto

Il problema vero non è tanto il non aver accesso ai servizi web di Appcelerator, quanto che lanciando l’applicazione l’sdk fallisce il processo di build: Application not registered. In pratica a ogni creazione di una nuova applicazione (o importazione di un’applicazione esistente) viene generato un guid univoco che viene associato all’appid, e sulla console web dell’utente (o meglio dell’azienda correntemente selezionata dallo sviluppatore) compare una coppia di applicazioni: quella mobile (Titanium) e l’Arrow DB.
Se si prova ad avviare l’applicazione e sui server Appcelerator all’organizzazione di cui fa parte lo sviluppatore non è associata un’applicazione con quel guid, il processo di build fallisce.

"Application not registered"

“Application not registered”


Il punto è che a ciascuna licenza Indie sono associate due entità: lo sviluppatore e l’organizzazione di cui questo fa parte. La creazione/importazione di un’app da parte di uno sviluppatore fa sì che all’organizzazione correntemente selezionata venga associata questa nuova applicazione, identificata da un guid univoco. Ciascuno sviluppatore può far parte di più organizzazioni, ma un’organizzazione Indie non può aver al suo interno più di uno sviluppatore.
Fregati?

Come fare se in azienda si hanno più licenze Indie e non si vuole pagare

Detto che Titanium è ancora su GitHub e lo si può compilare come spiegato sulla documentazione, ma anche che su questo repository non ci saranno più informazioni relative a tags e release varie, è chiaro che da San Francisco per rimpinguare le casse non puntano tanto agli sviluppatori indipendenti sprovvisti di un account (che probabilmente punteranno ad altre tecnologie più economiche), quanto a quella galassia di piccole software house che hanno scelto per le loro applicazioni quella che era la più promettente tecnologia gratuita in grado di non far sentire troppo la mancanza del nativo. E che potrebbero farsi ingolosire anche dai migliori servizi cloud e assistenza delle versioni Team e Enterprise rispetto alla Indie.

Il controllo messo in piedi da quelli di Appcelerator sulle applicazioni sviluppate con il loro sdk è abbastanza lasco e non limita più di tanto. Probabilmente hanno preferito non infierire troppo, fatto sta che una soluzione c’è: basta organizzarsi in modo da poter cambiare velocemente il guid associato all’applicazione (nel tiapp.xml) al cambiare dello sviluppatore.

Il nodo è nel guid (ultima riga)

Il nodo è nel guid (ultima riga)

Se in azienda non ci sono altri sviluppatori destinati alla piattaforma Titanium è sufficiente utilizzare sempre lo stesso account, per lo sviluppo e per rilasciare l’applicazione. Qualora si debba lavorare in parallelo sullo stesso progetto è invece meglio fare in modo che chi ha un account personale registri le applicazioni sul quale lavorerà sulla propria console Appcelerator, e implementi un meccanismo di sostituzione veloce dei guid. Lasciando l’account “aziendale” libero per rilasciare l’applicazione o per eventuali sviluppatori sprovvisti di un account Indie.

Registrazione di un applicazione già esistente su un diverso account

Il modo migliore che mi è venuto in mente è quello di creare una nuova applicazione – vuota – utilizzando la CLI, e assegnandole appid e nome uguale a quella che si sta cercando di “clonare”.
Apriamo la console, portiamoci su una cartella vuota creata per l’occasione e digitamo appc new --id APP_ID --name APP_NAME, con APP_ID uguale all’appid dell’app, e APP_NAME uguale al suo nome.
appcelerator-new-app
Questo è il modo più veloce di creare un’applicazione vuota, e oltre al riempimento della directory con i file della nuova applicazioni ci ritroveremo anche con la coppia di applicazioni Titanium/Arrow sulla console web. Per qualche motivo sconosciuto dalla console non si possono (ancora) eliminare le applicazioni Arrow, ma a leggere in rete sembra che presto colmeranno questa lacuna.
appcelerator-online-console

Sostituzione “on-demand” del guid

Una volta creata la nuova applicazione “copia” dell’originale possiamo anche buttarla via, perché l’unica cosa che ci interessa è il guid generato.
Il mio consiglio è quello di creare – all’interno dell’applicazione – una cartella con un file .sh per ogni account Indie che avete, e all’interno di questi mettere un comando che sostituisca il guid originale (quello registrato sull’account “aziendale”) con quello associato all’account Indie personale, e disponibile per la copia sulla console web di quest’ultimo.
In bash un modo per sostituire una stringa all’interno di un file è questo:
sed -i "" 's/ORIGINAL_GUID/REPLACED_GUID/' ../tiapp.xml

Ogniqualvolta si avrà bisogno di usare il proprio account Indie personale basterà eseguire il login con questo e poi lanciare il file .sh che metterà le cose in regola con quelli di Appcelerator. Naturalmente il nostro progetto è sotto git, quindi far ritornare il guid corretto dentro il tiapp.xml della nostra app è questione di un git reset.

Profilare con Xcode, alla ricerca di memory leaks e non solo

Chi fa il nostro mestiere prima o poi deve affrontare dei problemi di memoria… che la si perda a causa di stress e del passare degli anni, o si scriva programmi che si affidano ad allocazione/deallocazione automatica, prima o poi tutti abbiamo problemi con questo prezioso strumento.

Il caso peggiore: memory leak in applicazione web Java

Tempo fa lavorando ad un grosso progetto web sviluppato in Java (JSF2) ci ritrovammo a metterci le mani nei capelli a causa di qualche memory leaks che rendevano per così dire “poco scalabile” la nostra applicazione. Allora usammo l’Eclipse Memory Analyzer MAT, strumento molto potente e ben fatto che permette di analizzare lo heap di qualunque applicazione Java.
Su un’applicazione web certi problemi possono essere devastanti, mentre in programmi che girano localmente su macchine provviste di parecchia RAM spesso nemmeno ci si rende conto che il nostro programma sta lentamente mangiando tutta la memoria senza rilasciarla, finché va in crash. Se però questa cosa succede di rado, e in quelle poche occasioni stavamo facendo operazioni parecchio onerose, spesso nemmeno ci facciamo caso e/o facciamo finta di niente.
Memory Leak - Comic

Memory leak?

Se non siete uno degli ultimi due personaggi della vignetta dovreste sapere a grandi linee di che si tratta, ma nel dubbio cerco di spiegarlo in poche parole: un programmatore ha sbagliato qualcosa e tra le righe di codice c’è qualche operazione che occupa memoria senza rilasciarla al termine.
Se non si programma in C raramente ci si deve preoccupare di allocare e deallocare la memoria manualmente, perché quasi tutti i linguaggi gestiscono la memoria autonomamente, allocandola ad ogni nostra dichiarazione di variabile, e facendola liberare da un garbage collector. Il GC è un processo demone che scansiona l’area di memoria dove risiedono gli oggetti e le variabili creati dal nostro programma ed elimina quelli rimasti per così dire “isolati”, ovvero che non sono più referenziati da nessuno o che sono collegati solo a oggetti non referenziati da parti “vive” dell’applicazione. In presenza di GC i memory leak sono rari perché il GC a differenza nostra non si dimentica di liberare la memoria, ma a volte proprio non ce la fa a causa di strutture mal progettate che generano riferimenti “eterni” a variabili che credevamo temporanee, e in questi casi sono dolori.

Tipico grafico di un'applicazione affetta da memory leaks, lo heap si riempe e boom

Tipico grafico di un’applicazione affetta da memory leaks

Analisi della memoria su Xcode

Sviluppando in nativo su iOS non so quanto spesso capiti di dover profilare l’applicazione alla ricerca di problemi di memoria, ma parlando di Titanium io personalmente ho dovuto preoccuparmene in più di un’occasione. Il Mac è un prodotto del demonio, però Xcode fornisce alcuni validi strumenti che in questi frangenti tornano molto utili. Vediamo come profilare un’applicazione alla ricerca di problemi di memoria e di prestazioni.

Aprendo un progetto Xcode ci si trova di fronte la finestra delle impostazioni generali, e qui dobbiamo definire le impostazioni di deploy. Generalmente la versione di iOS e il tipo di dispositivo.
IOS Profiling 1
Scegliamo la destinazione del nostro test, tra eventuali dispositivi collegati al Mac e simulatori del tipo selezionato al passo precedente. Fatto questo dobbiamo ricompilare il progetto. Considerato che stiamo per fare una profilazione, tanto vale fare il “Build for > profiling”, e al termine avviamo la profilazione con “Profile”.
IOS Profiling 2
Selezioniamo il tipo di template che più si adatta alle nostre esigenze o creiamo un template contenente tutte le metriche che ci interessano.
IOS Profiling 5
Nella schermata che si apre, quando siamo pronti, premiamo il tasto di registrazione e l’applicazione inizia a girare mandando dati agli strumenti di diagnostica scelti.
In cima all’elenco possiamo leggere istante per istante i dati generali i utilizzo della memoria, e subito sotto quali sono i tipi di oggetti che contribuiscono in maggior misura a saturare la nostra cara RAM. Il diagramma parla più di tutti, se questo inizia lentamente ad assomigliare ad una sega inclinata verso l’alto sono cazz… problemi.
IOS Profiling 6
Se certe parti del flusso del programma sono sospette e volete vedere in dettaglio come cambia l’utilizzo della memoria facendo una determinata operazione non serve segnarsi i numeri sul foglio ma possiamo usare l’utilissimo pulsante “Mark generation”. Questo serve a scattare un’istantanea di un certo punto, istantanee che possono poi essere confrontate per vedere come cambia l’utilizzo della memoria tra queste diverse “generazioni” (e quali oggetti rimangono in memoria).
Nel mio caso la memoria rimane stabile e decresce alla chiusura di alcune finestre parecchio pesanti. Se in certi punti pensate ci siano dei memory leak ma i “buchi sul tubo” sono troppo piccoli da rilevare potete prendere un trapano e allargare il buco… basta aggiungere delle immagini o in generale blob pesanti in variabili sospette per vedere meglio la RAM che se ne va.
IOS Profiling 7

Sviluppo per iOS su Titanium

Se stiamo sviluppando con Titanium probabilmente Xcode lo conosciamo molto poco, eppure nella vostra cartella del progetto (sotto build/iphone) ci dovrebbe essere un file .xcodeproj. Apritelo e vi ritroverete con il progetto Xcode che potete maneggiare e lanciare a piacimento

La cartella del progetto iOS generato da Titanium

La cartella del progetto iOS generato da Titanium

Senza scomodare Xcode

Certi strumenti sono molto potenti e possono aiutarvi molto, ma se siete dei romantici e preferite migliorare le prestazioni del vostro programma basandovi solo sull’intuito potete comunque usare la finestra di Monitoraggio delle attività di OSX. Ogni programma lanciato nel simulatore iPad/iPhone è un processo a se stante, e potete quindi tenere sempre sott’occhio la memoria che questo utilizza.

Monitorare il processo spesso è sufficiente

Monitorare il processo spesso è sufficiente

Intuito, Xcode, oscilloscopio, qualunque mezzo decidiate di usare l’importante è che ogni tanto verifichiate la stabilità e la non eccessiva onerosità dei vostri programmi. Alcuni utenti non sono molto comprensivi – giustamente – quando l’applicazione si rallenta in modo esagerato con il passare del tempo o peggio scompare dalla loro vista all’improvviso.

Titanium Studio e GIT, integrato (a volte) è meglio

Sviluppatori: ognuno con le sue convinzioni e il suo credo

Gli sviluppatori mobile con Titanium si dividono in due scuole di pensiero: chi utilizza Titanium Studio e chi preferisce usare un ide meno pompato e la console. Io appartengo ancora alla prima categoria, principalmente perché mi districo male tra molte finestre e preferisco avere sempre tutto sotto controllo mentre lavoro. L’idea di passare a Sublime o Atom in combinazione eventuale con strumenti esterni mi ha tentato, ma ancora non ho raccolto gli stimoli sufficienti.

Il problema è che Titanium non è il solo strumento che contribuisca a dividerci in caste, perché anche GIT non scherza. I puristi conoscono tutti i comandi con relativi parametri a memoria e utilizzano soltanto la console, i pigri/smemorati come me si affidano a strumenti un po’ più “smart” e ricorrono alla console solo in casi di emergenza o come esercizio di memoria. Personalmente io uso alternativamente la console, il plugin integrato nell’ide e SourceTree, un gestore di repository GIT veramente ben fatto.

SourceTree, e GIT non sarà più così ostico

SourceTree, e GIT non sarà più così ostico

La I di IDE sta per “Integrated”…

Fatte queste distinzioni è ora di arrivare al dunque: perché questo articolo? Il punto è che non sarebbe male utilizzare nel proprio ambiente di sviluppo un plugin che ci aiuti ad avere sempre sotto controllo tutte le modifiche fatte ai nostri sorgenti. Eclipse ha degli showview integrati (History e Synchronize) con cui poter vedere lo storico e lo stato attuale delle modifiche, ma in Titanium questi non funzionano con GIT. Infatti l’ide Titanium Studio ha un suo plugin per GIT (com.aptana.git), che però si integra malissimo con Eclipse e secondo me è praticamente inutile.

Come guardare il dettaglio dei plugin installati

Come guardare il dettaglio dei plugin installati

Aptana Git, per la serie: meglio soli che mal accompagnati

Aptana Git, per la serie: meglio soli che mal accompagnati


L’amato/odiato Eclipse ha un suo plugin per gestire decentemente il repository GIT (EGit), ma non viene fornito con Titanium Studio e fa a cazzotti con quello installato di default.
Il mio consiglio è quindi quello di disabilitare il plugin di Aptana e utilizzare EGit, e ora vi mostro come fare.

Installazione e utilizzo di EGit su Titanium Studio

Punto 1: Per prima cosa conviene dire a Eclipse di non utilizzare più il plugin di Aptana per gestire i nuovi progetti GIT aggiunti nel workspace. Questa cosa la si fa dalla pagina delle preferenze di Eclipse.

Disabilitazione di Aptana Git per i nuovi progetti

Disabilitazione di Aptana Git per i nuovi progetti

Punto 2: Se volete usare su Eclipse un plugin non fornito di default (in questo caso EGit) bisogna installarcelo. La procedura è sempre la stessa e ne avevo parlato in modo un po’ più dettagliato su un precedente articolo (a proposito di SVN su Eclipse).

Installazione di EGit

Installazione di EGit

Punto 3: Nel caso abbiate già dei progetti che utilizzano GIT come VCS all’interno del vostro workspace questi continueranno a usare il vecchio plugin. Scollegateli da esso e fate in modo che usino il nuovo plugin.

Disconnessione di progetti esistenti da Aptana Git

Disconnessione di progetti esistenti da Aptana Git

Connessione di EGit ai progetti git precedentemente scollegati da Aptana Git

Connessione di EGit ai progetti git precedentemente scollegati da Aptana Git

Il Synchronize di Eclipse, uno dei miei strumenti preferiti del mio IDE preferito

Eclipse ha molte funzioni, ma una delle mie preferite e indipendenti dal VCS utilizzato (GIT, SVN, …) è la view Synchronize, che mostra l’elenco dei file modificati rispetto al repository (e all’origin nel caso del GIT) e da la possibilità di modificarli facilmente con una finestra di comparazione. Funzione fondamentale in un ambiente di sviluppo integrato degno di questo nome.
Titanium - Synchronize

Conclusioni

Si può usare un ide o qualunque editor di testo in combinazione con tool esterni, l’importante è avere sempre sotto mano tutte le funzioni di cui si ha bisogno. Titanium Studio per usare un eufemismo non è che sia proprio performante, ma è basato su quel mostro di configurabilità ed estendibilità che è Eclipse, conviene quindi sfruttare al meglio le sue peculiarità installando all’occorrenza ciò che manca.

TiShadow: un hack che (il più delle volte) può far risparmiare un sacco di tempo

Lo sviluppo mobile è una rogna, perché sul mercato ci sono un’infinità di dispositivi e svariate piattaforme e ogni singolo utente si aspetta di poter usare ciascuna applicazione di cui sente parlare.
Quando uno degli obiettivi è raggiungere più pubblico possibile la strada dello sviluppo multi-piattaforma offre varie alternative, ciascuna con i suoi punti di forza e le sue debolezze. Appcelerator Titanium è una di queste.

Compilazione e deploy a ogni modifica, ovvero come girarsi i pollici per la metà del tempo

Quasi in ogni contesto di sviluppo si deve affrontare l’enorme spreco di tempo dovuto a compilazione e deploy delle proprie applicazioni su dispositivi/simulatori, e Titanium non fa eccezione. O almeno non la faceva fino a un paio di anni fa.
Nel 2012 in Australia devono essersi stancati di aspettare il compilatore, e si sono inventati un hack: TiShadow. Il nome non rende molto bene l’idea, si tratta di un infrastruttura basata su un’applicazione mobile che funge da container (di applicazioni sviluppate con Titanium), un’applicazione server che ha il compito di iniettare il nostro codice all’interno del container, e una serie di comandi per console (CLI).

Un'immagine vale più di mille parole

Un’immagine vale più di mille parole


L’utilizzo in se non è complicato, e nemmeno capirne il funzionamento, ma è uno strumento ancora non così diffuso anche perché nei primi passi si può sbattere in alcuni spigoli e rimanere scoraggiati.

Distribuzione ed esecuzione paralleli su più dispositivi

Come è facile intuire stiamo parlando di strumenti sviluppati in Javascript per il Javascript, ecco quindi che spunta fuori npm e l’installazione consiste semplicemente nell’installazione di un modulo NodeJS, e ogni passaggio richiede l’utilizzo della linea di comando.

Installazione di TiShadow

npm install -g tishadow
(per un doveroso approfondimento sui moduli NodeJS leggete qui)
Una volta installato l’apposito modulo globale tutta una serie di comandi diventano disponibili da console.

Creazione dell’applicazione TiShadow

Andiamo quindi a creare una directory per la nostra applicazione, spostiamoci al suo interno, e lanciamo il comando per la creazione dell’app:
tishadow app -d ./
Fatto questo nella directory corrente comparirà un’applicazione Titanium installabile su tutte le piattaforme e contenente i moduli più comunemente usati. Quest’applicazione deve contenere tutto il necessario per il funzionamento della nostra app, perché sarà lei che ospiterà il pacchetto della nostra applicazione, o meglio tutto il contenuto della directory /app. Come potete vedere osservando la struttura di un progetto Titanium i moduli, i plugin, e soprattutto i file tiapp.xml e il manifest sono esterni alla directory app, è importante quindi andare ad aggiungere eventuali moduli non già presenti nell’installazione di TiShadow, e andare a “completare” il tiapp.xml della nuova applicazione ombra inserendovi gli eventuali moduli aggiunti e correggendo appid, version e altre informazioni che potrebbero essere importanti per il buon funzionamento della nostra app.

Deploy dell’applicazione ombra sui dispositivi

L’applicazione “ombra” creata al passo precedente deve essere installata sui nostri dispositivi (o simulatori) in cui dobbiamo testare la nostra applicazione mobile.
Se ad esempio vogliamo provare la nostra applicazione su un simulatore di Motorola Moto X creato con Genymotion sarà sufficiente utilizzare il CLI di Titanium con il comando:
ti build -p android -T emulator --device-id "Motorola Moto X - 4.3 - API 18 - 720x1280"
Questo passo in linea di principio è sufficiente farlo una volta, o almeno solo quando facciamo modifiche “sostanziali” alla nostra applicazione (come aggiunta di moduli o upgrade dell’sdk), perché poi l’applicazione TiShadow rimarrà sul nostro dispositivo/simulatore.

L'applicazione "ombra" TiShadow sul simulatore Genymotion

L’applicazione “ombra” TiShadow sul simulatore Genymotion


L’applicazione TiShadow è disponibile per lo scaricamento anche sull’Android Market, ma se ne sconsiglia vivamente l’utilizzo in favore dell’installazione vista sopra, perché non è chiaro quale sia la sua versione e non avremo modo di mettere le mani al suo interno (ad esempio per modificare il tiapp.xml o per aggiungere moduli).
TiShadow sul market. Ora dimenticatela.

TiShadow sul market. Ora dimenticatela.

Lancio del server TiShadow e connessione dell’applicazione ombra

Una volta installata e lanciata l’applicazione “container”, ci ritroveremo di fronte a una richiesta di connessione a un server…

Quale server TiShadow ?

Quale server TiShadow ?


Facendo un rapido riavvolgimento fino all’inizio dell’articolo potete vedere che avevo nominato un’applicazione server. Questa è una delle parti fondamentali del modulo TiShadow, e per lanciarla è sufficiente digitare:
tishadow server
Si possono specificare vari parametri ma niente di fondamentale. L’applicazione server si mette in ascolto su una porta (la 3000 di default), e aspetta che delle applicazioni client TiShadow vi si connettano così da stabilire un collegamento attraverso il quale iniettare la nostra applicazione.
Inseriamo quindi l’IP della nostra macchina sulla maschera di login dell’app TiShadow e lasciamo che i due attori si connettano.
Ripetiamo questo passaggio per ogni altro dispositivo/simulatore in cui vogliamo testare la nostra applicazione.

Esecuzione della nostra applicazione

Arrivati a questo punto dobbiamo solo posizionarci nella directory della nostra applicazione e dire a TiShadow di eseguirla:
tishadow run
Per magia ci ritroveremo con la nostra applicazione distribuita su ogni dispositivo/simulatore collegato al server.
Anche questo comando dispone di vari parametri, ad esempio con tishadow @ run il deploy è automatico ad ogni salvataggio… una manciata di secondi per un deploy a caldo su dispositivi multipli.
È doveroso specificare che spesso le cose si “incastrano” e c’è da riavviare server e/o client e/o fare qualche aggiustamento, fatto sta che lo strumento è di una potenza devastante.

Unit-test con TiShadow

Ipotizziamo per un momento che chi sta leggendo sia abituato a lavorare soltanto su una piattaforma e abbia una macchina abbastanza veloce da non trarre troppo giovamento da deploy a caldo e distribuzione parallela su più dispositivi, può trarre comunque giovamento da TiShadow? Una domanda scritta in questo modo presuppone una risposta affermativa, specialmente dopo aver letto il titolo, e infatti la risposta è sì.
Ci sono un sacco di moduli e librerie per eseguire test automatici di unità in Javascript, ma farli funzionare con Titanium non è sempre così semplice. TiShadow ci aiuta perché integra al suo interno la libreria Jasmine, e una volta scritte le specifiche nella consueta forma describe-it e inserite nella directory app_main_directory/spec il gioco è fatto.

describe("Spec description", function(){
  it("Test description", function(){
    expect(true).toBe(true);
  });
});

Non serve installare moduli o includere librerie, perché è già tutto dentro TiShadow. Basta descrivere le nostre specifiche come nell’esempio sopra, inserirle in file terminanti con il suffisso “_spec.js” e includere questi file nella directory “spec”. L’esecuzione dei test consiste in due parole:
tishadow spec

Conclusioni

La lentezza delle procedure di deploy è un problema sentito, specialmente nell’ambito dello sviluppo mobile. Forse meno sentito ma non meno importante è l’argomento dei test automatici. Su Titanium entrambi i problemi sono più o meno risolti da TiShadow, un modulo ancora ignoto a molti forse anche a causa del nome enigmatico.
Speriamo che questo breve articolo serva a fare un po’ di luce sull’argomento e a dissipare le ombre che molti vedono aleggiare su Titanium.