venerdì 18 novembre 2011

HTC Zeta

In base alle ultime indiscrezioni provenienti dal web, HTC starebbe progettando un nuovo smartphone Android il cui nome in codice è HTC Zeta.

Il nuovo smartphone sarà basato sul sistema operativo Android 4.0 Ice Cream Sandwich, e sarà dotato di un display da 4,5 pollici.

HTC Zeta dovrebbe montare un processore quad core APQ8064 da 2,5 GHz, sarà dotato di 1 GB di RAM, 32 GB di memoria interna, ed inoltre equipaggiato con due fotocamere, una frontale per le videochiamate da 1,3 megapixel, e una posteriore da 8 megapixel con doppio flash LED e Full HD a 1080p.

Per quanto riguarda la connettività, il nuovo HTC Zeta sarà dotato di modulo WiFi e Bluetooth 3.0.
Ancora non si è avuta nessuna anticipazione in merito al prezzo del nuovo dispositivo dell’azienda taiwanese, né è trapelata alcuna notizia relativa ai tempi di immissione sul mercato, quindi non ci resta che attendere comunicazioni ufficiali in merito.

mercoledì 16 novembre 2011

MIUI rom basata su Android 4

Sono stati rilasciati i sorgenti di Android 4.0 Ice Cream Sandwich, gli sviluppatori più famosi hanno iniziato a pensare e a stimare quando potrebbero riuscire a rilasciare le proprie custom roms.
E dopo Cyanogen che ha annunciato la sua CyanogenMod 9.0 fra 2 mesi, anche il team MIUI fa sentire la propria voce assicurando che all’inizio di Dicembre vedremo probabilmente i primi firmware basati su Android 4.0.
Il primo smartphone a ricevere la MIUI con Android 4.0, secondo un recente twitter sarà proprio il Nexus S e probabilmente il MIUI Phone.

martedì 15 novembre 2011

SDK 4.0

E' disponibile la nuova versione dell'sdk per gli sviluppatori. Tantissime le novità e le api utilizzabili.
Il tutto lo trovate al seguente indirizzo http://developer.android.com/sdk/android-4.0.html

lunedì 14 novembre 2011

Google : Conversation Mode

Google sta provando ad innovare il mondo dei traduttori online grazie ad un app per smartphone Android in grado ascoltare, trascrivere e tradurre oralmente, le frasi pronunciati dagli utente. L’applicazione si chiama Conversation Mode ed è stata lanciata in occasione del primo anniversario del lancio di Google Traslate, uno dei servizi mobile di Big G più utilizzati e meglio riusciti, che permette di tradurre frasi e testi in 50 linguaggi. Funzionamento dell’app:
Si preme un pulsante sul touchscreen del dispositivo quando si vuole parlare. Dopo aver pronunciato una frase, che sarà “catturata” dal microfono dello smartphone, l’applicazione la tradurrà nel giro di pochi secondi nella lingua scelta e la riprodurrà ad alto volume. In questo modo si può tradurre un’intera conversazione. Basta tenere aperta l’app. Certo è che “la modalità di conversazione è ancora nelle sue prime fasi”, ha spiegato Awaneesh Verma, Product Manager di Google: la funzionalità non è sempre corretta al 100%, come qualsiasi metodo attuale di traduzione automatica, ma Google stessa spiega come i problemi nello sviluppo di un servizio simile siano tipici della natura del linguaggio: “Cangiante, vario e pieno di deviazioni basate su infiniti dialetti, accenti, slang o semplicemente discorsi rapidi”.
Attualmente le lingue disponibili nell’app sono solo tre: inglese, spagnolo e tedesco, ma da Mountain View promettono che il numero di idiomi aumenterà molto presto. Infine secondo Hugo Barra, Product Management Director di Google, Conversation Mode cambierà il modo di comunicare in futuro e diventerà il più grande traduttore simultaneo di sempre.

venerdì 11 novembre 2011

Google Music

Google ha indetto una conferenza stampa per mercoledì 16 novembre e sui siti già si vocifera che quella sarà la data di lancio di Google Music. Google Music è un’applicazione in cloud che è già attiva in versione Beta, quindi solo per invito, negli Stati Uniti. L’applicazione consente di ascoltare, comprare, scaricare e condividere musica.

