Visualizzazione post con etichetta Intent. Mostra tutti i post
Visualizzazione post con etichetta Intent. Mostra tutti i post

mercoledì 9 febbraio 2011

Android Base: Un esempio di Intent Esplicito.

In un’Intent Esplicito specifichiamo l’Activity target invocandola direttamente. Tale gestione è utile nel caso si vogliano gestire messaggi all’interno delle proprie applicazioni.
A differenza delle Intent Implicite in cui dichiariamo il tipo di Intent che vogliamo sia gestita e deleghiamo alla piattafroma Android il compito di trovare l’Activity in grado di operare sui dati di cui abbiamo bisogno, ora definiamo a tempo di compilazione chi sarà ad “occuparsi dei nostri dati”.


Chiarirò tutto con un semplice esempio.
Supponiamo di avere due Activity:
·         InvokeActivity
·         InvokedActivity

Che, ovviamente, rappresentano l’Activity chiamante e quella chiamata.
Partiamo dalla definizione della nostra applicazione col seguente AndroidManifest.xml :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="it.delfio.android.activity.intents" android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".InvokeActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".InvokedActivity" android:label="@string/app_name">
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="3" />
</manifest>



L’InvokeActivity contiene un bottone “Invoca Activity” (da inserire nel file xml di layout: main.xml) che, una volta cliccato, permette di invocare l’Activity target.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent" android:layout_height="wrap_content">
       <TextView 
           android:layout_width="fill_parent" android:layout_height="wrap_content"
           android:text="@string/testoInvokeActivity" android:layout_weight="1"/>
        <Button android:text="@string/invokeButtonText"
              android:id="@+id/invokeButton" android:layout_gravity="center_horizontal"
              android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</LinearLayout>


Di seguito il codice dell’InvokeActivity con in evidenza la gestione dell’evento onClick lanciato alla pressione del bottone con id invokeButton                     

package it.delfio.android.activity.intents;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class InvokeActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
   Button invokeButton = (Button)findViewById(R.id.invokebutton);
   invokeButton.setOnClickListener(new OnClickListener() { 
     public void onClick(View v) {
        Intent explicitIntent = new Intent(InvokeActivity.this,InvokedActivity.class);
        startActivity(explicitIntent);
     }
   });
  }
}


Recuperiamo il pulsante che permetterà di lanciare il nostro Intent attraverso l’istruzione:

                     (Button)findViewById(R.id.invokebutton)

Di seguito, attraverso il costruttore :

                  Intent(InvokeActivity.this,InvokedActivity.class)

Possiamo specificare l’Activity sorgente e quella destinazione della chiamata, che verrà fatta sempre attraverso la chiamata:

                 startActivity(explicitIntent);

Definiamo nel file /res/values/string.xml tutte le stringhe che utilizzaremo nell’applicazione:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="testoInvokeActivity">Activity che lancia una Intent Esplicita</string>
    <string name="app_name">Prova Intent Esplicita</string>
<string name="invokeButtonText">Invoca Activity   </string>
<string name="testoInvokedActivity">Activity chiamata esplicitamente. Non abbiamo configurato nessun Intent Filter, quindi per invocare la seconda Activity bisogna chiamarla esplicitamente.</string>
</resources>


Alla pressione del bottone, come accennato in precedenza viene lanciata l’Intent a cui risponderà la nostra seconda InvokedActivity, il cui layout è definito dal file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent" android:layout_height="wrap_content">
    <TextView android:text="@string/testoInvokedActivity"
      android:layout_width="fill_parent" android:layout_height="wrap_content" >
    </TextView>
</LinearLayout>


Che contiene un unico campo testo da visualizzare appena viene invocata e visualizzata attraverso il semplice codice:

package it.delfio.android.activity.intents;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class InvokedActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.invokedactivity);
  }
}


Infine, provando a lanciare la nostra semplice applicazione sull’emulatore, dovremmo ottenere:



giovedì 3 febbraio 2011

Android Base: Intent e Intent Filter. Un esempio di Intent Implicito.

Nel precedente Post ho parlato di Intent e di Intent Filter, senza specificare di cosa si trattasse.
Gli Intent sono dei messaggi asincroni che permettono alle varie Activity di inviare o ricevere dati da e verso altre Activity o Servizi.
Per esempio un'applicazione può fare richiesta, attraverso un'intent, di informazioni relative ad un contatto, mentre un Intent Filter mi permette di registrarmi su un determinato tipo di dato (praticamente dico che posso gestire un certo tipo di dati).
Ci sono due tipi di Intent:

  • Impliciti
  • Espliciti
