Hlavní navigace

Programování pro Android v příkladech

10. 3. 2011
Doba čtení: 5 minut

Sdílet

Tutoriálů a různých příkladů věnujících se programování pro Android je na webu velké množství. Proč tedy vlastně psát další? Android prochází rychlým rozvojem a co platilo včera, již nemusí platit dnes. Článek vybírá několik častých programátorských oříšků a jejich řešení v Androidu 2.0 a vyšším.

Disclaimer

Uvedené příklady fungují na Android 2.0 a vyšších a jsou založeny na zkušenostech získaných při vytváření reálných aplikací pro Android. Ukázky jsou zaměřeny primárně na Contacts API, nicméně principy by měly být univerzální.

A ještě jedna věc. Pokud se v Androidu moc nevyznáte, přečtěte si nejdřív články Pavla Petřeka.

Získání kontaktu

Začneme malou rozcvičkou. Řekněme, že chceme nechat uživatele vybrat kontakt z telefonního seznamu a s tímto kontaktem dále pracovat.

Filosofie Androidu tento úkol značně zjednodušuje, protože samotný výběr není nutné vyvíjet – lze ho nechat na ostatních aplikacích. Než si ale ukážeme jak, bude dobré si pár slovy zmíněnou filozofii přiblížit.

Activity a Intenty

Typická aplikace pro Android (stejně jako aplikace pro jiné OS) se skládá z několika obrazovek. V terminologii Androidu se obrazovkám říká Activity. Nic nového pod sluncem.

Teď ovšem přijde to zajímavé – ve správné aplikaci jsou jednotlivé Activity navrhované tak, aby fungovaly zcela samostatně. Například tím, že mají jasně definované vstupy a výstupy. Takže ve své aplikaci můžete zavolat Activity z jiné aplikace a uživatel to v podstatě nepozná.

Analogicky je možné zaregistrovat libovolnou Activity, kterou pak mohou používat ostatní aplikace v telefonu. Mimochodem, zajímavý seznam volně dostupných aktivit je na OpenIntents.

Řekli jsme, že správně navržená Activity musí mít definované vstupy a výstupy. K tomu jsou v Androidu tzv. Intents. Intent je zkratka slova intetion, tedy úmysl. Použitím Intent u tedy systému sděluji, co mám v úmyslu, a nechávám na něm, jak můj úmysl splní.

Android postupuje tak, že vyhledá všechny Activity, které mohou daný Intent splnit, a pokud je jich více, dá uživateli vybrat. Příslušná Activity je poté nastartována a je jí předán konkrétní Intent jako vstup.

Rada nad zlato: než se vrhnete do programování, zjistěte, jestli si nemůžete ušetřit práci použitím existující aktivity. Kromě volného času tím získáte i spokojenějšího uživatele, který nebude zmaten novým vzhledem známé funkce.

Získání kontaktu II

Jsme zpět u rozcvičky. Takže jak se vyhledává kontakt v telefonu plném aktivit a intentů? Jednoduše:

  private static final int ACTIVITY_PICK_CONTACT = 42;

    private void pickContact() {
      Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
      startActivityForResult(intent, ACTIVITY_PICK_CONTACT);
    }

V prvním řádku metody pickContact() říkáme, že máme v úmyslu vybrat ( ACTION_PICK) konkrétní kontakt ( Contacts.CONTENT_URI) z telefonního seznamu. Druhým žádáme operační systém, aby našel a spustil příslušnou aktivitu. ACTIVITY_PICK_CONTACT je víceméně libovolná konstanta, kterou budeme potřebovat, až se bude vracet řízení zpět.

Nyní tedy Android nastartuje standardní telefonní seznam a nechá uživatele vybrat jeden kontakt. Po kliknutí na kontakt zavolá systém opět naší aktivitu, konkrétně callback metodu onActivityResult(). Pro tu si musíme připravit implementaci. Tady je:

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
       switch (requestCode) {
          case (ACTIVITY_PICK_CONTACT) :
              if (resultCode == Activity.RESULT_OK) {
                  //hotovo, máme kontakt
                  Uri pickedContact = data.getData();
                  return;
              }
          break;
      }
  }