Ad accettare l’idea di Google sono state molte case discografiche indipendenti assieme a EMI e alla Vivendi SA’s Universal Music Group, le altre 2 grandi, Warner e Sony, stanno prendendo tempo e faranno sapere in futuro se accettarono o meno la sfida.

L’accordo con le 4 majior è molo importante perchè servirà a dare ossigeno al neonato servizio di Google che con l’assenso anche della Warner e della Sony riuscirebbe a coprire l’87% della musica che si vende negli States.
Google Music non farebbe altro che rincorrere la Apple con il suo iTunes, ma considerando l’alto numero di dispositivi con Android si aprirebbe una bella sfida all’ultimo download.

giovedì 10 novembre 2011

Android 4 : Face Unlock

L’aggiornamento software Ice Cream Sandwich 4.0 di Android non è ancora stato rilasciato ufficialmente ma si discute già da settimane sui suoi punti di forza e sulle debolezze. Per quanto riguarda i “difetti” della nuova versione della piattaforma, si parla in questi giorni della funzionalità Face Unlock, che consente lo sblocco dello smartphone sfruttando la camera anteriore, attraverso lo “scan” del volto del possessore.

Secondo i primi utilizzatori che stanno sperimentando la piattaforma, questo nuovo metodo di unlock non è poi così infallibile, e a dimostrarlo c’è un video postato su YouTube che mostra con chiarezza i limiti della feature.

In pratica il Samsung Galaxy Nexus viene sbloccato non effettuando lo scan del volto, ma semplicemente mostrando alla camera frontale una fotografia del proprietario (in questo caso attraverso un altro device, avvicinando il display all’obbiettivo del Galaxy Nexus). Insomma, chi si aspettava metodi da hacker per poter ingannare il Face Unlock resterà sorpreso dell’estrema semplicità con cui, invece, è possibile farlo.

mercoledì 9 novembre 2011

Android 4 : Aggiornamenti

ASUS con un comunicato ufficiale ha annunciato che aggiornerà la famiglia di prodotti Eee Pad alla nuova release dell’OS. Questo vuol dire che Padfone, Transformer Prime e Eee Pad Transformer riceveranno l’update. Quando? Come tutti gli altri produttori non ha potuto fornire una data precisa. Anche la famiglia di tablet Motorola passerà ad Android 4: confermati Xoom e gli imminenti Xoom 2 e Xoom 2 Media Edition. I tablet-fonini di Samsung che verranno rinfrescati saranno invece il Galaxy Note e Galaxy Tab.

La lista degli smartphone a cui è stato promesso il sandwich al gelato è decisamente più ricca. HTC ha confermato che ci sarà del lavoro da fare per bilanciare il nuovo sistema operativo sull’hardware dei vari smartphone, ma per ora conferma un update solo per i suoi Rezound e Vivid. Non si esclude che l’update potrebbe arrivare su altri telefoni. Cattive notizie per i possessori di Nexus One, che non verrà aggiornato.

LG smentisce i rumors circolati sulla rete e conferma che Android 4 arriverà sia sull’Optimus 2X che su altri telefoni di fascia alta. Date più precise verranno annunciate quando Google rilascerà pubblicamente il nuovo sistema operativo. Anche la cinese Meizu ha pianificato aggiornamenti per i suoi telefoni. Il CEO fa sapere che MX e M9 verranno presto aggiornati.

Al momento non c’è nessuna dichiarazione da Samsung, ma sembra che Galaxy Nexus, Galaxy S II Skyrocket e Nexus S riceveranno l’update. Per quanto riguarda Sony Ericsson, è ormai ufficiale l’aggiornamento per l’Xperia 2011. Notizie positive anche per Motorola: nella lista ci sono Droid RAZR/Motorola RAZR e Droid Bionic. Per quanto riguarda Samsung: ok ufficiale per Galaxy S II e Nexus S.

Android 4

E' arrivata la nuova versione di Android "Ice Cream Sandwich".

