Lipiec 25, 2011
Intent Podstawowe komponenty Tutoriale
Intencje obok Aktywności są jednym z podstawowych komponentów z których zbudowane są Androidowe aplikacje. Mechanizm ten odpowiedzialny jest przede wszystkim za obsługę rozkazów wydawanych przez użytkownika. Za pomocą intencji możemy wprowadzić komunikację pomiędzy aplikacjami (lub mniejszymi komponentami, jak Usługi, Aktywności itp.). Jednak najważniejszym zadaniem tego komponentu jest uruchamianie odpowiednich aplikacji/Aktywności.
Jako, że uruchamianie Aktywności jest najczęstszym zastosowaniem Intencji, wpis ten będzie niemal w całości poświęcony tej czynności.
Intencje uruchamiające podzielone zostały na dwa główne typy:
Intencja tak, jak łatwo się domyślić, uruchomi aktywność MainActivity.
W tym wypadku informujemy nasz system o tym, że chcemy zobaczyć dane (Intent.ACTION_VIEW) zapisane pod adresem URI (w tym wypadku adres URL strony). Przykłady innych zastosowań możemy znaleźć w dokumentacji.
Oprócz uruchamiania komponentów Intencje pozwalają na dołączanie informacji, które mogą być przesłane do uruchamianego obiektu. Służy do tego zestaw metod putExtra(…), które pozwalają na dołączanie danych w postaci typów prostych (lub paczek Bundle). Przykładem takiej operacji niech będzie:
Aby pobrać powyższe dane w nowo uruchomionej Aktywności należy wykonać komplet poniższych operacji:
Pierwsza linijka pobiera Intencję, która uruchomiła Aktywność (należy pamiętać o sprawdzeniu czy przypadkiem zawracana wartość nie jest nullem).
Druga linijka to pobranie wartości za pomocą jednej z metod get…Extra(…). Pierwszym argumentem tych metod jest nazwa pod którą dana wartość została zapisana. Drugim natomiast – wartość domyślna, na wypadek gdyby Intencja nie zawierała żadnych danych zapisanych pod podanym ciągiem znaków.
Zbudujemy teraz aplikację, która wykorzystuje kilka podstawowych możliwości dostarczanych przez mechanizm Intencji.
Tworzymy aplikację składającą się z 3 Aktywności. Oto zrzuty oraz kod źródłowy poszczególnych layoutów przygotowanych dla każdego okna:
main.xml
second.xml
third.xml
Na koniec jeszcze plik strings.xml, w którym przechowujemy napisy naszej aplikacji:
Przypominam też o tym aby każdy z tych layoutów ustawić w Aktywnościach, oraz o tym by nowe Aktywności opisać w pliku AndroidManifest.xml .
W naszej aplikacji zaprezentujemy 4 przykłady opisujące różne możliwości jakie dają nam intencje. Zaczniemy oczywiście od inicjalizacji elementów layoutu i ustawienia listenerów na naszych przyciskach w MainActivity:
Jak widać, zaznaczyłem 4 metody, których implementacją zajmiemy się w poszczególnych przykładach.
Sposób uruchomienia nowej Aktywności został opisany w części teoretycznej tego artykułu. W naszej aplikacji wygląda to w ten sposób:
Wszystko zgodnie z tym co opisaliśmy wcześniej. Argumentami konstruktora Intencji są: kontekst aplikacji oraz obiekt Class klasy Aktywności, którą chcemy uruchomić.
W drugim przykładzie urozmaicimy nieco kod zaprezentowany powyżej. System bowiem daje nam możliwość uruchomienia Aktywności po to, by zwróciła nam ona jakieś dane (np. otwieramy listę kontaktów po to by pobrać z niej konkretną osobę).
My otworzymy nową Aktywność po to by pobrać z niej dane wpisane do pola tekstowego.
Zaczynamy od implementacji metody wywoływanej przez drugi przycisk naszej aplikacji:
Jak widać, różnicą w stosunku do poprzedniego przykładu jest metoda uruchamiająca Aktywność. Metoda startActivityForResult(…) przyjmuje bowiem jeszcze jeden argument. Jest nim identyfikator (liczba całkowita), na podstawie którego będzie można później stwierdzić skąd przyszła odpowiedź. U nas identyfikatorem jest stała klasy MainActivity:
Teraz powinniśmy napisać mechanizm, który obsłuży zwracany wynik. Aby to zrobić należy przesłonić metodę Aktywności – onActivityResult(int requestCode, int resultCode, Intent data). Jak widać, przyjmuje ona 3 argumenty:
Nasza implementacja wygląda w ten sposób:
Na koniec pozostało nam jeszcze zaimplementowanie mechanizmu zwracającego dane. Oto kod całej Aktywności ThirdActivity, która zgodnie z naszym założeniem powinna odesłać dane z pola tekstowego:
Jak widać odesłanie wyników jest stosunkowo prostą czynnością. Sprowadza się do:
Jako ciekawostkę dodam, że metoda finish(), którą możemy znaleźć w 16 linijce powyższego kodu kończy działanie Aktywności.
To tyle w kwestii przesyłania i odbierania danych. Przejdźmy teraz do następnego przykładu.
W tym przykładzie uruchomimy Aktywność, którą wybierze za nas system. Tym razem bowiem zamiast wskazywać konkretną klasę Aktywności, przekażemy jedynie akcję oraz dane, na których będziemy chcieli ją przeprowadzić. Jak to wygląda w praktyce? Tak:
Jak widać, akcją którą chcemy wykonać jest Intent.ACTION_VIEW czyli… obejrzyj. Danymi, na których podziałamy rzeczoną akcją jest adres url. Nietrudno zatem się domyślić, że system uruchomi naszą domyślną przeglądarkę i wyświetli stronę przekazaną w adresie url.
W zasadzie przykład ten jest powieleniem powyższego. Dzięki niemu jednak chciałem uzmysłowić ważną kwestię. Intencje bowiem operują na na adresach URI, a nie tylko podrzędnych do nich adresach URL (różnica URI a URL). Dzięki temu, oprócz adresów www możemy korzystać z takich zasobów jak:
W naszym przykładzie spróbujemy wyświetlić dane zapisane pod adresem URI geo:50.07,19.97:
Jak widać kod jest nieco dłuższy niż można było się tego spodziewać. Wynika to z faktu, że zabezpieczyliśmy go przed wysyłaniem Intencji, których system nie potrafi obsłużyć. Jak się bowiem okazuje, kiedy w systemie nie ma aplikacji mogącej obsłużyć nasze zapytanie, otrzymujemy wyjątek android.content.ActivityNotFoundException: No Activity found to handle Intent. Dlatego aby temu zapobiec, zaimplementowaliśmy metodę isIntentAvailable(Intent) (przy okazji odsyłam do odpowiedniego snippetu), której kod wygląda tak:
Oto co stanie się, gdy nasze urządzenie nie posiada aplikacji obsługującej adres URI geo: (w tym wypadku zrzut z emulatora AVD)
I tym sposobem skończyliśmy nasz wstęp do wykorzystania Intencji w naszych aplikacjach.
Cały projekt dostępny jest na naszym githubie – HelloIntents.
Cały kod źródłowy plików .xml wklejony został na początku opisu naszej przykładowej aplikacji.
MainActivity.java
SecondActivity.java
ThirdActivity.java
[…] powiadomień (Notifications) są jednym z podstawowych komponentów systemu (obok Aktywności, Intencji oraz Dostarczycieli treści). Jest to zbiór elementów, które „zaczepiają” […]
Klasa MainActivity odwołuje do klasy bibliotecznej. Wszystko niby dobrze ale nie w klasie MainActivity nie rozpoznaje RESPONSE.
Klasę biblioteczną mam dodaną w Manifest i zaimportowaną :/. Co może być jeszcze nie tak?
Zaloguj się lub skorzystaj z profilu:
Możesz również zostawić komentarz bez rejestracji, korzystając z poniższego formularza:
Musisz być zalogowany aby móc pisać komentarze.
Wstęp do Intencji (Intents)
Powiązane linki
O możliwościach intencji
Przykładowa aplikacja
Typy uruchomień
Przesyłanie danych
Przygotowanie
Kod źródłowy aplikacji
Kompletny kod źródłowy
Komentarze (2)
Prześlij komentarz
Przykład 1 – jawne uruchamianie nowej Aktywności
Przykład 2 – uruchamianie Aktywności w celu otrzymania od niej odpowiedzi
Przykład 3 – niejawne uruchamianie Aktywności
Przykład 4 – niejawne uruchamianie Aktywności (nie tylko adresu url)
- Jawne (explicit) – czyli takie, w których jasno precyzujemy obiekt, który chcemy stworzyć. W tym wypadku jednym z argumentów konkstruktora Intencji jest obiekt typu Class (np. MainActivity.class) wskazujący na klasę, której obiekt chcemy stworzyć. Najprostszy przykład to:
Intent intent = new Intent(context, MainActivity.class);
- Niejawne (implicit) – są to intencje, w których zawieramy informacje o tym co chcemy zrobić, bez podawania konkretnych klas, które mają to zrealizować. Najczęściej opisujemy to dwoma informacjami – co chcemy zrobić i na jakich danych chcemy tą czynność wykonać. W takim wypadku to system (za pomocą Filtrów Intencji, o których polecam poczytać, choćby na naszej stronie) decyduje jaka Aktywność ma być uruchomiona. Przykład:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
- int requestCode – jest to liczba całkowita, na podstawie której możemy zidentyfikować która Aktywność zwróciła nam wynik (ta sama, którą ustawiliśmy w metodzie startActivityForResult(…).
- int resultCode – liczba całkowita na podstawie której możemy określić stan wykonanej operacji (np. za pomocą stałych Activity.RESULT_OK lub Activity.RESULT_CANCELED).
- Intent data – dane zwrócone z Aktywności.
- Numery telefonów (tel:123456),
- Dane zamieszczone w gdzieś w pamięci telefonu (książka telefoniczna – content://contacts/people/…)
- i wiele innych (np. adres położenia geograficznego przedstawiony poniżej).
- Utworzenia obiektu Intent, który chcemy odesłać (linijka 23),
- Wpisania do niego danych (linijka 24) za pomocą metod putExtra(…),
- Ustawienia odpowiedzi za pomocą metody setResult(int resultCode, Intent data) – linijka 25. Argumenty ustawiane w tej metodzie pokrywają się z argumentami metody onActivityResult(…).
intent.putExtra("UserID", 123);Intent intent = getIntent();
int userId = intent.getIntExtra("UserID", 0);<?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"> <TextView android:textAppearance="?android:attr/textAppearanceLarge" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/application_header" android:layout_gravity="center"></TextView> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/btnOpenActivity" android:text="@string/button_open_activity"></Button> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/btnOpenActivityForResponse" android:text="@string/button_open_activity_for_response"></Button> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/btnOpenUrl" android:text="@string/button_open_url"></Button> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/btnOpenGeo" android:text="@string/button_open_geo"></Button> <TextView android:text="---" android:id="@+id/tvResult" android:layout_height="wrap_content" android:layout_width="wrap_content"></TextView> </LinearLayout>
<?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"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/second_activity_information"></TextView> </LinearLayout>
<?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"> <EditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/etResponse" android:hint="@string/third_activity_hint"> <requestFocus></requestFocus> </EditText> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnSendResponse" android:layout_gravity="right" android:text="@string/button_send_response"></Button> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">HelloIntents</string>
<string name="application_header">Intent examples</string>
<string name="button_open_activity">Open new Activity</string>
<string name="button_open_activity_for_response">Open Activity for response</string>
<string name="button_open_url">Open URL address</string>
<string name="button_open_geo">Open geo URI address</string>
<string name="second_activity_information">Just click back button.</string>
<string name="third_activity_hint">Type your response here...</string>
<string name="button_send_response">Send back response</string>
</resources>public class MainActivity extends Activity {
private Button btnOpenActivity;
private Button btnOpenActivityForResponse;
private Button btnOpenUrl;
private Button btnOpenGeo;
private TextView tvResult;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnOpenActivity = (Button) findViewById(R.id.btnOpenActivity);
btnOpenActivityForResponse = (Button) findViewById(R.id.btnOpenActivityForResponse);
btnOpenGeo = (Button) findViewById(R.id.btnOpenGeo);
btnOpenUrl = (Button) findViewById(R.id.btnOpenUrl);
tvResult = (TextView) findViewById(R.id.tvResult);
initButtonsOnClickListeners();
}
private void initButtonsOnClickListeners() {
btnOpenActivity.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openSecondActivity();
}
});
btnOpenActivityForResponse.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openActivityForResult();
}
});
btnOpenGeo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openGeoUriAddress();
}
});
btnOpenUrl.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openUrlAddress();
}
});
}
} ...
private void openSecondActivity() {
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(intent);
} ...
private void openActivityForResult() {
Intent intent = new Intent(getApplicationContext(), ThirdActivity.class);
startActivityForResult(intent, THIRD_ACTIVITY_REQUEST_CODE);
}public class MainActivity extends Activity {
private static final int THIRD_ACTIVITY_REQUEST_CODE = 1;
......
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (THIRD_ACTIVITY_REQUEST_CODE == requestCode) {
String response = data.getStringExtra(ThirdActivity.RESPONSE);
insertResponse(response);
}
}public class ThirdActivity extends Activity {
public static final String RESPONSE = "Response";
private EditText etResponse;
private Button btnSendResponse;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.third);
etResponse = (EditText) findViewById(R.id.etResponse);
btnSendResponse = (Button) findViewById(R.id.btnSendResponse);
btnSendResponse.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
prepareResponse();
finish();
}
});
}
private void prepareResponse() {
String response = etResponse.getText().toString();
Intent resultIntent = new Intent();
resultIntent.putExtra(RESPONSE, response);
setResult(RESULT_OK, resultIntent);
}
}...
private void openUrlAddress() {
Uri url = Uri.parse("http://www.google.com");
Intent intent = new Intent(Intent.ACTION_VIEW, url);
startActivity(intent);
}...
private void openGeoUriAddress() {
Uri geoUri = Uri.parse("geo:50.07,19.97");
Intent intent = new Intent(Intent.ACTION_VIEW, geoUri);
if(isIntentAvailable(intent)) {
startActivity(intent);
} else {
Toast.makeText(getApplicationContext(),
"Your system hasn't necessary application for this intent",
Toast.LENGTH_LONG)
.show();
}
}...
private boolean isIntentAvailable(Intent intent) {
PackageManager packageManager = getApplicationContext().getPackageManager();
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return resolveInfo.size() > 0;
}package pl.froger.hellointents;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final int THIRD_ACTIVITY_REQUEST_CODE = 1;
private Button btnOpenActivity;
private Button btnOpenActivityForResponse;
private Button btnOpenUrl;
private Button btnOpenGeo;
private TextView tvResult;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnOpenActivity = (Button) findViewById(R.id.btnOpenActivity);
btnOpenActivityForResponse = (Button) findViewById(R.id.btnOpenActivityForResponse);
btnOpenGeo = (Button) findViewById(R.id.btnOpenGeo);
btnOpenUrl = (Button) findViewById(R.id.btnOpenUrl);
tvResult = (TextView) findViewById(R.id.tvResult);
initButtonsOnClickListeners();
}
private void initButtonsOnClickListeners() {
btnOpenActivity.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openSecondActivity();
}
});
btnOpenActivityForResponse.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openActivityForResult();
}
});
btnOpenGeo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openGeoUriAddress();
}
});
btnOpenUrl.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
openUrlAddress();
}
});
}
private void openSecondActivity() {
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(intent);
}
private void openActivityForResult() {
Intent intent = new Intent(getApplicationContext(), ThirdActivity.class);
startActivityForResult(intent, THIRD_ACTIVITY_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (THIRD_ACTIVITY_REQUEST_CODE == requestCode) {
String response = data.getStringExtra(ThirdActivity.RESPONSE);
insertResponse(response);
}
}
private void insertResponse(String response) {
tvResult.setText(response);
}
private void openUrlAddress() {
Uri url = Uri.parse("http://www.google.com");
Intent intent = new Intent(Intent.ACTION_VIEW, url);
startActivity(intent);
}
private void openGeoUriAddress() {
Uri geoUri = Uri.parse("geo:50.07,19.97");
Intent intent = new Intent(Intent.ACTION_VIEW, geoUri);
if(isIntentAvailable(intent)) {
startActivity(intent);
} else {
Toast.makeText(getApplicationContext(),
"Your system hasn't necessary application for this intent",
Toast.LENGTH_LONG)
.show();
}
}
private boolean isIntentAvailable(Intent intent) {
PackageManager packageManager = getApplicationContext().getPackageManager();
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return resolveInfo.size() > 0;
}
}package pl.froger.hellointents;
import android.app.Activity;
import android.os.Bundle;
public class SecondActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
}
}package pl.froger.hellointents;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class ThirdActivity extends Activity {
public static final String RESPONSE = "Response";
private EditText etResponse;
private Button btnSendResponse;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.third);
etResponse = (EditText) findViewById(R.id.etResponse);
btnSendResponse = (Button) findViewById(R.id.btnSendResponse);
btnSendResponse.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
prepareResponse();
finish();
}
});
}
private void prepareResponse() {
String response = etResponse.getText().toString();
Intent resultIntent = new Intent();
resultIntent.putExtra(RESPONSE, response);
setResult(RESULT_OK, resultIntent);
}
}
1 sierpnia 2011 o 14:35
27 stycznia 2012 o 00:19