Around the World
Ciele
  1. Naučiť sa načítavať obrázky z rôznych zdrojov, prístup k internému a externému úložisku médií na telefóne.
  2. Práca s webservismi - načítanie a odoslanie skóre.
Úvod
V tomto cvičení sa naučíte ako pristupovať v aplikácii k špecifickým typom multimediálnych súborov na zariadení. Hráč si môže zvoliť, či chce náhodný výber obrázka alebo si konkrétny obrázok vyberie sám. Tieto dve voľby sa realizujú na internom alebo externom úložisku zariadenia (SD karta). Taktiež sa oboznámite s možnosťou pripojenia sa a využitia web servisov v aplikácii.
Postup
  1. Tento krok je zameraný na vytvorenie nastavenia, pomocou ktorého hráč zadá spôsob výberu obrázku, ktorý sa rozloží na puzzle.
    Úloha:  Otvorte si projekt HelloAndroid z minulého cvičenia alebo si ho stiahnite a importujte do vývojového prostredia Eclipse.
    Úloha:  Keďže idete vytvárať nové špecifické nastavenie, musíte vytvoriť podtriedu triedy Preference src/tuke.fei.hello/PrefsImage.java a vyberte vytvorenie jednoduchého konštruktora PrefsImage(Context, AttributeSet), z ktorého si ochováte referenciu na kontextový objekt.
    Pre nastavenie zdroja obrázka je nutné v prvom rade vyvolať dialóg ako pri výbere stupňa obtiažnosti na začiatku hry.
    Úloha:  Vytvorte v zdrojovom súbore /res/values/arrays.xml nové pole pre výber zdroja obrázku.
    Úloha:  Implementujte zdedenú metódu onClick() obsluhujúcu výber tohto nastavenia v zozname nastavení tak, aby sa otvoril dialóg typu AlertDialog.
    Tento dialóg má mať svoj názov, obsahovať položky, z ktorých môže byť v čase aktívna iba jedna, potvrdzujúce a zamietajúce tlačidlo. Využijete teda metódy
    • setTitle(int)
    • setSingleChoiceItems(int, int, OnClickListener)
    • setPositiveButton(int, OnClickListener)
    • setNegativeButton(int, OnClickListener)
    Uvažujeme, že prípad, kedy si hráč vyberie náhodný výber obrázka, na pozadí vyberie náhodný obrázok. V prípade, že hráč zvolí výber vlastného obrázku, mal by sa otvoriť prehliadač s cestou k adresáru externého úložiska zariadenia, na ktorom sa nachádzajú uložené obrázky. Pre tento prípad teda bude potrebné vytvoriť triedu implementujúcu OnClickListener, ktorá obslúži výber tejto položky v dialógu, inštancia ktorej bude použitá pri volaní metódy setSingleChoiceItems(). Ďalšou novou triedou implementujúcou OnClickListener bude trieda, ktorá bude reagovať na stlačenie potvrdzujúceho tlačidla dialógu, objekt ktorej bude využitý pri volaní metódy setPositiveButton().
    Úloha:  Založte v triede nastavenia PrefsImage.java privátnu triedu implementujúcu OnClickListener SelectionListener.
    Úloha:  Implementujte metódu onClick(DialogInterface, int), ak hráč zvolí možnosť výberu vlastného obrázku, otvorí sa v prehliadaci galéria obrázkov na SD karte.
                    // otvori prehliadac galerie obrazkov na externom ulozisku - SD karte
                    Intent aBrowserIntent = new Intent(Intent.ACTION_GET_CONTENT);
                    aBrowserIntent.setDataAndType(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
    
                    // vytvorenie moznosti vyberu obrazka
                    Intent aChooser = Intent.createChooser(aBrowserIntent, "Choose Image");
                    // po vybere obrazka obsluhujuca Aktivita Prefs ziska informacie o danom obrazku
                    // druhy parameter oznacuje jedinecny kod definujuci zasielane data
                    ((Activity) myContext).startActivityForResult(aChooser, 123);
            
    Poznámka:  Pre interné úložisko slúži voľba android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI .
    Po výbere obrázka Aktivita obsluhujúca nastavenia obdrží informácie o vybranom obrázku s cieľom poslať tomuto nastaveniu cestu k vybranému obrázku. Ak následne hráč potvrdí túto voľbu potvrdzujúcim tlačidlom, uloží sa obdržaná cesta do nastavení.
    Úloha:  Deklarujte premennú prostredia typu Uri, ktorá bude uchovávať cestu k vybranému obrázku a vytvorte pre ňu jednoduchý verejne prístupný setter.
    Úloha:  Vytvorte verejnú statickú metódu saveImagePreference(Context, Uri), ak zasielaná cesta nebude prázdnym reťazcom, uloží sa medzi nastavenia pomocou editora manažéra nastavení pod jedinečným kľúčom táto cesta ako reťazec.
    Úloha:  Vytvorte verejnú metódu getRandomImage(ContentResolver) s návratovým typom Uri, ktorá bude slúžiť na výber náhodného obrázka z galérie.
              // zoznam s jedinecnymi identifikatormi pre kazdy prvok, projekcia
              String[] projection = new String[] {MediaStore.Images.Media._ID };
              
              // cesta ku galerii            
              //Uri uri = new Random().nextInt(1) == 0 ? Media.EXTERNAL_CONTENT_URI : Media.INTERNAL_CONTENT_URI;
              Uri uri = Media.EXTERNAL_CONTENT_URI;
              
              // kurzor ukazujuci na vsetky obrazky v galerii zoradene podla identifikatora
              Cursor aCursor =  Media.query(theResolver, uri, projection, null, null, MediaStore.Images.ImageColumns._ID);
              if (aCursor == null || aCursor.getCount() = 0) { return null; }
            
              aCursor.moveToPosition(new Random().nextInt(aCursor.getCount()));
              return Uri.withAppendedPath(uri, aCursor.getString(0)); 
            
    Úloha:  Založte v triede nastavenia PrefsImage.java privátnu triedu implementujúcu OnClickListener ConfirmationListene.
    Úloha:  Implementujte metódu onClick(DialogInterface, int), ak hráč zvolí možnosť výberu vlastného obrázku, zavolá sa uloženie nastavenia s cestou k náhodne vybranému obrázku, inak sa uloží do nastavenia cesta k vybranému obrázku, ak táto cesta nie je prázdna.
    Úloha:  V zdrojovom súbore pre nastavenia pridajte nové nastavenie - teda element tuke.fei.hello.PrefsImage s parametrami
              android:defaultValue  // ktora moznost je vybrata (0 alebo 1)
              android:layout="?android:attr/preferenceLayoutChild"
              android:dependency="pref_image" //zavislosti, ci ma byt vobec obrazok zobrazeny   
              android:key="pref_image_source" // jedinecny kluc
              android:title
              android:summary
            
    Poznámka:  Dáta na SD karte môžete prechádzať alebo pridávať pri spustenom AVD v DDMS perspektíve v prostredí Eclipse Window -> Open Perspective -> DDMS -> File Explorer -> mnt -> sdcard
    Úloha:  V Aktivite nastavení Prefs.java implementujte zdedenú metódu pre obsluhu prijatia dát aktivovanú pri výbere obrázku hráčom z galérie. Z obdržaných Intent dát získate cestu k súboru volaním getData() na Intent objekte a na zvolenom nastavení typu PrefsImage identifikovanom kľúčom pomocou volania findPreference(CharSequence) nastavíte danú cestu pomocou volania príslušnej statickej metódy.
    Poznámka:  V tomto prípade môžete ale aj nemusíte brať do úvahy identifikačný kód prichádzajúcich dát (1. parameter)
               @Override
               protected void onActivityResult(int, int, Intent data)
            
  2. Aplikovanie nastavenia zdroja obrázku v hracom poli.
    Úloha:  Vytvorte privátnu metódu setBitmap() volanú po načítaní nastavení, ktorá získa z uložených nastavení cestu k obrázku v podobe reťazca. Ak je daný reťazec prázdny, načíta do premennej pre zobrazovanú bitmapu prednastavený zdrojový obrázok, v opačnom prípade získa požadovanú bitmapu pomocou volania MediaStore.Images.Media.getBitmap(ContentResolver, Uri) , ktorú následne uloží.
    Poznámka:  Objekt typu ContentResolver získate na kontextovom objekte volaním getContentResolver(), Uri z reťazca pomocou volania Uri.parse(String).
  3. Pre širší záber možností Android aplikácií si môžete v tomto kroku vyskúšať pripojenie sa k web servisu a jeho využitie pre výmenu dát z internetu, v tomto prípade to bude odoslanie vlastného najlepšieho a prijatie celosvetovo najlepších skóre.
    Uvažujeme, že pri výbere možnosti odoslania najlepšieho skóre nahratého v rámci zariadenia sa berie do úvahy príznak záznamu skóre o tom, či už dané skóre bolo odoslané. Ďalšou podmienkou odoslania skóre zo zariadenia z hľadiska efektívnosti je výška skóre, skóre bude odoslané iba v prípade, že sa nachádza celosvetovo v prvej stovke najlepších zahraných časov.
    Úloha:  Stiahnite si Aktivitu reprezentujúcu klienta pre bežiaci webservis pre spracovanie skóre WebServiceClient.java a pridajte ju medzi ostatné triedy v projekte.
    Úloha:  Preštudujte si dodaný kód.
    Úloha:  Vytvorte zdrojový návrhový súbor /res/layout/webscore.xml, ktorý bude zobrazovať top 10 svetových skóre, teda bude mať rovnakú štruktúru ako návrhový súbor pre zobrazovanie lokálnych skóre.
    Poznámka:  Princíp napĺňania zoznamu najlepších časov sa nemení, zmenou bude iba funkcia tlačidla, ktorá zabezpečí odoslanie, prípadne neodoslanie najlepšieho lokálneho skóre a obnovenie zoznamu.
    Úloha:  Asociujte návrhový súbor s Aktivitou v mieste vytvárania Aktivity, nastavte obsluhu udalosti stlačenia tlačidla pre odoslanie skóre.
    Úloha:  V metóde LoadData() sa nachádza funkcionalita obdržania dát a ich následné uloženie do poľa reťazcov. Implementujte v tejto metóde načítanie dát do návrhového prvku, v ktorom budú zobrazené, obdobne ako pri zobrazovaní lokálnych skóre.
    Úloha:  Ak načítavanie dát z nejakého dôvodu zlyhalo, implementujte pre tento stav vypísanie odkazu o tejto udalosti na mieste zobrazovaných dát.
    Úloha:  Implementujte metódu getTheBestScore() tak, aby vrátila najlepšie lokálne skóre v podobe objektu typu ScoreItem. Ak dané skóre má príznak o odoslaní rovný 1, teda už raz bolo odoslané, metóda vráti prázdny objekt.
    Úloha:  Implementujte metódu pre odoslanie najlepšieho skóre sendData() tak, aby údaje o hráčovi a jeho skóre uložené v neprázdnom ScoreItem objekte boli pridelené zasielanému objektu typu SoapObject.
    Úloha:  Vytvorte a implementujte verejnú metódu updateFirst() v triede obsluhujúcej lokálnu databázu src/tuke.fei.hello/ScoreDatabase.java , ktorá zmení príznak o odoslaní odoslaného skóre na 1.
    Úloha:  Aplikujte zmenu príznaku o odoslaní v klientovi v metóde sendData() daného záznamu v lokálnej databáze, ak odoslanie prebehlo úspešne.
    Úloha:  Ak odoslanie zlyhalo, implementujte pre tento stav vypísanie odkazu o tejto udalosti na mieste zobrazovaných dát.
    Úloha:  Vytvorte akciu na stlačenie tlačidla pre odoslanie dát v metóde onClick(View).
    Úloha:  Vytvorte v hlavnom menu tlačidlo pre možnosť zobrazenia najlepších nahraných svetových skóre a aplikujte všetky potrebné akcie s tým súvisiace.
    Aby sa aplikácia mohla pripájať na webservis, potrebuje mať povolenie pre prístup k internetu.
    Úloha:  Povolenie pre prístup aplikácie k internetu zadajte v manifeste aplikácie (AndroidManifest.xml) použitím elementu uses-permission s atribútom
               android:name="android.permission.INTERNET"
            
    Poznámka:  Nezabúdajte, že manifest aplikácie musí obsahovať referenciu na každú Aktivitu, ktorá je v aplikácii použitá.
Doplňujúce úlohy