Novità principali per l'utente finale :
- evoluta l'interfaccia utente
- nuove cartelle sulla home
- widgets ridimensionabili
- nuovo lock
- risposte rapide per le chiamate in arrivo
- migliorato inserimento del testo
- migliorato il controllo ortografico
- motore per il riconoscimento vocale

Novità anche per gli sviluppatori :
- social api
- calendar api
- visual voiceman api
- android beam
- modular sharing widget

martedì 13 settembre 2011

TextView

In questo breve tutorial vediamo come integrare immagini e testo formattato in HTML all'interno di una TextView La piattaforma Android infatti, senza particolari difficoltà, ci permette di inserire questa tipologia di contenuto all'interno dei diversi controlli grafici. Vediamo nel dettaglio l'implementazione ed il meccanismo di integrazione.

La classe HTML


La classe android.text.Html ci consente di trasformare una stringa formattata in HTML in un particolare oggetto Spanned che a sua volta viene opportunamente interpretata e visualizzata - in questa caso - in una TextView tramite il metodo setText(). Questa classe implementa i seguenti metodi statici:
  • Html.fromHtml(String source): trasforma una stringa formattata in HTML in un oggetto di tipo Spanned
  • Html.fromHtml(String source, ImageGetter imageGetter, TagHandler handler): la medesima funzione, solo che nel caso del tag <img> richiama un'implementazione dell'interfaccia ImageGetter (vedremo di cosa si tratta). Mentre per l'altro argomento quando il parser incontra un tag che non riesce ad interpretare invoca il metodo dell'interfaccia TagHandler
  • Html.toHtml(Spanned spanned): questo metodo invece effettua l'inverso, cioè da un oggetto Spanned ne ritorna una rappresentazione HTML in formato stringa
Vediamo qualche esempio di implementazione. Partiamo con qualcosa di semplice, un testo HTML che contiene grassetto, corsivo e sottolineato:
import android.text.Html;
import android.text.Spanned;
...
TextView textView ....
String source = "Esempio <b>grassetto</b>, <i>corsivo</i>, <u>sottolineato</u>";
Spanned text =  Html.fromHtml(source);
textView.setText(text);
Non tutti i tag HTML sono supportati, ma diciamo quelli più semplici ma fondamentali. Ad esempio è possibile combinare diversi colori in un testo utilizzando il tag font combinato con l'attributo color:
import android.text.Html;
import android.text.Spanned;
....
TextView viewTextColor ....
String textColorRed = "<font color='#FF0000'><b>Red</b></font>";
String textColorGreen = "<font color='#00FF00'><b>Green</b></font>";
String textColorBlue = "<font color='#0000FF'><b>Blue</b></font>";
Spanned textColor = Html.fromHtml(textColorRed+","+textColorGreen+","+textColorBlue);
viewTextColor.setText(textColor);
Ho inserito anche il grassetto per dare più risalto al testo.

E' evidente che questo meccanismo semplifica molto le cose. Infatti in altri contesti GUI ciò può diventare un'operazione abbastanza complessa.

Gestire il tag img


Altra funzionalità molto interessante è riuscire ad integrare anche le immagini insieme al testo, cosa che non è possibile effettuare con le modalità che abbiamo visto negli esempi sopra, in quanto il tag <img> viene completamente ignorato dal parser. Quindi per visualizzare anche le immagini bisogna utilizzare l'interfaccia ImageGetter che contiene questo metodo:
abstract Drawable getDrawable(String source)
Questo metodo viene invocato quando il parser incontra un tag HTML <img>. L'argomento source è la stringa dell'attributo src del tag img, il valore di ritorno dovrebbe essere una rappresentazione Drawable dell'immagine oppure null per una immagine di sostituzione generica.


Quindi bisogna distinguere diversi casi per quanto riguarda la locazione delle immagini che intendiamo visualizzare. Infatti se le immagini si trovano su un server web bisogna scaricare l'immagine dal server e trasformarla in un oggetto Drawable. In questo caso la stringa source rappresenta una risorsa http. Vediamo un'implementazione per scaricare un'immagine residente su un server web:
class HttpImageGetter implements ImageGetter {

