giovedì 30 agosto 2012

Android: Only the original thread that created a view hierarchy...

... can touch its views.

Sì, il maledetto messaggio che vi da il log degli errori quando una funzione invocata da un thread secondario cerca di modificare qualcosa nella GUI dell'Activity, ad esempio nascondere una progress bar attiva.

Si risolve facilmente, per fortuna. E' sufficiente dare a Cesare quel che è di Cesare, ovvero forzare l'esecuzione della funzione incriminata all'interno del thread che gestisce la user interface. Così:

runOnUiThread(new Runnable(){
   @Override
   public void run() {
      
      // qui il codice che crea l'errore
      // ...
   }     
});
E il gioco è fatto. Tanto semplice quanto facile da dimenticare.

Buon coding!

venerdì 24 agosto 2012

HowTo: Primi passi per sviluppare un Flash Game

Circa sei mesi fa ho deciso di smettere di snobbare ActionScript e cimentarmi nell'esperimento di produrre un gioco Flash. Tutt'ora non sono ben sicuro sull'usare il termine Flash piuttosto che Flex, ma ci siamo capiti.

La prima bella sorpresa è stata essersi trovati di fronte ad un linguaggio, ActionScript 3 appunto, che nulla aveva a che fare con lo script, termine che personalmente ho sempre relegato, sbagliando per carità, a qualcosa di riduttivo, disordinato, poco elegante e anche un po' sporco. No, quello che mi trovavo tra le mani era un vero linguaggio di programmazione, con tutta la dignità di un Java o un C# (e, a mio personale giudizio, anche la medesima comoda curva di apprendimento e immediata produttività).

La seconda bella sorpresa è stata scoprire un ottimo IDE free e ottime librerie a supporto. Ma...

...c'è un ma, e anche bello grosso. Prima di arrivare a tutto questo, infatti, mi sono trovato veramente spaesato in mezzo ad una miriade di possibilità e opzioni, senza una vera bussola che non fosse bussare in qualche forum, pigiare tasti Cerca e, naturalmente, chiedere a Google. Alla fine di questo processo di documentazione sono giunto ad una mia configurazione. La reputo produttiva, completa e, soprattutto, semplice, quindi la condivido qui su questa pagina.

Step 1: un IDE di nome FlashDevelop



Naturalmente non possiedo una licenza per Adobe Flash in nessuna sua forma o versione ma, anche se fosse, non avrei di certo perso l'occasione di provare un ottimo IDE open source quale FlashDevelop.


Il download per Windows sono circa 16 mega di ambiente fresco e pulito, con già tutte le librerie necessarie per partire con lo sviluppo di numerose tipologie di progetti con target non solo il noto Player di Adobe, ma anche AIR, l'ambiente (sempre di Adobe) per applicazioni desktop.

Come IDE, a parte essere bello (ho una passione per gli editor di testo, per cui passatemi l'aggettivo), è anche piuttosto completo e performante, comprendendo features come l'autocompletamento, l'intellisense (ma che funziona, non come quella di Code::Blocks...), un buon debugger (non come... ah, l'ho già detto), opzioni per il refactor e via dicendo.

La prima cosa da fare, quindi, è andare sul sito di questo ottimo progetto, scaricarselo e installarlo.

Step 2: una libreria di nome FlashPunk


Non intendevo affrontare il framework Flex di petto, lo ammetto. Frequentando come giocatore diversi giochi Flash mi ero reso conto che molti condividevano parecchie caratteristiche comuni, vuoi nei font, vuoi nei loghi in apertura. Le paroline Powered by riportate nei credits indicavano quasi sempre un paio di nomi: FlashPunk o Flixel.

Dilemma. Alla fine ho scelto FlashPunk con la stessa angoscia con cui in terza media decidiamo dove indirizzare le nostre vite. Anche la conoscenza di cosa scartavo era più o meno la stessa, così come la profondità delle motivazioni di tale scelta: di FlashPunk mi è piaciuto di più il sito. Ma anche la documentazione.

Step 3: Hello World


Provenendo dal C++ ed essendo FlashPunk un framework opensource di cui avevo appena scaricato i sorgenti ero già pronto a perdere non meno di 4 ore nel farli accettare al compilatore e farli trovare al linker, e invece mi sbagliavo. Mi ci sono voluti 30 secondi, 20 dei quali spesi in pausa di sorpresa.

