Dialogová okna a notifikace jsou základními nástroji pro interakci s uživatelem v mobilních aplikacích. Android nabízí různé možnosti pro zobrazování informací a zajištění uživatelské zpětné vazby. Mezi nejběžnější komponenty patří třídy jako AlertDialog pro potvrzení akcí a ProgressDialog pro zobrazení indikátoru průběhu úkolu. Tyto komponenty jsou důležitým nástrojem pro zlepšení uživatelského zážitku a interaktivity aplikace. Následující text vysvětluje, jak správně využívat tyto nástroje v Androidu a jak s nimi pracovat.

Nejprve se zaměříme na AlertDialog. Tento typ dialogu se často používá pro potvrzení uživatelských akcí, jako je smazání položky. Jeho implementace je poměrně jednoduchá a vyžaduje pouze pár základních kroků. Vytvoření instance AlertDialog.Builder umožňuje nastavit různé vlastnosti dialogu, jako je titul, zpráva a tlačítka pro potvrzení nebo zrušení akce. V tomto případě se používají metody setPositiveButton() pro potvrzení a setNegativeButton() pro zrušení akce. Obě tlačítka spustí příslušné akce po stisknutí, například zobrazení krátké zprávy pomocí Toast.

Další možností, jak vylepšit vzhled dialogu, je přidání ikony. Tato ikona se přidává metodou setIcon() a může například obsahovat ikonu aplikace. Dále je možné pracovat s výběrovými seznamy, které umožňují uživateli vybrat položku z nabídky. Seznam může být jednoduchý, s jedním výběrem, nebo více možnostmi pro označení více položek. Při použití seznamu se však zpráva, nastavená metodou setMessage(), přestane zobrazovat, protože tato metoda má vyšší prioritu.

Pokud bychom chtěli do dialogu přidat vlastní rozvržení, lze využít metodu setView(), která umožňuje vložit vlastní komponenty do dialogového okna. Když nahradíme standardní tlačítka, musíme se postarat i o uzavření dialogu, což lze provést metodami jako hide() nebo dismiss().

Kromě AlertDialog je dalším běžně používaným nástrojem ProgressDialog, který zobrazuje průběh nějakého procesu, například čekání na odpověď ze serveru. Tato třída byla dlouho součástí Androidu, ale vývojáři ji dnes doporučují spíše vyhnout se jejímu používání, pokud to není nutné. Důvodem je to, že uživatel nemůže s aplikací interagovat, dokud je dialog zobrazen. Místo toho se doporučuje použít progress bar přímo v rozhraní aplikace, což umožňuje uživateli pokračovat v interakci s aplikací i během čekání. V případě, že však používáme ProgressDialog, je důležité nastavit, zda je dialog zrušitelný nebo ne, což se dělá metodou setCancelable(false).

Pokud chceme vytvořit vlastní indikátor pokroku, můžeme použít metodu setProgressStyle(), která umožňuje nastavit, zda bude indikátor pokračovat v neustálém pohybu, nebo zda bude ukazovat konkrétní hodnotu pomocí horizontálního progress baru.

Pokud jde o notifikace, ty jsou v Androidu velmi rozšířeným způsobem, jak informovat uživatele o důležitých událostech. Notifikace mohou zahrnovat různé způsoby upozornění, jako jsou světelné efekty, vibrace nebo zvuk. Je důležité si uvědomit, že notifikace by neměly být příliš rušivé, protože mohou uživatele odradit od používání aplikace. Proto by měla být možnost nastavit, jakým způsobem a zda vůbec budou notifikace zobrazovány, například s nebo bez zvuku.

Pro využívání vibrace je nutné získat příslušné oprávnění v Android Manifestu. Notifikace je pak možné přizpůsobit a řídit pomocí Notification.Builder, kde se definují různé atributy, jako je obsah, ikona nebo zvuk. Je také možné nastavit prioritu notifikace, aby byla zajištěna její správná viditelnost.

Při používání těchto nástrojů by měli vývojáři dbát na to, aby nedošlo k jejich nadměrnému využívání. Příliš mnoho rušivých notifikací může vést k negativnímu uživatelskému zážitku a odinstalaci aplikace. Na druhou stranu, správně implementované dialogy a notifikace mohou výrazně zlepšit interakci s uživatelem a zajistit, že aplikace bude pro uživatele intuitivní a efektivní.

