Az Android alkalmazások fejlesztésében a widgetek egyedi eszközként szolgálnak a felhasználói élmény fokozására. A widgetek lehetővé teszik a felhasználók számára, hogy közvetlen hozzáférést nyerjenek az alkalmazás funkcióihoz anélkül, hogy meg kellene nyitniuk az alkalmazást. Ebben a fejezetben bemutatjuk, hogyan hozhatunk létre egy alapvető widgetet, amelyet a felhasználó a kezdőképernyőre helyezhet, és hogyan konfigurálhatunk különböző beállításokat annak érdekében, hogy a widget a kívánt módon működjön.

Az első lépés a widget elrendezésének létrehozása, amely egy egyszerű XML fájl formájában történik. A widgetek esetében fontos, hogy a layoutot Remote View-ként kezeljük, mivel a widgetek nem rendelkeznek teljes körű Android felhasználói felülettel. Ez korlátozza a felhasználható komponensek körét, és a widgetek viselkedését egyszerűsíti. Az Android rendszerében a widgetek elrendezése a RemoteViews osztály használatával történik, amely a widget layoutját jelenti, és biztosítja annak megjelenítését.

Az XML erőforrás könyvtár szolgál az AppWidgetProviderInfo fájl tárolására, amely az alapértelmezett widget beállításokat határozza meg. A konfigurációs beállítások azokat az alapvető paramétereket tartalmazzák, amelyek meghatározzák, hogyan jelenjen meg a widget, mikor az elérhető widgetek között böngészünk. Ebben a példában egyszerű beállításokat használunk, de ezek könnyedén bővíthetők, például előnézeti képekkel, amelyek bemutatják a widget működését, illetve méretezési opciókkal.

A updatePeriodMillis attribútum a frissítési gyakoriságot határozza meg. Mivel a widgetek frissítése felébreszti az eszközt, így itt kompromisszumot kell kötni a friss adatok és az akkumulátor élettartama között. A felhasználó számára lehetőség van ezen beállítás módosítására egy opcionális beállító tevékenységen (Settings Activity) keresztül. Az AppWidgetProvider osztályban kezeljük az onUpdate() eseményt, amelyet az updatePeriodMillis pollingja vált ki. A példánkban nem szükséges frissítés, ezért az polling értékét nullára állítjuk. Az onUpdate() metódus az események kezelésére szolgál, például amikor a widgeten található analóg óra rákattintásakor megnyitjuk az alkalmazást.

Az onUpdate() metódus az egyik legbonyolultabb része a widgetek kezelésének. Fontos megjegyezni, hogy az onUpdate() metódus csak egy alkalommal fut le minden egyes polling intervallum alatt, amikor az összes widgetet létrehoztuk. Emiatt használjuk a for ciklust, hogy végigiteráljunk az összes létező widgeten. Itt hozzuk létre azt a pending intentet, amely lehetővé teszi, hogy megnyissuk az alkalmazásunkat, amikor a felhasználó rákattint a widgetre. Az App Widgetek Remote View-ként működnek, tehát a layoutot a RemoteViews() metódussal kérjük le, amelyhez az alkalmazásunk csomagneve és a layout ID-ja szükséges. Miután megszereztük a layoutot, hozzáadhatjuk a pending intentet az óra nézetéhez a setOnClickPendingIntent() segítségével. Végül az AppWidgetManager-t hívjuk meg a updateAppWidget() metódussal, hogy alkalmazzuk a módosításokat.

A következő lépés a widget deklarálása az Android Manifestben. Itt meg kell határoznunk a kezelt eseményt, amely a legtöbb widget esetében az "Update" esemény lesz. A deklarációban szereplő egyéb fontos elem a widget konfigurációs fájl helye, amely az alkalmazásunk konfigurációját tartalmazza.

A widgetek rugalmasabbá tétele érdekében hozzáadhatunk egy konfiguráló tevékenységet, amely lehetőséget ad arra, hogy a felhasználók testre szabják widgetjük működését, például megváltoztathassák a frissítési gyakoriságot, a megjelenítést vagy a kattintási viselkedést. A konfigurációs tevékenységhez néhány további lépést kell követnünk. Először is deklarálni kell az Activity-t a Manifestben, és meg kell adni a APPWIDGET_CONFIGURE műveletet. A configure attribútumot is meg kell adni az AppWidgetProviderInfo fájlban, hogy az Android tudja, hol találja a konfiguráló Activity-t.