E' infatti sufficiente fare copia/incolla della cartellina con i sorgenti di Flashpunk all'interno della cartella src del vostro progetto (creata dall'IDE) e il gioco è fatto.

Quale tipo di progetto creare? Già, in effetti se c'è una cosa un po' spaesante è proprio la quantità di tipologie di progetti realizzabili con FlashDevelop, ma quello che interessa a noi è AS3 Project!

A questo punto si tratta di utilizzare FlashPunk per istanziare il suo Engine e iniziare a creare i Worlds, qualcosa che somiglia moltissimo ad una gestione degli stati. Ma tutto questo è spiegato benissimo nei tutorial sul sito di FlashPunk quindi, as usual,

buon coding!

venerdì 3 febbraio 2012

Android: impostare un context grafico OpenGL ES

E così vuoi fare un gioco per Android.
Benvenuto compagno di viaggio.
Non hai ancora deciso se sarà un 3D o un 2D, ma tanto non ti interessa, dato che non ti piegherai ad usare un Canvas o una semplice View per disegnare, tu vuoi codare the hard way, vuoi la potenza dell'accelerazione hardware, vuoi OpenGl ES.

E allora eccoci qui. La prima cosa da fare è capire come si imposta il contesto grafico, e arrivare alla mitica schermata monocolore. Da lì in avanti, lo sappiamo, è tutta in discesa... (chi ha detto caduta libera?)

Suppongo tu sappia già come funziona una applicazione Android, e se non lo sai, beh, sappilo. Mi riferisco a inezie tipo il concetto di Activity (non ti servirà comunque molto altro).

Quindi, il nostro progetto partirà con una Activity vuota ma funzionante. Per impostare il nostro contesto grafico ci occorrono essenzialmente due cose:

  1. Una istanza della classe GLSurfaceView
  2. Una implementazione dell'interfaccia GLSurfaceView.Renderer

La prima ce la fornisce il framework, ma in un progetto reale vorremo probabilmente ereditare da quella base per accedere alle notifiche dell'input utente e, in generale, avere maggiore controllo sulla vita dell'applicazione. Per ora possiamo accontentarci, ad ogni modo, di usarla così come è.

La seconda necessita invece di un po' di codice. GLSurfaceView.Renderer è l'interfaccia dell'oggetto che si occupa di creare il contesto opengl, gestirne i cambiamenti (risoluzione dello schermo) e disegnare il frame. Implementandola, dovremo scrivere il codice per i metodi:

public void onDrawFrame(GL10 gl);
public void onSurfaceChanged(GL10 gl, int width, int height);
public void onSurfaceCreated(GL10 gl, EGLConfig conf);

Dove GL10 è l'oggetto wrapper sulle API OpenGL (1.0).

Ecco una semplice implementazione:

public class MyRenderer implements Renderer {
 
 @Override
 public void onDrawFrame(GL10 gl) {
  gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
  
  gl.glMatrixMode(GL10.GL_MODELVIEW);
  gl.glLoadIdentity();
 }

 @Override
 public void onSurfaceChanged(GL10 gl, int w, int h) {
  gl.glViewport(0, 0, w, h);
  gl.glMatrixMode(GL10.GL_PROJECTION);
  gl.glLoadIdentity();
  GLU.gluPerspective(gl, 45f, (float)w / (float)h, 0.1f, 450f);
  gl.glMatrixMode(GL10.GL_MODELVIEW);
  gl.glLoadIdentity();
 }

 @Override
 public void onSurfaceCreated(GL10 gl, EGLConfig conf) {
  gl.glShadeModel(GL10.GL_SMOOTH);
  gl.glClearDepthf(1.0f);
  gl.glEnable(GL10.GL_DEPTH_TEST);
  gl.glDepthFunc(GL10.GL_LEQUAL);
  gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
  gl.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
 }

}

Per un gioco 2D, naturalmente, imposteremo la GL_PROJECTION con una glOrtho, o gluOrtho2D... insomma, OpenGL rimane sempre lei.

Il main, oops, scusate, la OnCreate dell'Activity, resta banale:

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyRenderer renderer = new MyRenderer();

        GLSurfaceView surface = new GLSurfaceView(this);
        surface.setRenderer(renderer);

        setContentView(surface);
}

Tutto quel che facciamo è istanziare il Renderer e la GLSurfaceView e passare a quest'ultima la nostra implementazione, quindi assegnare la View all'Activity.