Je důležité, aby vývojáři dbali na optimalizaci uživatelského rozhraní, přičemž by měli brát v úvahu různé scénáře, kdy je použití dialogu či notifikace vhodné, a kdy by mohl být uživatelský zážitek negativně ovlivněn. Dialogová okna by měla být použita pouze v nezbytných případech, například pro potvrzení důležitých akcí, a měla by se vždy zaměřovat na jasné a stručné vyjádření informace, kterou mají uživateli předat.

Jak vytvořit upozornění pro přehrávač médií v Androidu a používat Heads-Up Notifikace

V systému Android 5.0 (API 21) byla představena nová možnost notifikací, která umožňuje zobrazovat upozornění s multimediálním obsahem přímo na zamykací obrazovce. Tento typ notifikace je běžně využíván v přehrávačích médií a jiných aplikacích, které vyžadují interakci s uživatelem bez nutnosti přepnutí do samotné aplikace. V této kapitole si ukážeme, jak vytvořit základní notifikaci pro přehrávač médií a jak ji přizpůsobit pro různé verze Androidu, s důrazem na kompatibilitu s API 21 a novějšími verzemi.

Pro tento účel si vytvoříme nový projekt v Android Studiu s názvem MediaPlayerNotification, kde použijeme jednoduchý tlačítko, které aktivuje naši notifikaci. Tato notifikace bude mít základní funkce přehrávače médií, jako je ovládání přehrávání, pozastavení a přeskakování skladeb.

Příprava projektu

  1. Vytvoření nového projektu
    Otevřete Android Studio a vytvořte nový projekt s názvem MediaPlayerNotification. Při volbě API úrovně vyberte API 21 (Lollipop) nebo vyšší, protože právě tato verze systému Android umožňuje práci s pokročilými notifikacemi.

  2. Úprava layoutu
    V souboru activity_main.xml přidejte jednoduché tlačítko pro aktivaci notifikace. Může to vypadat například takto:

    xml
    <Button
    android:id="@+id/showNotificationButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Show Notification" android:onClick="showNotification"/>

Implementace kódu pro notifikaci

V souboru MainActivity.java vytvoříme metodu showNotification(), která se postará o vytvoření a zobrazení notifikace.

  1. Přidání metody pro zobrazení notifikace

    Vytvořte metodu showNotification() následujícím způsobem:

    java
    @Deprecated public void showNotification(View view) {
    Intent activityIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, 0); Notification notification; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { notification = new Notification.Builder(this) .setVisibility(Notification.VISIBILITY_PUBLIC) .setSmallIcon(Icon.createWithResource(this, R.mipmap.ic_launcher)) .addAction(new Notification.Action.Builder( Icon.createWithResource(this, android.R.drawable.ic_media_previous), "Previous", pendingIntent).build()) .addAction(new Notification.Action.Builder( Icon.createWithResource(this, android.R.drawable.ic_media_pause), "Pause", pendingIntent).build()) .addAction(new Notification.Action.Builder( Icon.createWithResource(this, android.R.drawable.ic_media_next), "Next", pendingIntent).build()) .setContentTitle("Music") .setContentText("Now playing...") .setLargeIcon(Icon.createWithResource(this, R.mipmap.ic_launcher)) .setStyle(new Notification.MediaStyle().setShowActionsInCompactView(1)) .build(); } else { notification = new Notification.Builder(this) .setVisibility(Notification.VISIBILITY_PUBLIC) .setSmallIcon(R.mipmap.ic_launcher) .addAction(new Notification.Action.Builder( android.R.drawable.ic_media_previous, "Previous", pendingIntent).build()) .addAction(new Notification.Action.Builder( android.R.drawable.ic_media_pause, "Pause", pendingIntent).build()) .addAction(new Notification.Action.Builder( android.R.drawable.ic_media_next, "Next", pendingIntent).build()) .setContentTitle("Music") .setContentText("Now playing...") .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setStyle(new Notification.MediaStyle().setShowActionsInCompactView(1)) .build(); } NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notification); }