Fontos kiemelni, hogy a konfigurációs Activity nem fogja meghívni az onUpdate() metódust. Az Activity felelős minden szükséges kezdeti beállításért, ha azok szükségesek.

Az Android widgetek fejlesztése egy olyan eszközt ad a kezünkbe, amely rendkívül hasznos lehet a felhasználói élmény javításában, különösen akkor, ha a felhasználó számára testre szabható beállításokat biztosítunk. A jól megtervezett widgetek növelhetik az alkalmazásunk használhatóságát, és segíthetnek abban, hogy az alkalmazásunk folyamatosan elérhető maradjon anélkül, hogy a felhasználónak külön nyitnia kellene azt.

Hogyan készítsünk értesítéseket és figyelmeztetéseket Android alkalmazásokban?

Az értesítések és figyelmeztetések alapvető szerepet játszanak abban, hogy az Android alkalmazások interaktívabbak és hasznosabbak legyenek a felhasználók számára. Az Android operációs rendszer különféle lehetőségeket kínál az értesítések testreszabására, lehetővé téve, hogy különböző vizuális, hang- és vibráló hatásokat alkalmazzunk, vagy akár gombokat adjunk hozzá az értesítésekhez. Az alábbiakban bemutatjuk, hogyan hozhatunk létre értesítéseket, miként tehetjük azokat gazdagabbá, és hogyan reagálhatunk a felhasználó interakcióira.

Első lépésként, ha értesítést szeretnénk küldeni, fontos, hogy figyeljünk a minimálisan szükséges elemekre: a kis ikont és a szöveget. Ezek nélkül az értesítés nem fog megjelenni. A kód a következőképpen nézhet ki, ha egy egyszerű értesítést szeretnénk létrehozni:

java
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("LightsActionSoundRedux") .setContentText("Lights, Action & Sound"); NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notificationBuilder.build());

Fontos megjegyezni, hogy a NotificationCompat használata szükséges, mert ez a támogatói könyvtár biztosítja, hogy az értesítések kompatibilisek maradjanak az Android régebbi verzióival is. Ez a kompatibilitás elengedhetetlen ahhoz, hogy a felhasználók zökkenőmentesen használhassák az alkalmazást, függetlenül attól, hogy milyen verziójú operációs rendszert futtatnak.

Az értesítésekhez további funkciók is hozzáadhatók. Például a hang, fény és vibrálás mind elérhetők a NotificationCompat segítségével. Az alábbi kódrészlet bemutatja, hogyan adhatunk hangot, fényt és vibrálást az értesítéshez:

java
Uri notificationSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("LightsActionSoundRedux") .setContentText("Lights, Action & Sound") .setSound(notificationSoundUri) .setLights(Color.BLUE, 500, 500) .setVibrate(new long[]{250, 500, 250, 500, 250, 500});
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(
0, notificationBuilder.build());

Itt a .setSound() a beállított értesítési hangot használja, a .setLights() a képernyő fényét szabályozza, míg a .setVibrate() lehetővé teszi a vibrálási minta testreszabását. A vibrálás mintája úgy működik, hogy az első érték az "off" időt jelöli, a második érték pedig a vibráló időt, és így tovább.

Az értesítéseken belüli további testreszabási lehetőségek közé tartozik a gombok hozzáadása. Az Android lehetőséget ad arra, hogy az értesítésekhez három gombot is hozzáadjunk. Az addAction() metódus segítségével ezeket a gombokat hozhatjuk létre. Íme egy egyszerű példa arra, hogyan adhatunk hozzá egy gombot, amely egy e-mail küldését indítja el:

java
Intent activityIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, 0); notificationBuilder.addAction(android.R.drawable.ic_dialog_email, "Email", pendingIntent); notificationManager.notify(0, notificationBuilder.build());

Ez a kódrészlet egy gombot hoz létre, amely egy e-mail küldésére indítja el a felhasználót. Az addAction() három paramétert igényel: az első a gomb ikonját, a második a gomb szövegét, a harmadik pedig egy PendingIntent, amely az esemény végrehajtásáért felelős.