E adesso via a scrivere il vostro gioco!

mercoledì 11 gennaio 2012

Unit Test in C++ con MiniCppUnit

Continua la carrellata di tool utilissimi e semplici da usare per arricchire la nostra cassetta degli attrezzi C++.

Dopo aver visto quanto sia facile fare parsing ed editing di documenti xml con TinyXML, vi segnalo una libreria molto pratica per lo unit testing: MiniCppUnit.

MiniCppUnit condivide con TinyXML l'approccio lib-free, ovvero non la trovate compilata come libreria da includere nel vostro progetto, ma come due semplici file (un header e la relativa implementazione) da aggiungere e compilare assieme al vostro codice (C++ standard, STL e nessuna dipendenza esterna... good!).

L'utilizzo segue la logica del più noto JUnit per Java, di cui esiste il porting C++, CppUnit, del quale il nostro MiniCppUnit non è altro che la versione semplificata. Per chi non conoscesse JUnit (o NUnit per .Net) facciamo un rapidissimo ripassino:

  • si crea un progetto per il test di un altro progetto/classe/sottosistema
  • si creano una o più classi speciali marcate come TestFixture e contenenti metodi marcati come Test
  • si scrivono test basati sull'utilizzo di asserzioni
  • si danno tutte le TestFixture in pasto ad un motore che le esegue e riporta i risultati (successo/fallimento)

NB: per info più precise sullo Unit Testing si veda la Rete.


Cosa mi fa testare?


MiniCppUnit permette di verificare vari tipi di asserzioni:

ASSERT(3==1+2);
ASSERT_MESSAGE( 2==1+1, "2 should be 1 plus 1 ");
ASSERT_EQUALS(expected, result);
ASSERT_EQUALS_EPSILON(expected, result, 0.05);

...e pure una macro sul controllo delle eccezioni!

Sono poche e semplici, ma sicuramente l'essenziale per mettere in piedi un sistema di testing più evoluto di un main con tanti cout, o peggio ancora di no tests at all.

Come lo lancio?


Il main è quanto di più banale possa esistere:

#include "MiniCppUnit.hxx"

int main()
{
   return TestFixtureFactory::theInstance().runTests() ? 0 : -1;
} 

Il singleton TestFixtureFactory va in automatico a prendersi tutte le classi TestFixture (registrate tramite apposita macro REGISTER_FIXTURE()) e le esegue, riportando il risultato in una schermata di console. Semplice, pratico e pulito.

Il pacchetto che scaricate, oltre ai due file da includere nel vostro progetto, contiene anche altri due file con un esempio d'uso, da cui ho preso il codice d'esempio. Sono più che sufficienti a togliere ogni dubbio residuo sull'utilizzo, ma se servisse altro c'è pure una ottima documentazione doxygen online.

Concludendo


Niente scuse, quindi: il vostro prossimo progetto C++ godrà di unit testing, perché if it ain't tested, it's broken!

venerdì 30 dicembre 2011

Programmazione: Ecco perché dovresti usare i private accessors

Ah, gli accessors. Per molti programmatori in erba sono quasi degli sconosciuti. Per i più navigati (e pigri) poco più che delle seccature. Per alcuni IDE, un modo come un altro per generare warnings e riempirvi il codice di fastidiose sottolineature.

E' tuttavia pratica comune ammettere che gli accessors pubblici hanno un loro perché, tirando fuori il principio di Incapsulamento dell'OOP. Ma cosa si può dire di un accessor privato?

Prendiamo ad esempio il seguente frammento di codice C++:

class Player
{
   public:
   
   void hurt(int damage){
      this->hp -= damage;
   }

   void heal(int amount){
      this->hp += amount;
   }

   private:

   int hp;
}

Il membro hp è privato e la classe Player vi accede in modo diretto all'interno dei suoi metodi. Che c'è di male? Beh, niente. Tutto lecito. Il compilatore va avanti e il programma funzia. Ma vediamo come apparirebbe con l'utilizzo di accessors privati:

class Player
{
   public:
   
   void hurt(int damage){
      setHp(getHp()-damage);
   }

   void heal(int amount){
      setHp(getHp()+amount);
   }

   private:

   int hp;

   private:

   void setHp(int value){
      this->hp = value;
   }

   int getHp(){
      return this->hp;
   }

}