Tato metoda vytvoří notifikaci s možnostmi pro ovládání přehrávače médií: „Předchozí“, „Pozastavit“ a „Další“. Notifikace bude obsahovat také titul a text, který informuje uživatele, že se právě přehrává hudba.

Kompatibilita s verzemi systému Android

Zajímavým aspektem tohoto kódu je použití kontroly verze systému Android, která zajistí kompatibilitu mezi různými verzemi Androidu. Notifikace byla poprvé uvedena v API 21 a od té doby byly provedeny různé změny v API, zejména co se týče ikon a stylů.

  1. Kontrola verze systému
    Při implementaci notifikace zkontrolujeme, zda je zařízení vybaveno verzí systému Android 6.0 (API 23) nebo vyšší. Pokud ano, použijeme novou třídu Icon pro vytváření ikon. V opačném případě využijeme starší metody.

  2. Zobrazení na zamykací obrazovce
    Pro to, aby byla notifikace viditelná na zamykací obrazovce, nastavujeme viditelnost na VISIBILITY_PUBLIC, což umožňuje, aby byla notifikace zobrazená i když je zařízení zamknuto.

  3. Skrýt akce v kompaktním zobrazení
    Příkaz .setShowActionsInCompactView(1) slouží k tomu, aby akce jako „Pozastavit“, „Předchozí“ a „Další“ byly zobrazeny i v kompaktním zobrazení, což je důležité pro zajištění přehlednosti na zamykací obrazovce.

Další vylepšení a možnosti

Pokud bychom vytvářeli skutečný přehrávač médií, můžeme použít třídu MediaSession, která by umožnila systému rozpoznat mediální obsah a reagovat na něj. To by zahrnovalo například aktualizaci obrázku alba na zamykací obrazovce nebo změnu notifikace na základě aktuální skladby.

Pokud budete chtít přidat pokročilejší funkce, můžete například implementovat obsluhu přehrávání hudby prostřednictvím MediaPlayer, přidat změnu metadat o skladbě, nebo integrovat funkcionalitu pro ovládání přehrávání z notifikace na zamykací obrazovce.

Další důležitou věcí je věnovat pozornost uživatelskému zážitku při práci s Heads-Up Notification, která je novinkou v Android 5.0 a může být v některých případech velmi rušivá. Při jejím použití je důležité mít na paměti, že by měla být využívána v situacích, kdy je uživatelova pozornost nezbytně nutná, například při upozornění na důležité události nebo akce.

Jak vytvořit kompas pomocí dat z čidel a animace rotace v Androidu

V předchozí kapitole jsme ukázali, jak číst data z fyzických čidel zařízení. V tomto případě jsme použili světelný senzor, protože data z environmentálních senzorů obvykle nevyžadují žádné další zpracování. Ačkoli je snadné získat data o magnetickém poli, samotná čísla nemají příliš velký význam a rozhodně netvoří vizuálně atraktivní zobrazení. V této kapitole ukážeme, jak získat data o magnetickém poli spolu s daty z akcelerometru a vypočítat tak magnetický sever. K tomu využijeme metodu SensorManager.getRotationMatrix k animaci kompasu při pohybu zařízení.

Než začneme upravovat rozložení prostřednictvím kódu, zavoláme metodu beginDelayedTransition() třídy TransitionManager s typem přechodu. Tato třída bude sledovat změny pro koncovou scénu. Jakmile zavoláme metodu go(), TransitionManager automaticky animuje změnu.

Před tím, než se pustíme do samotného kódu, je nutné vytvořit nový projekt v Android Studiu a pojmenovat jej "Compass". Vyberte výchozí možnosti pro telefony a tablety a při výběru typu aktivity zvolte prázdnou aktivitu.

