Sommario

    Esportare un’app Flutter per il PlayStore

    Chi decide di pubblicare per la prima volta sul PlayStore, probabilmente resterà meravigliato nel costatare che non si tratta di un’operazione immediata. Non resta che armarsi di pazienza e cominciare passo dopo passo.

    Mentre infatti per pubblicare un sito web è sufficiente caricare i file tramite FTP dal proprio PC sul server, per un’app la procedura invece è ben diversa. Possiamo distinguere due fasi ben distinte:

    1. la prima in cui l’app va preparata ed esportata in un file .aab (Android App Bundle) pronto per la pubblicazione sul PlayStore;
    2. la seconda in cui si crea un profilo sviluppatore (nel caso in cui sia la prima app), si carica il file .aab, si forniscono tutte le informazioni e gli asset necessari per la pubblicazione stessa e si attende l’approvazione.

    In questo tutorial ci occuperemo della prima fase e non della pubblicazione. A questo scopo seguiremo la guida ufficiale ma non in modo rigoroso, salteremo alcuni passaggi non sempre necessari e integreremo la documentazione ufficiale con questo video di heyflutter.com. La guida ufficiale resta comunque il punto di riferimento dal momento che questo tutorial riflette solo un’esperienza personale non esaustiva per tutte le possibili casistiche o problematiche che si potrebbero riscontrare.

    Dopo avere aperto il progetto Flutter da esportare, digiteremo tutte le istruzioni a riga di comando dal Terminal di Visual Studio Code su piattaforma Windows 10. Ogni riferimento a percorsi di file è relativo alla directory del progetto Flutter indicata con [nome_progetto].

    Icona

    Per prima cosa si deve creare una launch icon, in parole semplici un’icona per la nostra app. Il modo più semplice ed efficiente è affidarsi ad un buon generatore online di icone quale IconKitchen. Di solito io preferisco caricare un file svg monocromatico 512×512 e indicare il colore di sfondo. Dopo avere scaricato il file zip è sufficiente sovrascrivere le cartelle [nome_progetto]/android/app/src/main/res/mipmap-* del progetto Flutter con le cartelle omonime del file compresso.

    Se si esegue nuovamente l’app nell’emulatore (o in un dispositivo fisico) si vedrà già in azione la nuova icona.

    Il nome predefinito del file icona è ic_launcher, se si cambia il nome nel campo Filename di IconKitchen bisogna ricordarsi di modificare conseguentemente l’attributo <application android:icon...> in [nome_progetto]/android/app/src/main/res/AndroidManifest.xml.

    Nel probabile caso in cui si volesse predisporre anche una splash screen, la schermata iniziale che compare quando l’app viene avviata ‘a freddo’ (cioè quando il processo dell’app non era già precedentemente in esecuzione), consiglio di dare un’occhiata anche al pacchetto flutter_native_splash.

    Nome dell’applicazione

    A questo punto scegliamo il nome dell’applicazione. Quest’ultimo è il nome pubblico visibile all’utente, che compare sotto l’icona. Il tool rename CLI consente di raggiungere lo scopo con una semplice istruzione a riga di comando. Questa riga ad esempio assegna il nome “Shopping List” all’app.

    rename setAppName --targets android --value "Shopping list"

    Con ogni probabilità per eseguire questo comando senza intoppi si dovrà configurare correttamente la variabile d’ambiente Path per il proprio sistema operativo. Nel mio caso, lavorando su Windows 10, ho dovuto aggiungere il percorso %LOCALAPPDATA%\Pub\Cache\bin a quelli già presenti in Path. Per sapere come modificare una variabile di sistema basta seguire uno dei tanti tutorial in rete.

    Se il passaggio precedente dovesse risultare ostico e considerato che stiamo cambiando il nome solo per la piattaforma Android, è sufficiente, in alternativa, editare manualmente l’attributo <application android:label...> in [nome_progetto]/android/app/src/main/res/AndroidManifest.xml.

    Allo stesso modo cambieremo l’application id o bundled id dell’applicazione, che è invece il nome che identifica univocamente la nostra app nello store. Di norma si adotta una notazione reverse domain come ad esempio com.example.appname. L’istruzione seguente a riga di comando imposterà “name.marcellosurdi.shoppinglist” quale application id dell’applicazione.

    rename setBundleId --targets android --value "name.marcellosurdi.shoppinglist"

    Non è necessario essere i proprietari del dominio indicato.

    Anche in questo caso rename CLI non è indispensabile. In alternativa è sufficiente editare il file [nome_progetto]/android/app/build.gradle del nostro progetto Flutter nella sezione defaultConfig (un commento identifica la riga da modificare).

    Firma digitale

    Per caricare l’app nello store, inoltre, sarà necessario firmarla con un certificato digitale. Questo garantirà che i successivi aggiornamenti e caricamenti dell’applicazione siano fatti esclusivamente dall’autore dell’app.

    Creazione del certificato per l’upload

    Dal Prompt dei comandi digitare per Windows il seguente comando avendo cura di sostituire [path] con il percorso nel quale si vuole salvare il certificato appena generato:

    keytool -genkey -v -keystore [path]\upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload

    Se il comando non va a buon fine, anche in questo caso il problema è la variabile di sistema Path non configurata. Occorre seguire con attenzione la guida ufficiale e rieseguire il comando usando il percorso individuato tramite l’output di flutter doctor -v, quindi inserire le informazioni richieste dalla procedura guidata.

    Fare riferimento al certificato all’interno del progetto

    A questo punto occorre che l’app ‘sia a conoscenza’ di questo certificato e che, in seguito, lo utilizzi per compilare il file da caricare sul PlayStore.

    Creare quindi il file [nome_progetto]/android/key.properties con i riferimenti al certificato in questo modo:

    storePassword=<password-from-previous-step>
    keyPassword=<password-from-previous-step>
    keyAlias=upload
    storeFile=<keystore-file-location>
    

    In sostituzione dei segnaposti <password-from-previous-step> inserire la password digitata al momento della creazione del certificato. Al posto di <keystore-file-location> digitare invece il percorso fisico del certificato. Io di solito sposto il file .jks dentro [nome_progetto]/android/app e di conseguenza scrivo storeFile=../app/upload-keystore.jks.

    Non resta adesso che modificare il file [nome_progetto]/android/app/build.gradle come indicato nel capitolo della documentazione ufficiale Configure signing in gradle.

    Numero di versione

    Dopo aver generato il certificato digitale ed effettuati i dovuti riferimenti ad esso siamo pronti per il passo conclusivo: la generazione del file .aab da caricare sullo store. Prima di questo step finale, tuttavia, non si deve dimenticare di aggiornare il numero di versione dell’app.

    versionName

    Il numero di versione dell’app si imposta dal file pubspec.yaml del progetto Flutter e il valore predefinito è 1.0.0+1. Si compone di due parti, la prima obbligatoria prima del segno + la seconda opzionale dopo il segno +.

    Relativamente al mondo Android la prima parte composta da una stringa di tre numeri separati da un punto è denominata versionName. In base alle regole del versionamento semantico la sequenza dei numeri del versionName è così composta <major>.<minor>.<patch>. Di seguito il loro uso:

    • <major>, il primo numero, indica una release incompatibile con le precedenti;
    • <minor>, il secondo numero, indica una release che introduce delle nuove funzionalità compatibili con le versioni precedenti;
    • <patch>, l’ultimo numero, indica una release che corregge dei bug delle versioni precedenti.

    Se, come di consueto, la prima versione è 1.0.0, le successive correzioni di bug verranno contrassegnate da un numero <path> crescente quindi 1.0.1, 1.0.2, 1.0.3 e così via. Quando lo sviluppatore introdurrà nuove funzionalità retrocompatibili si modificherà <minor> in questo modo 1.1.0 (1.2.0, 1.3.0…) e le eventuali correzioni di bug a seguire si indicheranno di conseguenza con 1.1.1, 1.1.2 e 1.1.3 ecc… Quando (e se) verrà introdotta una release non retrocompatibile si sceglierà come numero di versione 2.0.0.

    versionCode

    Dopo il segno + si può opzionalmente indicare un versionCode.

    Un numero intero positivo utilizzato come numero di versione interno. Questo numero aiuta a determinare se una versione è più recente di un’altra, con numeri più alti che indicano le versioni più recenti. Questo non è il numero di versione mostrato agli utenti; questo numero è impostato dall’impostazione versionName. Il sistema Android utilizza il valore versionCode per proteggerti dai downgrade, impedendo agli utenti di installare un APK con un valore versionCode inferiore alla versione attualmente installata sul dispositivo. […] In genere, rilasci la prima versione dell’app con versionCode impostato su 1, quindi aumenti invariabilmente il valore a ogni release, indipendentemente dal fatto che si tratti di release principale o secondaria. Ciò significa che il valore versionCode non assomiglia necessariamente alla versione di release dell’app visibile all’utente. Le app e i servizi di pubblicazione non devono mostrare questo valore di versione agli utenti.

    developer.android.com

    File .aab

    Per concludere, dopo essersi assicurati che il terminale punti ancora alla directory del progetto Flutter (in caso contrario usare il comando cd [nome_progetto]), digitare a riga di comando nell’ordine:

    1. flutter clean
    2. flutter pub get
    3. e infine flutter build appbundle

    In questo modo andremo a generare il file [nome_progetto]/build/app/outputs/bundle/release/app-release.aab pronto per il caricamento sullo store.