E' vero, c'è del codice in più. E' vero, codice in più == bug in più. Ma ci sono anche ottimi motivi per operare in questo modo. Elenchiamoli:

  • Tutte le modifiche in un punto solo
    Sappiamo che questo vale per gli accessors pubblici, perché non dovrebbe valere per quelli privati? Ogni modifica al membro hp verrà fatta dentro setHp(), riducendo la complessità di debug e manutenzione del codice (un solo breakpoint).
  • Validazione
    E' possibile operare logiche aggiuntive in un unico punto. Ad esempio si potrebbe controllare che gli hp non scendano sotto lo zero, o che non salgano sopra una certa soglia, mettendo tutti i controlli nella setHp() anziché spargerli nelle varie hurt(), heal() e così via.
  • Unit test?
    Con qualche accorgimento (tipo un metodo wrapper pubblico sugli accessor privati, magari da commentare dopo la fase di test) possiamo scrivere dei test più sicuri ed efficienti, perché andranno a spremere con tutte le logiche possibili un unico metodo. (I moderni tool di unit testing solitamente hanno poi escamotage per raggiungere anche i metodi privati, senza chiederci di sporcare il codice con wrapper vari.)
  • Incapsulamento
    Ancora una volta, l'essere privato non elimina i vantaggi del pubblico. E' vero, stiamo "nascondendo" dettagli implementativi alla stessa classe che li implementa, il che può apparire sciocco. Ma non è mai sciocco racchiudere funzionalità operanti su un membro in un unico punto.
  • Ridefinizione nelle classi derivate
    Ok, qui bariamo un attimo e rendiamo i nostri accessors virtual e protected. Le classi derivate possono ridefinire l'accesso al membro. Se questa esigenza fosse sorta dopo un po' e non avessimo avuto gli accessors privati saremmo stati costretti quantomeno ad un pericoloso refactoring.
  • Undo e Redo
    Altro figlio dell'avere le modifiche in un solo punto è la possibilità di aggiungere con facilità funzionalità di undo e redo.

I vantaggi qui elencati sono solo esempi. Scommetto che lavorandoci se ne potrebbero trovare altri.

Buon coding...e Buon Anno!

L'articolo originale da cui ho tratto lo spunto per questa riflessione è pubblicato sul blog Joel on Software

mercoledì 28 dicembre 2011

Dwarf Fortress: come ti sopravvivo al primo anno (parte 1)

Questo post poteva anche appartenere alla serie "Il gioco indie che forse non conoscete...", ma chi non ha mai sentito parlare di Dwarf Fortress? Chi non ha mai provato a giocarci e, dopo solo tre minuti, l'ha cestinato per via della sua inconcepibile complessità? E chi, tra questi, ha mantenuto quell'amaro in bocca dovuto alla sensazione di aver appena rinunciato ad una esperienza di gioco potenzialmente molto valida?


Ebbene, se siete tra i tanti frustrati che ci hanno provato ma ne sono stati sconfitti, questo post tenterà di farvi tornare la voglia per un nuovo tentativo. Sì, perché qui si parla della base di partenza per creare una fortezza e mantenerla in vita per il primo anno di gioco.

E' vero, ci sono tanti tutorial su Dwarf Fortress, quindi perché anche questo?