Pro zobrazení kompasu budeme potřebovat obrázek indikátoru kompasu. Tento obrázek lze stáhnout z webu Pixabay (https://pixabay.com/en/geography-map-compass-rose-plot-42608/), který nabízí obrázek s průhledným pozadím. Pokud preferujete jiný obrázek, můžete použít libovolný jiný soubor, stačí zajistit, aby měl průhledné pozadí, což lépe vypadá při rotaci.

Implementace kódu

  1. Vytvoření obrázku kompasu:

    • Zkopírujte váš obrázek do složky res/drawable a pojmenujte ho compass.png.

    • Otevřete soubor activity_main.xml a nahraďte stávající TextView následujícím ImageView:

      xml
      <ImageView
      android:id="@+id/imageViewCompass" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/compass" android:contentDescription="@string/compass_desc"/>
  2. Deklarace proměnných v MainActivity.java:

    V souboru MainActivity.java přidejte následující deklarace globálních proměnných:

    java
    private SensorManager mSensorManager; private Sensor mMagnetometer; private Sensor mAccelerometer; private ImageView mImageViewCompass;
    private float[] mGravityValues = new float[3];
    private float[] mAccelerationValues = new float[3];
    private float[] mRotationMatrix = new float[9];
    private float mLastDirectionInDegrees = 0f;
  3. Vytvoření posluchače senzorů:

    Přidejte posluchač událostí pro senzory, který bude reagovat na změny v datech ze senzorů:

    java
    private SensorEventListener mSensorListener = new SensorEventListener() {
    @Override public void onSensorChanged(SensorEvent event) { calculateCompassDirection(event); } @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // Nothing to do } };
  4. Registrace senzorů v metodách onResume() a onPause():

    V metodách onResume() a onPause() zajistíme registraci a odregistrování posluchače senzorů:

    java
    @Override protected void onResume() { super.onResume(); mSensorManager.registerListener(mSensorListener, mMagnetometer, SensorManager.SENSOR_DELAY_FASTEST); mSensorManager.registerListener(mSensorListener, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST); } @Override protected void onPause() { super.onPause(); mSensorManager.unregisterListener(mSensorListener); }
  5. Inicializace senzorů a animace:

    V metodě onCreate() inicializujte senzory a nastavte obrázek kompasu:

    java
    mImageViewCompass = findViewById(R.id.imageViewCompass);
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  6. Výpočet směru kompasu:

    Metoda calculateCompassDirection() spočítá směr kompasu a animuje obrázek při změně orientace:

    java
    private void calculateCompassDirection(SensorEvent event) { switch (event.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: mAccelerationValues = event.values.clone(); break; case Sensor.TYPE_MAGNETIC_FIELD: mGravityValues = event.values.clone(); break; }
    boolean success = SensorManager.getRotationMatrix(mRotationMatrix, null, mAccelerationValues, mGravityValues);
    if (success) { float[] orientationValues = new float[3]; SensorManager.getOrientation(mRotationMatrix, orientationValues);
    float azimuth = (float) Math.toDegrees(-orientationValues[0]);
    RotateAnimation rotateAnimation = new RotateAnimation( mLastDirectionInDegrees, azimuth, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setDuration(50); rotateAnimation.setFillAfter(true); mImageViewCompass.startAnimation(rotateAnimation); mLastDirectionInDegrees = azimuth; } }

Další tipy a úvahy

Při práci s animacemi a senzory je důležité experimentovat s nastavením časování aktualizací senzorů a rychlostí animace. V našem kódu používáme SENSOR_DELAY_FASTEST a nastavujeme trvání animace na 50 milisekund, čímž získáme rychlou animaci. Můžete však také experimentovat s pomalejšími aktualizacemi senzorů a pomalejšími animacemi a porovnat výsledky. Další nastavení, jako je například jemnost animace, může ovlivnit celkový dojem z aplikace a její plynulost.

Kromě toho je užitečné mít na paměti, že aplikace bude nejlépe fungovat na reálném zařízení, protože emulátory nemají vestavěné senzory pro magnetometr a akcelerometr.

Jak používat výchozí aplikaci fotoaparátu v Androidu pro pořizování snímků a jejich zobrazení

Pro vývoj aplikace, která umožňuje uživatelům pořídit fotografii pomocí výchozí aplikace fotoaparátu a následně ji zobrazit v aplikaci, je klíčové pochopit, jak správně využít Intenty a správně nastavit příslušná oprávnění v Androidu. Tento návod popisuje proces krok za krokem, jak použít výchozí aplikaci fotoaparátu pro zachycení a zobrazení fotografie.

Pro začátek vytvoříme nový projekt v Android Studiu. Pojmenujme ho například UsingTheDefaultCameraApp a použijeme nastavení pro telefon a tablet. Jako typ aktivity vybereme Empty Activity.

Nyní se podívejme na samotnou implementaci. Cílem je vytvořit uživatelské rozhraní s tlačítkem a ImageView. Tlačítko bude sloužit k vytvoření Intentu, který spustí výchozí aplikaci fotoaparátu. Po pořízení fotografie aplikace obdrží zpětnou vazbu prostřednictvím callbacku.

Prvním krokem je úprava souboru Android Manifest, kde je potřeba přidat příslušná oprávnění pro práci s externím úložištěm a kamerou. Přidejte následující oprávnění:

xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Dalším krokem je úprava souboru activity_main.xml. Zde odstraníme výchozí TextView a nahradíme jej tlačítkem a ImageView pro zobrazení pořízené fotografie. Kód pro toto rozhraní vypadá následovně:

xml
<Button
android:id="@+id/takePictureButton" android:text="Pořiďte fotografii" android:onClick="takePicture" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="match_parent" />

V souboru MainActivity.java přidáme několik důležitých proměnných a metod. Nejprve definujeme globální proměnnou pro identifikaci požadavku a proměnnou pro URI pořízené fotografie:

java
final int PHOTO_RESULT = 1;
private Uri mLastPhotoURI = null;

Dále vytvoříme metodu pro generování URI pro uložení fotografie:

java
private Uri createFileURI() { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(System.currentTimeMillis());
String fileName = "PHOTO_" + timeStamp + ".jpg";
return Uri.fromFile(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), fileName)); }

Metoda pro pořízení fotografie bude vypadat takto:

java
public void takePicture(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { mLastPhotoURI = createFileURI(); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mLastPhotoURI); startActivityForResult(takePictureIntent, PHOTO_RESULT); } }

