Fortune For Mobile

Fortune approda sul telefonino!

Per il mio primo esperimento di programmazione “microedition” ho deciso di effettuare il porting dell’assolutamente inutile programma linux fortune.

Cosa è fortune?

E’ un giochino!
Se lo avete installato sul vostro sistema linux provate a lanciare il comando fortune per vedere cosa accade.

Screenshot

Il comando fortune visualizzerà una frase, una legge di murpy, o anche un “insulto”, pescandola a caso da un database di files testuali; la versione per mobile funziona allo stesso modo.

Screenshot mobile

La versione distribuita contiene circa 1000 frasi italiane provenienti da http://www.fortune-it.net. Non è stato possibile includere tutto il database
fornito da Andrea `Zuse’ Balestrero per questioni di performance e di dimensioni.

Nell’immagine qui sotto potete visualizzare il “design flow” della semplice applicazione.

Fortune Flow

Scrivere “fortune” mi ha aiutato ad avvicinarmi al mondo della programmazione Java per microdispositivi. Credo sia un valido esempio per la creazione di semplici interfacce, operazioni di I/O sui file, e l’utilizzo della tecnologia WMA 2.0 per l’invio di SMS da applicazioni Midlet.

640K sono sufficienti per chiunque.
— Bill Gates, 1981

Il primo problema che ho dovuto affrontare nel mio esperimento di creazione Midlet è stato relativo alle performance. E’ facile non pensarci più di tanto quando abbiamo a che fare con un pc pseudo-recente, dove la RAM abbonda. Scrivere codice su un dispositivo dalle caratteristiche ridotte impone un certo tipo di approccio diverso che generalmente viene ignorato dai moderni programmatori

Il core di “Fortune” utilizza una logica semplicissima:
Le frasi sono memorizzate in diversi file di testo, suddivise per categoria. Ogni frase è delimitata dal simbolo ‘%’.
A richiesta dell’utente viene prima selezionato random il file da cui a attingere la frase e successivamente viene estratta sempre randomicamente la frase stessa per poi essere mostrata a video.

Mi sono reso immediatamente conto che includere tutte le frasi italiane era impossibile, il jar risultante era di dimensioni troppo elevate e molti dispositivi (compreso il mio) non supportano jar così grandi. Non sono particolramente documentato ma per esempio i telefonini Noikia serie 30 supportano jar di massimo 64Kb mentre quelli della serie 40 fino a 128Kb. Per il momento ho compilato una versione da 86Kb che contiene circa 1000 frasi. Ho suddiviso le 1000 frasi in files di dimensioni ridotte tra gli 8 e i 19Kb.

Le API per CLDC-1.1 non mettono a disposizione metodi nativi per “listare” il contenuto di una directory contenuta nel jar dell’applicazione. Ho deciso di mettere i database testuali delle frasi all’interno della directory resource e di crearmi un file system virtuale all’interno del file descriptor.txt dove avrei elencato tutti i miei file di testo

Il file descriptor txt risultava essere simile a questo:

computer
computer-1
computer-2
definizioni
definizioni-1
italia
italia-1
leggi
leggi-1
leggi-2

La mia idea era quella di parsare il file descriptor.txt e caricare in un vettore l’elenco dei file in modo da averli accessibili in qualsiasi momento e nel caso in cui avessi voluto aggiungere un database testuale di frasi sarebbe stato sufficente aggiungere una riga al file descritore e ricreare il jar.

Leggere un file testuale in ambiente Java ME è un’operazione piuttosto semplice

-Si crea un oggetto InputStream
-Si legge lo stream con l’oggetto InputStreamReader:


InputStream is = this.getClass().getResourceAsStream("res/descriptor.txt");
InputStreamReader reader = null;
StringBuffer buff = new StringBuffer();
int chr;
try {
reader = new InputStreamReader(is,"UTF-8");
} catch (UnsupportedEncodingException ex) {
}

try {

while((chr = reader.read()) != -1) {
char tmp_char = (char)chr;
buff.append(tmp_char);

}
} catch (IOException ex) {
}
A questo punto, dopo aver opportunamente parsato il descrittore e popolato un vettore di stringhe, potevo tranquillamente selezionarne un file random e procedere all’estrazione randomica di una frase contenuta.

L’idea di leggere l’intero file, estrarre le singole frasi, salvarle una a una in un vettore e estrarne una random sull’emulatore funzionava alla grande, peccato che una volta installata l’applicazione sul telefonino questa operazione risultava di una lentezza disarmante!

Ho deciso quindi di estendere le informazioni contenute nel file descriptor.txt aggiungendo oltre al nome del file anche i dei marcatori che mi permettessero di sapere quale fosse l’inizio e la fine di una frase potendo così evitare di leggere l’intero file.
Per creare il descrittore contenente i mark di ogni file ho scritto al volo un programmino che, si occupa anche di rimuovere spazi superflui dai file originali, dato che la formattazione per una console a 80 colonne sarebbe stata inutile su un cellulare e in più, così facendo, ho ridotto ulteriormente le dimensioni di ogni singolo file.

Il descrittore ha definitivamente preso questa forma:

computer 0_103_164_223_422_489_544_655_740_811_…
computer-1 0_734_924_1243_1377_1466_1862_…

Tramite il metodo skip() dell’oggetto InputStreamReader ho potuto muovere il puntatore interno del file in modo da potermi posizionare nel punto esatto dell’inizio della frase leggendo un determinato buffer ricavato dalla differenza del macatore iniziale con quello successivo.
Con questo metodo le prestazioni sono migliorate notevolmente e sul mio telefono (Nokia 6070), la media è di circa due secondi a frase (calcolata su un’estrazione di 100 frasi).
Probabilmente esiste un algoritmo migliore, se avete suggerimenti in merito fatevi avanti :).
Per evitare un fastidioso “freeze” durante la ricerca della frase da estrarre ho preferito creare un thread separato:

public void run() {
synchronized(this) {
this.is_busy = true;
this.get_stringItemPhrase().setText(“Aspetta….”);
this.get_stringItemPhrase().setText(this.freader.getFortunePhrase());
this.is_busy = false;
}
}

La frase estratta può essere inoltrata tramite SMS direttamente dall’applicazione.
E’ possibile inviare SMS da applicazioni java ME se il vostro telefono supporta le API WMA Wilreless Messaging API. Vi rimando a questo articolo per approfondire l’argomento.

Randomizziamo:
Per estrarre la frase o il file da cui estrarla in modo randomico ho utilizzato una classe wrapper per l’oggetto java.util.Random.
Il mio scopo era ottenere un numero random compreso tra 0 e numero elementi del vettore -1. Per fare ciò ho semplicemente wrappato l’oggetto aggiungendo un po’ di matematica spicciola:

/**
* Generate a pseudorandom int between min and max
* @param min minimun
* @param max maximun
* @return random int
*/
public static int random(int min, int max)
{
Random r = new Random(System.currentTimeMillis());
return Math.abs(r.nextInt()%(max+1))+min;
}

Attaulmente “Fortune For Mobile” è stato testato sui seguenti modelli:

-Nokia 6070
-Nokia 6680

Stefano lo ha provato su:
-Nokia 6101
-Nokia 7650

Se avete la possibilità/voglia di provarlo anche sul vostro telefonino fatemi sapere come è andata indicandomi il modello!

Download:

Binario

Sorgenti (*)

*Il progetto è stato realizzato con NetBeans e NetBeans Mobility Pack

Per approfondire: Java ME Platform, APIs

Bookmark and Share

4 Responses to “Fortune For Mobile”

  1. Non so quando questa pagina sia stata creata, né se ancora butti un occhio alla medesima… ma scrivo comunque per farti sapere che la tua idea del Fortune in Java per telefonini è proprio bella! Non sai quanto sia utile averla a portata di mano in certi momenti… Non appena riesco a testarla ti farò sapere su quali dei miei 2 telefoni funziona.

    So che è particolarmente fuori tema, ma se poi si riuscisse ad abbinare ad un CowSay sarebbe semplicemente perfetto! 😀 Anzi, magari provo a mettere le mani al codice (sono negato, ma non mi esimerò) e vedo se riesco ad introdurre almeno una specie di splashscreen con la small.cow prima che venga visualizzato il fortune casuale…
    ,__,
    (oo)____
    (__) )\
    ||--|| *

    Grazie per aver condiviso questo grande seppur piccino progetto!

    eNjoy

    Stefano

    • Sono contento che tu abbia trovato interessante il progetto :)
      E’ il mio primo esperimento su microdispositivi e con “Fortune” mi sono divertito a testare un po’ di API interessanti

      Una splash screen è già presente, quindi basterebbe modificare l’immagine ed ecco pronta la “CowSay” :)

      Fammi sapere se e come funziona sul tuo cell!!

      Cya!

  2. Ciao, grazie per questa simpatica inutility! Ho appena provato (riuscendoci) a trasformare il jar in un’applicazione che gira sul BlackBerry. Il mio è l’8100, ma credo giri su tutti quelli con almeno la versione 4 del software.
    Ci vuole i BlackBerry JDE e le istruzioni sono qui, verso la fine, quando parla di deployment. Non so perché il file risultante sia grande più o meno il doppio. Forse con un po’ più di esperienza in Java si può ottimizzare.
    Se non vuoi fare tutta la procedura (la cosa più lunga è scaricare il JDE), ti mando il file compilato (scrivimi una email se lo vuoi).

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

© 2013 Francesco Laurita' s blog Suffusion theme by Sayontan Sinha