Beh, DF è un gioco grosso (ma rende meglio all'americana: HUGE!) e, quasi fosse fisiologico, anche i tutorial che vanno ad occuparsene finiscono per diventarlo. Inoltre sono spesso scritti da guru del gioco, persone che ormai ne padroneggiano i segreti più occulti e che hanno perso di vista quella sensazione di muro che si trova davanti il novizio.

Io no. Ho perso le mie prime fortezze in molti modi: per fame, per sete, per rabbia dei nani, per fantasmi (!), per cause ignote ma che mi lasciavano nani morti ammazzati in giro per le sale e per altri divertimenti assortiti.

Dopo diversi tentativi ho però trovato la formula per l'equilibrio, quel tanto che basta a far vivere e prosperare la fortezza fino all'arrivo della prima carovana di mercanti, e anche un po' più in la. Tutto si riassume in due parole: cibo e alcolici. Fate in modo di produrne in quantità regolari (ma anche abbondanti) e avrete risolto i bisogni primari dei vostri nani.

Produrre cibo e alcol sottintende avere una o più fattorie (farm plot) funzionanti. Per fare una fattoria occorrono però una serie di passi intermedi che vanno dal tagliare gli alberi allo scavare in un terreno adatto (o irrigare). Fondamentale sarà anche tenere un conto preciso delle scorte.

In questa prima parte prenderemo solo confidenza con i meccanismi di base del gioco.
Incredibilmente, per essere un gioco tanto complesso, le meccaniche sono essenzialmente tre o quattro, e si ripetono sempre uguali.

All'inizio troverete i vostri nani (sette, naturalmente) attorno al wagon, il carro con cui sono giunti al luogo della spedizione. Sul wagon ci sono un sacco di robe utili, ma per ora non ce ne preoccupiamo.

Fermi tutti!


Il gioco parte in stato di pausa, come vedete nella parte alta a sinistra della schermata. Lo stato di Pausa è fondamentale e ci passerete gran parte del tempo. Occorre quindi padroneggiarlo. Si entra in pausa in due modi: o per volontà, premendo Space dal menu principale, o in automatico, quando si entra in un sottomenu. Durante la pausa il tempo si blocca (ma dai!), i nani non fanno nulla e non accade niente di divertente, ma potete navigare tra i ricchi sottomenu in santa pace e assegnare ordini e direttive ai vostri nani, o capire cosa non va e con chi. Per ora allenatevi ad entrare ed uscire dalla pausa, acquisendo coscienza di essa.

Potete dare ordini ai nani premendo 'd' (Designations), come vedete nella parte destra dello schermo. Da qui si accede ad un sottomenu con i vari ordini, da scavare (Mine), a tagliare alberi (Chop down trees), a raccogliere erbe (Gather plants) ecc.

Sì, ma come?


Ogni voce ha un suo tasto associato, che occorre premere. Mine, ad esempio, ha la 'd'. Per selezionare l'azione scavare, quindi, occorre premere 'd' e poi ancora 'd'. A questo punto la X gialla nella schermata di mappa con i nani diventa un cursore. Dobbiamo selezionare l'area interessata dall'azione, specificandone il vertice alto a sinistra e basso a destra. Per farlo portiamo il cursore (con le frecce) nel punto desiderato (alto a sinistra) e premiamo Enter. Quindi ci portiamo nel secondo vertice (basso a destra) e premiamo Enter di nuovo. L'area viene evidenziata. Nel caso dello scavare, l'area evidenziata rappresenta la fetta di terra/roccia da eliminare. Naturalmente ha senso solo se fatta in una zona con una parete rocciosa, oppure sotto terra.

Altro menu importante è quello delle costruzioni (Buildings). Ci si accede col tasto 'b' e vengono mostrate le possibili costruzioni. Ci torneremo, nel frattempo esplorate pure i vari sottomenu, specialmente quello dei laboratori (Workshops).

Chi fa cosa?


E' importante capire che non comandate direttamente i singoli nani, ma specificate cosa deve essere fatto (è un gestionale). I nani hanno poi delle statistiche e il sistema invia i nani più skillati nel lavoro scelto. A volte capita che nessun nano sappia fare la cosa scelta. In questo caso occorre agire sul singolo nano, abilitandolo al lavoro specifico (Labor). Ma questa è un'altra storia. Se avete scelto di giocare subito (consigliato) anziché preparare il viaggio con cura avrete a disposizione sette nani capaci di svolgere i compiti basilari.

Su e giù


Altra abilità importante che dovete sviluppare come giocatori di Dwarf Fortress è il concetto di Z-Level e come muoversi tra essi. DF è un gioco in 2D, ma simula il 3D lavorando con i livelli, come un programma di fotoritocco. Premendo '>' si scende di un livello (si va in profondità), mentre con '<' si risale. Quando i vostri nani inizieranno a scavare (o a costruire verso l'alto, perché no) diventerà essenziale navigare tra i livelli. Fate esercizio già da ora e vedrete come i livelli più bassi appaiano ora quasi del tutto neri (solida roccia), magari con qualche falda acquifera qua e la, mentre quelli più alti vadano a perdere di dettaglio man mano che si sale. Se vi perdete niente paura: con F1 si torna al wagon.

Coraggio dunque, iniziate la vostra avventura nanica e prendete la mano con i comandi di base e la mentalità del gioco, che nella prossima puntata si parte con la strategia di sopravvivenza.

mercoledì 30 novembre 2011

HowTo: usare la fotocamera su Android

Domanda: sto facendo una mia app per Android. Devo permettere all'utente di scattare una foto per farci poi alcune cose, come faccio?

Risposta: chiedi in prestito la camera ad Android.

Il concetto di base è quello di sfruttare il meccanismo degli Intent per chiedere al sistema di prestarci la sua gestione della fotocamera. Gli Intent sono una caratteristica veramente interessante di Android e chiunque decida di fare sul serio con questa piattaforma dovrebbe studiarseli per bene. Volendo comunque riassumere in due righe cosa sono e perché ci servono, possiamo dire che gli Intent sono lo strumento a disposizione delle applicazioni per esprimere la propria necessità di fare qualcosa (scattare una foto, mostrare una pagina web, vedere un video...), anche senza specificare il come farla. Di questo si delega il sistema stesso, che sceglie l'applicazione più consona a soddisfare l'esigenza.

La nostra esigenza, ovviamente, è scattare una foto e averla poi a disposizione. Una volta impostata la nostra Activity e l'azione che deve scatenare la richiesta, come pigiare un button, non ci resta che scrivere il poco codice che serve.

NB: prima di iniziare, preciso che tutto il codice qui indicato è esente da qualsiasi gestione delle eccezioni, anche da quelle comandate, in favore della leggibilità. Non è un grosso problema, dato che l'IDE (e Java) stesso vi obbligheranno a gestire le Exceptions necessarie.

private static final int CAMERA_REQUEST = 100; // un numero a nostro piacimento 
File tmpFotoFile = null;

private void launchCamera(){

   // Fase 1
   //

   tmpFotoFile = File.createTempFile("myappprefix", null);

   // Fase 2
   //

   Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
   cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tmpFotoFile));
   startActivityForResult(cameraIntent, CAMERA_REQUEST);
}