  @Override
  public Drawable getDrawable(String source) {
    try {
      URL url = new URL(source);
      HttpURLConnection conn = (HttpURLConnection)url.openConnection();
      conn.setDoInput(true);
      conn.connect();
      InputStream is = conn.getInputStream();
      BitmapDrawable dr = new BitmapDrawable(BitmapFactory.decodeStream(is));
      dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
      return dr;
   } catch (IOException e) {
    e.printStackTrace();
    return null;
  }
}
In poche parole abbiamo utilizzato la connessione Http definita nel package java.net combinata con il BitmapFactory (per creare l'oggetto Drawable) che contiene diversi metodi che trasformano array di byte in oggetti Bitmap oppure in BitmapDrawable nel nostro caso. L'operazione setBounds() sull'oggetto Drawable serve per specificare la dimensione dell'immagine altrimenti risulterebbe nulla e l'immagine non verrebbe visualizzata. Mettiamo il caso che siamo all'interno di un'Activity, facciamo un esempio che utilizza questo meccanismo:
TextView imgTextView = ....
String source = "<img src='http://www.example.com/image.png' />";
imgTextView.setText(Html.fromHtml(source, new HttpImageGetter(), null);



Adesso invece vediamo di implementare un meccanismo per reperire le immagini che si trovano in locale. Quindi possono essere o nelle risorse oppure nella sdcard. Se ad esempio abbiamo delle immagini che sono posizionate nelle risorse, cioè nella cartella drawable-xxxx/ del nostro progetto allora bisogna semplicemnte utilizzare questa implementazione:
private class LocaImageGetter implements Html.ImageGetter {

  private Context context;

  public ImageGetterSmile(Context context) {
    this.context = context;
  }

  @Override
  public Drawable getDrawable(String source) {
    Drawable d = null;
    int resID = context.getResources().getIdentifier(source,
      "drawable", context.getPackageName());
    d = context.getApplicationContext().getResources().getDrawable(
    resID);
    d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
    return d;
  }
}
La stringa source deve contenere il nome della risorsa. Se ad esempio nelle cartelle drawable-xxxx/ abbiamo un'immagine logo.png e vogliamo visualizzarla in codice HTML dobbiamo procedere in questo modo:
TextView textView...
String sourceHtml = "<img src='logo' />"
Spanned spanned = Html.fromHtml(sourceHtml, new LocalImageGetter(this), null);
textView.setText(spanned);



Applicazione di esempio con le emoticons


Come esempio propongo di realizzare una semplice applicazione che visualizza in una TextView un testo inserito da noi in una EditText trasformando le stringhe ':-) :-( :-D' etc.. in immagini. Ecco il codice dell'Activity:
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.text.Html.ImageGetter;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TextView;
public class ActivityEmoticons extends Activity implements OnClickListener, ImageGetter {

  private EditText editText;
  private TextView textView;


  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TableLayout layout = new TableLayout(this);
    layout.setPadding(5, 5, 5, 5);
    super.setContentView(layout);
    editText = new EditText(this);
    textView = new TextView(this);
    Button convertButton = new Button(this);
    convertButton.setText("Converti");
    convertButton.setOnClickListener(this);
    layout.addView(editText);
    layout.addView(convertButton);
    layout.addView(textView);
  }

  @Override
  public Drawable getDrawable(String source) {
    Drawable d = null;
    int resID = this.getResources().getIdentifier(source,
      "drawable", this.getPackageName());
    d = this.getApplicationContext().getResources().getDrawable(resID);
    d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
    return d;
  }

  @Override
  public void onClick(View arg0) {
    String source = replaceEmoticons(editText.getText().toString());
    Spanned spanned = Html.fromHtml(source, this, null);
    textView.setText(spanned);
  }

  protected String replaceEmoticons(String source) {
    source = source.replace(":-)", "<img src='happy' />");
    source = source.replace(":-(", "<img src='sad' />");
    source = source.replace(":-O", "<img src='surprised' />");
    source = source.replace(":-D", "<img src='laughing' />");
    source = source.replace(";-)", "<img src='winking' />");
    return source;
  }
}
Il codice è abbastanza chiaro, abbiamo utilizzato il meccanismo per reperire le immagini in locale. Mentre il metodo replaceEmoticons() sostiutisce alle smile in formato stringa il tag img che punta (attributo src) al nome delle immagini che si trovano nella cartella drawable/ del progetto.

mercoledì 10 agosto 2011

Google Maps 5.7

E' uscita Google Maps 5.7 per Android con  l’integrazione di Transit Navigation in versione beta, migliori suggerimenti per i risultati di ricerca e un aggiornamento della funzione per ottenere indicazioni stradali, utile quando ci si trova in zone sconosciute della città o in località del tutto nuove.

Transit Navigation (Beta)

Oggi Google Maps Navigatore (Beta) permette di ricevere indicazioni stradali tramite GPS, a piedi o in auto, tali da percorrere oltre 19 miliardi di chilometri di strade. Da oggi, questa navigazione satellitare GPS diventa ancora più utile, offrendo indicazioni relative al trasporto pubblico in oltre 400 città del mondo (comprese alcune città italiane).


L'articolo completo e' al seguente link.

mercoledì 13 luglio 2011

Menu con le ViewStub

Prima di tutto creiamo un nuovo progetto con Eclipse.
Il Manifest non subirà cambiamenti particolari quindi tralasciamo la sua visualizzazione e analizziamo invece il layout dell’Activity principale.

Sorgenti:
stubs.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical"
android:gravity="center">
<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Click...but do nothing" />
</LinearLayout>

<ViewStub android:id="@+id/stub_menu" android:inflatedId="@+id/panel_menu"
android:layout="@layout/menu" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_gravity="top" />

</merge>

La prima cosa che salta all’occhio direi è l’utilizzo del tag <merge>
Cos’è ? A cosa serve ? Il tag <merge> è stato creato per ridurre il numero di livelli nella gerarchia delle Views, sembra un po’ ostica da capire come cosa, ma vedendolo in azione si intuisce meglio il suo scopo. In altre parole, basta pensare che ogni View, e quindi ogni Layout, è figlio di un’altra View (o Layout) e difatti quando si crea un XML layout bisogna specifare un root Layout, che verrà istanziato poi al momento di generare il codice Java corrispondente dalla classe LayoutInflater. In questo caso però, quando il LayoutInflater incontrerà il tag <merge> non creerà una nuova istanza di un Layout ma non farà altro che unire la nostra View alla top-level View, cioè alla View di alto livello già istanziata. Comunque per altri chiarimenti vi rimando alla bibliografia in fondo al tutorial. Un altro motivo per cui ho utilizzato il tag <merge> è per poter sovrapporre le due View del layout, che sono il LinearLayout e, per l’appunto, la nostra ViewStub !
Il LinearLayout comprende una EditText e un Button, che ho messo a puro scopo indicativo, mentre vorrei soffermarmi un po’ sulla ViewStub, anche perché è il motivo di questo tutorial !

Analizzando la ViewStub

La ViewStub è una View che non ha dimensioni, non viene disegnata e che quindi non viene considerata in nessun modo all’interno del nostro layout. In pratica l’unica cosa che facciamo è dichiarare la sua esistenza per poterla poi usare in seguito quando ne avremo bisogno ! Il beneficio di usare una ViewStub è quello di non appesantire il sistema nella creazione di nuovi elementi a runtime, un po’ come la tecnica del lazy loading delle immagini,che spopola nel progettazione Web 2.0

Gli attributi della ViewStub

Quello che ci serve per dichiarare una ViewStub è un android:id, cioè l’identificativo della ViewStub stessa, e un android:layout, che non è altro che il riferimento al file XML contenente il layout che andrà a “popolare” la ViewStub. Un terzo attributo è l’android:inflateId, cioè l’identificativo del file XML contenente il layout (quello specificato prima). Per il resto, larghezza e altezza ecc.. sono i classici attributi che ritroviamo nella creazione dei layout. Nel caso specifico, ho settato come android:layout_gravity il valore top, in modo da posizionare la ViewStub in alto nello schermo.
Ok direi che per ora può bastare, vedremo successivamente come gestire la ViewStub all’interno dell’Activity. Per ulteriori informazioni vi rimando alla bibliografia in fondo a questo tutorial.

Il layout del menu

Quello di seguito altro non è che il layout XML del menu vero e proprio, quello che sarà dichiarato nell’attributo android:layout della ViewStub

Sorgenti:
menu.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:background="#99000000">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content" android:padding="20dp"
android:orientation="horizontal" android:gravity="center"
android:background="#888">
<Button android:id="@+id/button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Button 1" />
<Button android:id="@+id/button_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Button 2" />
<Button android:id="@+id/button_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Button 3" />
</LinearLayout>
</LinearLayout>

Molto semplice, due LinearLayout, uno dentro l’altro. Il secondo è quello che contiene i 3 pulsanti di esempio, mentre il primo è il nostro root Layout !
Ed ecco il trick . Nel primo LinearLayout ho settato come attributo android:background il valore “#99000000” , il quale darà il nostro tocco di stile al menu, rendendo lo sfondo trasparente (o traslucente). Ma cosa sono quei numeri ? Non è altro che il riferimento ad un colore del tipo rgb con una componente alpha-transparency, in pratica i primi due numeri -99- definiscono la alpha-transparency (a), i seguenti 2 numeri -00- la componente red (r), i successivi -00- il green (g) e infine gli ultimi due -00- il blue (b). Tradotto, ho settato lo sfondo del LinearLayout con il colore nero e un grado di trasparenza pari a 99. Provate a variare i primi due numeri (da 00 a 99) per vedere le varie differenze di trasparenza.

L’Activity principale

Ed eccoci finalmente al codice dell’Activity principale (nonché l’unica del tutorial).

Sorgenti:
StubActivity.java
Codice (Java): [Seleziona]
public class StubActivity extends Activity {
/** Called when the activity is first created. */
private View menu;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stubs);
menuInit();
}

private void menuInit() {
menu = ((ViewStub) findViewById(R.id.stub_menu)).inflate();
menu.setVisibility(View.GONE);
Button b1 = (Button) menu.findViewById(R.id.button_1);
b1.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(),
"Click on Button 1",
Toast.LENGTH_SHORT).show();
}

});
Button b2 = (Button) menu.findViewById(R.id.button_2);
b2.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(),
"Click on Button 2",
Toast.LENGTH_SHORT).show();
}

});
Button b3 = (Button) menu.findViewById(R.id.button_3);
b3.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(),
"Click on Button 3",
Toast.LENGTH_SHORT).show();
}

});
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
int visibility = menu.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE;
menu.setVisibility(visibility);
break;
case KeyEvent.KEYCODE_BACK:
if (menu.getVisibility() == View.VISIBLE) {
menu.setVisibility(View.GONE);
} else
this.finish();
break;
default:
break;
}
return false;
}

}