Gli Intent Espliciti chiamano direttamente il componente di cui hanno bisogno (per esempio una classe Java), mentre gli Intent impliciti chiedono al sistema do eseguire un servizio (per esempio aprire un Browser).
Quando selezioniamo un dato in un'applicazione e richiediamo un certo servizio Android determinerà le applicazioni adatte a gestirlo e proporrà  all'utente una scelta. La determinazione di quali applicazioni presentare nella scelta é basata sugli Intent Filter, rappresentati dalla classe "android.content.IntentFilter". Gli Intent Filter sono in genere definiti tramite l'AndroidManifest.xml. Un componente utilizza gli Intent Filter per definire quali Intent sia in grado di gestire, se non viene configurato nessun Intent Filter, significa che possiamo chiamare il componente solo in modo esplicito.
Per chiarire meglio la differenza tra i due tipi di Intent, facciamo degli esempi.

Intent Implicito

Supponiamo che voglia aprire un URL e vogliamo fare in modo che il sistema inserisca tra le scelte possibili per gestirlo, la nostra Activity.
Creaiamo, a tale scopo, il package it.delfio.android.activity.intents con l’Activity ImplicitManager. Partendo dalla definizione di un view Layout:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"    android:layout_height="fill_parent">

<Button android:id="@+id/Bottone1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Call browser"  android:onClick="IntentManager">
</Button>
</LinearLayout>


Per poter utilizzare alcuni tipi di Intent bisogna configurarli sul file manifest della nostra applicazione. Dobbiamo, quindi, avere:



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="it.delfio.android.intents"
      android:versionCode="1" android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".IntentsManager"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="9" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>


La nostra Activity che gestirà la chiamata alla Intent sarà:


package it.delfio.android.activity.intents;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class ImplicitManager extends Activity {
       /** Called when the activity is first created. */
       @Override
       public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.main);
       }

       public void callIntent(View view) {
         Intent intent = null;
         if (R.id.Bottone1==view.getId()) {
          intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.google.it"));
          startActivity(intent);
          startActivityForResult(intent, -1);          
         }
       }
      
       @Override
       public void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (resultCode == Activity.RESULT_OK && requestCode == 0) {
           String result = data.toURI();
           Toast.makeText(this, result, Toast.LENGTH_LONG);
         }
       }
}



Ho inserito nella mia Activity un metodo che permette di gestire gli eventuali dati di ritorno provenienti dalla Activity che ha gestito l’Intent (per esempio nel caso della scelta di un nominativo dalla rubrica). In questo caso avrei dovuto lanciare l’Intent tramite il comando:

            startActivityForResult(intent, 0);

Il secondo parametro rappresenta il request code. Far partire una Activity con un valore negativo di questo parametro equivale a lanciare il metodo startActivity(intent).  Da notare che per Intent come Intent.ACTION_VIEW, Intent.ACTION_MAIN e altre (che non prevedono un valore di ritorno), non ha senso chiamare l’activity con tale metodo che, tra l’altro, potrebbe ritornare un valore non atteso. Per esempio, nel caso di lancio di una Activity che prevede l’avvio sullo stesso thread del chiamante, otterremo come risposta un risultato di  CANCEL.

Nel prossimo articolo parlerò delle Intent Esplicite che meritano un Post a parte.

lunedì 31 gennaio 2011

Categorizzare un Intent Filter

Cominciamo qui una serie di Tips per chi desidera sviluppare applicazioni mobile su piattaforma Android.
Come ben sappiamo, la piattaforma Android è una piattaforma "aperta". Una conseguenza di questo è che le nostre applicazioni girano con gli stessi privilegi delle applicazioni native.
E' possibile, quindi, fare in modo che una nostra applicazione venga utilizzata al posto della Home nativa (essa stessa è una Activity) e per fare questo basta configurare il nostro AndroidManifest.xml in questo modo :

<activity android:name="miaHome">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.HOME"/>
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>


Come si può vedere non abbiamo fatto altro che definire in Intent Filter (in prossimi Post parleremo più in dettaglio di cosa siano e a cosa servono), e scegliere per esso la categoria a cui appartiene anche la Home nativa ovvero android.intent.category.HOME, è stata inoltre inserita la cetegoria android.intent.category.DEFAULT per fare in modo che la nostra Activity sia quella di default quando si preme il punsante Home sul dispositivo.