Come vedete il codice si compone di due fasi:
  1. dobbiamo creare un'area di memoria in cui salvare i dati della foto che andremo a scattare. Volendo potremmo anche creare un file fisico, ma per questo tutorial supponiamo che non vogliate (o possiate) scrivere sulla SDCard. Il nostro file temporaneo in memoria è gestito da tmpFotoFile.
  2. ora possiamo chiedere al sistema di lanciare la sua gestione della fotocamera. Per fare questo creiamo la giusta Intent, dicendogli che ci serve qualcosa per ottenere una ACTION_IMAGE_CAPTURE. Decoriamo ulteriormente la Intent con una informazione extra: l'output, caro Android, mettimelo per cortesia in tmpFotoFile. Come vedete è tutto estremamente generico, proprio perché adattabile anche ad altri contesti. Fatto questo, lanciamo la nuova Activity risultante dall'Intent specificata in modo da attenderne (e gestirne) il risultato.

A questo punto siamo già in grado di lanciare la gestione della fotocamera e scattare le foto. Alla chiusura dell'Activity della fotocamera, però, non abbiamo più il controllo sui dati della foto scattati. Per fare questo ci occorre gestire l'override di un metodo della classe base Activity, onActivityResult, intercettando il corretto codice di request. Ecco come:

byte[] bitmapdata;
ImageView preview;

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   
   if (requestCode == CAMERA_REQUEST) {
     Bitmap datifoto = android.provider.MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.fromFile(tmpFotoFile));
     preview.setImageBitmap(datifoto);
    
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     datifoto.compress(CompressFormat.JPEG, 70, bos); 
     bitmapdata = bos.toByteArray();
       
     tmpFotoFile.delete();
  }
}


Ci facciamo restituire la Bitmap leggendone i dati dal nostro file temporaneo. Con questa, volendo, andiamo ad impostare una ImageView che ci fornisce l'anteprima dell'immagine (la ImageView deve essere opportunamente presente nella nostra Activity e referenziata attraverso findViewById(...)).

La seconda cosa che vogliamo fare è ottenere una immagine jpeg compressa partendo dalla grossa bitmap ottenuta. Lo facciamo con le tre righe che seguono l'impostazione della preview, nelle quali specifichiamo il grado di compressione (70, nell'esempio) tenendo conto che 0 significa massima compressione e 100 massima qualità.

Infine, puliamo la memoria eliminando il nostro file temporaneo, che ci sembra sempre cosa buona e giusta.

Non ci resta altro da fare che aggiungere nel Manifest le uses-permission necessarie a far funzionare il tutto, ovvero:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
<uses-feature android:name="android.hardware.camera" />

Buone foto!