Come sempre, creiamo una classe che estende Activity e settiamo la View principale con il file stubs.xml, dopodiché inizializziamo il menu.
Ho creato il metodo menuInit() proprio per fare questo, vediamo cosa fa.

Codice (Java): [Seleziona]
menu = ((ViewStub) findViewById(R.id.stub_menu)).inflate();
Ecco il tassello mancante per l’utilizzo delle ViewStub. Il metodo inflate() inserisce di fatto la ViewStub all’interno del nostro layout, restituendo il riferimento alla View che contiene il layout del menu. Da questo momento la View diventa visibile a tutti gli effetti, ecco perché con la successiva riga di codice

Codice (Java): [Seleziona]
menu.setVisibility(View.GONE);
Rimuovo la View da flusso delle View visibili a schermo, perché per il momento il menu non deve essere visibile.
Ora che abbiamo il riferimento alla View del menu, possiamo interagire con i componenti che la popolano. Nello specifico, è stato assegnato un OnClickListener ai 3 pulsanti del menu, i quali al loro click faranno apparire a video un messaggio.

Gestire il menu sull’onKeyDown

Ora che il menu è inizializzato possiamo mostrarlo e renderlo fruibile. In questo tutorial ho deciso di farlo apparire alla pressione del tasto menu del device (ma guarda il caso… ) ma nulla vieta di gestirlo diversamente. Il codice non è ottimizzato al massimo, ma d’altronde è solo un esempio.
Con queste righe di codice