Následně přidáme metodu pro zpracování výsledku fotografování, která zobrazí pořízený obrázek v ImageView:

java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PHOTO_RESULT && resultCode == RESULT_OK) { mImageView.setImageBitmap(BitmapFactory.decodeFile(mLastPhotoURI.getPath())); } }

Po těchto krocích můžeme aplikaci spustit na zařízení nebo emulátoru. Pokud vše probíhá správně, uživatelé budou moci pomocí aplikace pořídit fotografii a okamžitě ji zobrazit.

Pokud vám nevadí, kde se fotografie uloží, můžete volitelně vynechat parametr MediaStore.EXTRA_OUTPUT. V takovém případě bude v onActivityResult() vrácena miniatura fotografie, kterou lze jednoduše zobrazit následujícím způsobem:

java
if (data != null) {
imageView.setImageBitmap((Bitmap) data.getExtras().get("data")); }

Pokud chcete načíst plnou velikost fotografie, můžete použít následující kód:

java
if (data != null) { try { imageView.setImageBitmap( MediaStore.Images.Media.getBitmap(getContentResolver(), Uri.parse(data.toUri(Intent.URI_ALLOW_UNSAFE))) ); } catch (IOException e) { e.printStackTrace(); } }

Pokud místo fotografie chcete pořizovat video, celý proces je velmi podobný. Stačí změnit Intent na MediaStore.ACTION_VIDEO_CAPTURE. Výsledek videozáznamu obdržíte opět v metodě onActivityResult() ve formě URI videa.

Použití výchozí aplikace fotoaparátu je jednoduchý způsob, jak implementovat funkčnost pro pořizování snímků v aplikaci bez nutnosti přímé interakce s hardwarem zařízení. Tento přístup je ideální pro rychlou implementaci, pokud vám nevadí omezená kontrola nad parametry fotoaparátu. Pokud ale potřebujete více funkcí a přímou kontrolu nad nastavením kamery, můžete zvážit použití staršího rozhraní Camera API nebo novějšího Camera2 API, které nabízí širší možnosti.

Pro práci s těmito API budete potřebovat specifické přístupy k hardwaru, což zahrnuje například použití TextureView pro zobrazení živého náhledu z kamery, což je výhodné pro novější verze Androidu, které podporují Camera2 API. Při práci s těmito API si dejte pozor na podporu různých verzí Androidu, protože novější API jsou dostupná pouze od verze Android 5.0 (API 21).