Az Android 4.1-es verziójával bevezetett "bővített értesítések" funkció lehetővé teszi, hogy az értesítések gazdagabbak legyenek. A setStyle() metódus használatával az értesítések három stílust támogathatnak: InboxStyle, BigPictureStyle és BigTextStyle. Minden stílus különböző típusú vizuális tartalmat biztosít, amely a felhasználó számára könnyebben áttekinthetővé teszi az értesítéseket.

Példa a BigTextStyle stílusra:

java
NotificationCompat.Builder notificationBuilderBigTextStyle = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("LightsActionSoundRedux"); NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); bigTextStyle.bigText("Ez egy példa a BigTextStyle bővített értesítésre."); notificationBuilderBigTextStyle.setStyle(bigTextStyle); notificationManager.notify(0, notificationBuilderBigTextStyle.build());

Ez a stílus hosszabb szövegek megjelenítésére használható, amelyet a felhasználók részletesebben olvashatnak el.

A zárolt képernyőn való értesítések megjelenítése Android 5.0 (API 21) és újabb verziókon elérhető. Az setVisibility() metódus használatával szabályozhatjuk, hogy milyen típusú információk jelenjenek meg a zárolt képernyőn:

  • VISIBILITY_PUBLIC: Minden tartalom látható.

  • VISIBILITY_PRIVATE: Csak az alapvető információk (cím és ikon) jelennek meg.

  • VISIBILITY_SECRET: Semmilyen tartalom nem látható.

Ez az opció biztosítja, hogy a felhasználó biztonságban érezze magát, miközben értesítéseket kap, mivel a bizalmas információk nem kerülnek felfedésre, amikor a képernyő zárolva van.

Fontos, hogy az értesítések kezelése mindig összhangban legyen az alkalmazás funkcionális tervezésével. Az értesítések nem csupán információk közvetítésére szolgálnak, hanem a felhasználói élmény javítására is. A megfelelő tervezés segíthet abban, hogy az alkalmazás hatékonyan kommunikáljon a felhasználókkal, miközben fenntartja a navigációs élményt és biztosítja a szükséges interakciókat. A gombok és a bővített értesítések különösen hasznosak lehetnek, ha az alkalmazás különböző műveleteket szeretne végrehajtani anélkül, hogy teljes képernyős interakciót igényelne.

Hogyan kezeljük a hangokat Android alkalmazásokban?

A hangok kezelésének megértése az Android fejlesztésében fontos szerepet játszik, különösen akkor, ha multimédiás alkalmazásokat kívánunk készíteni. Az Android különböző hangkezelési eszközöket kínál, mint például a SoundPool és a MediaPlayer, amelyek mindkettő hasznos lehetőségeket biztosítanak, de más-más esetekben és környezetben alkalmazandók. Az alábbiakban a két módszer alkalmazását és azok működését vizsgáljuk meg, hogy jobban megértsük, mikor melyiket érdemes használni.

SoundPool és annak alkalmazása

A SoundPool egy olyan osztály, amely lehetővé teszi több hang egyidejű lejátszását, és különösen akkor hasznos, ha rövid hangokat szeretnénk lejátszani, például gombnyomások, értesítések vagy játékok során. Az Android Lollipop (API 21) verziótól kezdődően jelentős változás történt a SoundPool konstruktorában: a régi konstruktor elavult, és helyette a SoundPool.Builder használata ajánlott.