Codice (Java): [Seleziona]
int visibility = menu.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE;
menu.setVisibility(visibility);

Rendo visibile o meno il menu alla pressione del tasto menu.
Dato che stiamo facendo l’override del metodo onKeyDown dell’Activity, il tasto “indietro” del device sarà ora inutilizzabile, quindi andiamo a gestire anche questo, per poter permettere l’uscita dall’applicazione nel modo tradizionale, e già che ci siamo aggiungiamo un altro tocco di stile al nostro menu, nascondendolo anche alla pressione del suddetto tasto

Codice (Java): [Seleziona]
if (menu.getVisibility() == View.VISIBLE) {
menu.setVisibility(View.GONE);
} else this.finish();

E con questo è tutto, abbiamo realizzato un menu con sfondo trasparente con il solo ausilio delle ViewStub. In questo modo l’app risulta notevolmente meno appesantita, il nostro codice è modulare e la nostra ViewStub è riusabile per altri progetti.

Bibliografia:

giovedì 7 aprile 2011

Length-prefix message framing for streams

/// <summary>
/// Maintains the necessary buffers for applying a length-prefix message framing protocol over a stream.
/// </summary>
/// <remarks>
/// <para>Create one instance of this class for each incoming stream, and assign a handler to <see cref="MessageArrived"/>. As bytes arrive at the stream, pass them to <see cref="DataReceived"/>, which will invoke <see cref="MessageArrived"/> as necessary.</para>
/// <para>If <see cref="DataReceived"/> raises <see cref="System.Net.ProtocolViolationException"/>, then the stream data should be considered invalid. After that point, no methods should be called on that <see cref="PacketProtocol"/> instance.</para>
/// <para>This class uses a 4-byte signed integer length prefix, which allows for message sizes up to 2 GB. Keepalive messages are supported as messages with a length prefix of 0 and no message data.</para>
/// <para>This is EXAMPLE CODE! It is not particularly efficient; in particular, if this class is rewritten so that a particular interface is used (e.g., Socket's IAsyncResult methods), some buffer copies become unnecessary and may be removed.</para>
/// </remarks>
public class PacketProtocol
{
/// <summary>
/// Wraps a message. The wrapped message is ready to send to a stream.
/// </summary>
/// <remarks>
/// <para>Generates a length prefix for the message and returns the combined length prefix and message.</para>
/// </remarks>
/// <param name="message">The message to send.</param>
public static byte[] WrapMessage(byte[] message)
{
// Get the length prefix for the message
byte[] lengthPrefix = BitConverter.GetBytes(message.Length);
// Concatenate the length prefix and the message
byte[] ret = new byte[lengthPrefix.Length + message.Length];
lengthPrefix.CopyTo(ret, 0);
message.CopyTo(ret, lengthPrefix.Length);
return ret;
}
/// <summary>
/// Wraps a keepalive (0-length) message. The wrapped message is ready to send to a stream.
/// </summary>
public static byte[] WrapKeepaliveMessage()
{
return BitConverter.GetBytes((int)0);
}
/// <summary>
/// Initializes a new <see cref="PacketProtocol"/>, limiting message sizes to the given maximum size.
/// </summary>
/// <param name="maxMessageSize">The maximum message size supported by this protocol. This may be less than or equal to zero to indicate no maximum message size.</param>
public PacketProtocol(int maxMessageSize)
{
// We allocate the buffer for receiving message lengths immediately
this.lengthBuffer = new byte[sizeof(int)];
this.maxMessageSize = maxMessageSize;
}
/// <summary>
/// The buffer for the length prefix; this is always 4 bytes long.
/// </summary>
private byte[] lengthBuffer;
/// <summary>
/// The buffer for the data; this is null if we are receiving the length prefix buffer.
/// </summary>
private byte[] dataBuffer;
/// <summary>
/// The number of bytes already read into the buffer (the length buffer if <see cref="dataBuffer"/> is null, otherwise the data buffer).
/// </summary>
private int bytesReceived;
/// <summary>
/// The maximum size of messages allowed.
/// </summary>
private int maxMessageSize;
/// <summary>
/// Indicates the completion of a message read from the stream.
/// </summary>
/// <remarks>
/// <para>This may be called with an empty message, indicating that the other end had sent a keepalive message. This will never be called with a null message.</para>
/// <para>This event is invoked from within a call to <see cref="DataReceived"/>. Handlers for this event should not call <see cref="DataReceived"/>.</para>
/// </remarks>
public Action<byte[]> MessageArrived { get; set; }
/// <summary>
/// Notifies the <see cref="PacketProtocol"/> instance that incoming data has been received from the stream. This method will invoke <see cref="MessageArrived"/> as necessary.
/// </summary>
/// <remarks>
/// <para>This method may invoke <see cref="MessageArrived"/> zero or more times.</para>
/// <para>Zero-length receives are ignored. Many streams use a 0-length read to indicate the end of a stream, but <see cref="PacketProtocol"/> takes no action in this case.</para>
/// </remarks>
/// <param name="data">The data received from the stream. Cannot be null.</param>
/// <exception cref="System.Net.ProtocolViolationException">If the data received is not a properly-formed message.</exception>
public void DataReceived(byte[] data)
{
// Process the incoming data in chunks, as the ReadCompleted requests it
// Logically, we are satisfying read requests with the received data, instead of processing the
// incoming buffer looking for messages.
int i = 0;
while (i != data.Length)
{
// Determine how many bytes we want to transfer to the buffer and transfer them
int bytesAvailable = data.Length - i;
if (this.dataBuffer != null)
{
// We're reading into the data buffer
int bytesRequested = this.dataBuffer.Length - this.bytesReceived;
// Copy the incoming bytes into the buffer
int bytesTransferred = Math.Min(bytesRequested, bytesAvailable);
Array.Copy(data, i, this.dataBuffer, this.bytesReceived, bytesTransferred);
i += bytesTransferred;
// Notify "read completion"
this.ReadCompleted(bytesTransferred);
}
else
{
// We're reading into the length prefix buffer
int bytesRequested = this.lengthBuffer.Length - this.bytesReceived;
// Copy the incoming bytes into the buffer
int bytesTransferred = Math.Min(bytesRequested, bytesAvailable);
Array.Copy(data, i, this.lengthBuffer, this.bytesReceived, bytesTransferred);
i += bytesTransferred;
// Notify "read completion"
this.ReadCompleted(bytesTransferred);
}
}
}
/// <summary>
/// Called when a read completes. Parses the received data and calls <see cref="MessageArrived"/> if necessary.
/// </summary>
/// <param name="count">The number of bytes read.</param>
/// <exception cref="System.Net.ProtocolViolationException">If the data received is not a properly-formed message.</exception>
private void ReadCompleted(int count)
{
// Get the number of bytes read into the buffer
this.bytesReceived += count;
if (this.dataBuffer == null)
{
// We're currently receiving the length buffer
if (this.bytesReceived != sizeof(int))
{
// We haven't gotten all the length buffer yet: just wait for more data to arrive
}
else
{
// We've gotten the length buffer
int length = BitConverter.ToInt32(this.lengthBuffer, 0);
// Sanity check for length < 0
if (length < 0)
throw new System.Net.ProtocolViolationException("Message length is less than zero");
// Another sanity check is needed here for very large packets, to prevent denial-of-service attacks
if (this.maxMessageSize > 0 && length > this.maxMessageSize)
throw new System.Net.ProtocolViolationException("Message length " + length.ToString(System.Globalization.CultureInfo.InvariantCulture) + " is larger than maximum message size " + this.maxMessageSize.ToString(System.Globalization.CultureInfo.InvariantCulture));
// Zero-length packets are allowed as keepalives
if (length == 0)
{
this.bytesReceived = 0;
if (this.MessageArrived != null)
this.MessageArrived(new byte[0]);
}
else
{
// Create the data buffer and start reading into it
this.dataBuffer = new byte[length];
this.bytesReceived = 0;
}
}
}
else
{
if (this.bytesReceived != this.dataBuffer.Length)
{
// We haven't gotten all the data buffer yet: just wait for more data to arrive
}
else
{
// We've gotten an entire packet
if (this.MessageArrived != null)
this.MessageArrived(this.dataBuffer);
// Start reading the length buffer again
this.dataBuffer = null;
this.bytesReceived = 0;
}
}
}
}