Jak je vidět, zde je použita konstanta ACTIVITY_PICK_CONTACT. Vybraný kontakt se předává opět jako Intent, konkrétně jako jeho property data. V případě, že je potřeba předat něco jiného než Uri, použijeme metodu getExtras(), která dovolí předat libovolný objekt.

Uri

Než se pustíme do dalšího příkladu, možná by stálo za to, vysvětlit si pojem Uri. Nemám na mysli ani tak samotný pojem URI, ten asi čtenáři Roota znají dobře, ale jeho použití v Androidu. Nechci zde duplikovat vývojářskou příručku, takže jen krátce.

Obsah (tedy kontakty, SMSky, fotky, …) Android telefonu je v zásadě dostupný všem aplikacím bez rozdílu. O přístup k jednotlivým položkám se starají tzv. Content Providers. Content Providers zapouzdřují práci s obsahem – vyhledávání, editaci, mazání apod. Uri vyjadřuje za prvé typ obsahu a za druhé může, ale nemusí ukazovat i na konkrétní záznam.

Takže například jeden určitý kontakt bude mít takovéto  Uri:

content://com.android.contacts/contacts/666

Vytvoření dialogu

Dost bylo odboček, pojďme se podívat, jaký kontakt si uživatel vybral. Pro začátek zkusíme zobrazit Uri kontaktu v dialogu. Nějak takhle:

Zobrazení alertu nemůže přece být nic složitého? A opravdu není:

  new AlertDialog.Builder(this).
    setTitle("URI kontaktu").
    setMessage(pickedContact.toString()).
    setCancelable(true).
    setPositiveButton("OK", null).
    create().
    show();

Jediná „drobnost“ – takto vytvořený alert při otočení telefonu a změně orientace displeje spadne a vezme s sebou celou aplikaci (zkuste si to).

Tak na to správně po androidsku? Je nutné předefinovat metody onCreateDialog()onPrepareDialog():

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case DIALOG_SHOW_CONTACT: {
                return new AlertDialog.Builder(this).
                        setTitle("URI kontaktu").
                        setCancelable(true).
                        setPositiveButton("OK", null).
                        create();
            }
        }
        return null;
    }

    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        switch (id) {
            case DIALOG_SHOW_CONTACT: {
                ((AlertDialog)dialog).setMessage(pickedContact.toString());
            }
        }

První z metod volá systém při vytváření dialogu, což znamená, že se zavolá pouze jedenkrát. Dále už je „recyklován“ vytvořený dialog opakovaným voláním druhé metody, čehož využijeme k nastavení správného textu k zobrazení. Všimněte si, že jsme museli definovat další konstantu, podle které rozlišujeme, jaký dialog se bude vytvářet. Samotné zobrazení pak zajistíme voláním:

   showDialog(DIALOG_SHOW_CONTACT);

Jistě vám neušlo, že v metodě showDialog() není možné předat konkrétní data k zobrazení. To se většinou řeší nastavením proměnné třídy, kterou si poté metoda onPrepareDialog() přečte. A poslední zrada – tato proměnná musí být statická, aby přežila znovuvytvoření aktivity a dialogu při změně orientace displeje.

Naštěstí se blýská na lepší časy. Od verze 2.2 je možné přidat do volání showDialog() objekt typu Bundle, takže vytváření dialogů bude o něco jednodušší.

Cloud 24 - tip 1

Co bude příště?

V příštím článku si zkusíme vytáhnout základní údaje kontaktu – telefonní číslo, e-mail, fotku. A pak se je naučíme změnit.

Celý zdrojový kód příkladu je k dispozici na Githubu.

Byl pro vás článek přínosný?

Autor článku

Lukáš Marek pracuje jako Software Architect a věnuje se vývoji pro Android.