A SoundPool osztály létrehozása és konfigurálása az alábbi módon történik:

  1. A SoundPool inicializálása: A kódunk elején létre kell hoznunk a SoundPool objektumot. Ezt megtehetjük egy új, az Android Lollipop verziójára vonatkozó függvény használatával, amely figyelembe veszi a verziókat. Az alábbiakban látható, hogyan érhetjük el, hogy a különböző Android verziók esetén más-más metódust hívjunk meg a SoundPool létrehozásához:

    java
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { createSoundPoolNew(); } else { createSoundPoolOld(); }
  2. A hangok betöltése: Miután inicializáltuk a SoundPool-t, következő lépésként be kell töltenünk a hangokat. Ehhez a load() metódust használhatjuk, amely egyedi hangazonosítót rendel a hangfájlokhoz. Az alábbi kód a hangok betöltését mutatja be:

    java
    mHashMap.put(1, mSoundPool.load(this, R.raw.sound_1, 1)); mHashMap.put(2, mSoundPool.load(this, R.raw.sound_2, 1));
  3. Hang lejátszása: Miután betöltöttük a hangokat, a play() metódussal lejátszhatjuk azokat. A lejátszáshoz különböző paramétereket adhatunk meg, például a hangerőt, a lejátszás sebességét és a hurok számát. Ezen kívül figyelnünk kell arra, hogy a hangok lejátszása előtt biztosítani kell, hogy azok teljesen betöltődtek. Az alábbi kódrészlet mutatja be a lejátszást:

    java
    public void playSound1(View view){
    mSoundPool.play(mHashMap.get(1), 0.1f, 0.1f, 1, 0, 1.0f);
    }
    public void playSound2(View view){ mSoundPool.play(mHashMap.get(2), 0.9f, 0.9f, 1, 1, 1.0f); }
  4. A hangok törlése: Az alkalmazás életciklusa során, ha már nincs szükség a hangok lejátszására, fontos, hogy megfelelően felszabadítsuk a használt erőforrásokat. Ezt az onStop() callback metódusban tehetjük meg, ahol a SoundPool objektumot le kell zárni:

    java
    @Override protected void onStop() { super.onStop(); mSoundPool.release(); }

A SoundPool tehát ideális választás rövid hangok lejátszására, például interakciók, értesítések vagy játékhangeffektusok esetén.

MediaPlayer és annak alkalmazása

A MediaPlayer osztály egy sokkal komplexebb eszköz, amely lehetővé teszi hosszú audió fájlok lejátszását. A MediaPlayer különösen hasznos akkor, ha folyamatos hangokat kell lejátszanunk, például háttérzenét, hangos könyveket vagy más médiát.

A MediaPlayer osztály segítségével könnyen lejátszhatunk különböző típusú audió fájlokat, beleértve az MP3, WAV, FLAC és más formátumokat. Az alábbiakban bemutatjuk, hogyan állíthatjuk be a MediaPlayer-t az alkalmazásunkban:

  1. A MediaPlayer inicializálása: A MediaPlayer létrehozása egyszerű, és a következő módon történik:

    java
    mMediaPlayer = MediaPlayer.create(this, R.raw.sound_1);
  2. A hang lejátszása, szüneteltetése és leállítása: A MediaPlayer osztály kínálja a lejátszás, szüneteltetés és leállítás lehetőségeit is, és ezek mindegyike egyszerű metódusokkal érhető el:

    java
    public void buttonPlay(View view){
    if (mMediaPlayer == null) { mMediaPlayer = MediaPlayer.create(this, R.raw.sound_1); mMediaPlayer.setLooping(true); // Ha ismétlődő lejátszást szeretnénk mMediaPlayer.start(); } else { mMediaPlayer.start(); } } public void buttonPause(View view){ if (mMediaPlayer != null && mMediaPlayer.isPlaying()) { mMediaPlayer.pause(); } } public void buttonStop(View view){ if (mMediaPlayer != null) { mMediaPlayer.stop(); mMediaPlayer.release(); mMediaPlayer = null; } }
  3. A MediaPlayer erőforrások felszabadítása: Hasonlóan a SoundPool-hoz, a MediaPlayer esetén is szükséges, hogy az alkalmazás bezárásakor felszabadítsuk az erőforrásokat. Ehhez az onStop() metódusban kell végrehajtanunk a következő kódot:

    java
    @Override
    protected void onStop() { super.onStop(); if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; } }

A MediaPlayer osztály tehát ideális akkor, ha hosszú hangfájlokat szeretnénk lejátszani, vagy ha a felhasználói interakciók mellett folyamatos média lejátszásra van szükség.

Különböző típusú hangok kezelése

Fontos megjegyezni, hogy a különböző típusú hangok (például rövid hangok és hosszú háttérzene) más-más eszközöket igényelnek. A SoundPool ideális a rövid hangok, effektek lejátszásához, míg a MediaPlayer a hosszú hangok, mint például a zenék és hangoskönyvek kezelésére alkalmas. Mindkét eszköznél figyelni kell az erőforrások kezelésére, hogy az alkalmazás ne fogyasszon túl sok memóriát, és az erőforrásokat megfelelően felszabadítsuk a megfelelő pillanatokban.