
Vývoj pre Android - Multimédia / 13. časť
Späť na úvod >> Späť na seriál
Moderné telefóny a tablety majú kvalitný hardvér nielen na zobrazovanie fotografií, prehrávanie zvuku a videa, ale aj na ich snímanie a spracovanie. V prenosných zariadeniach sa často využíva možnosť nahrávať hlasové poznámky. Multimédiá sú jedným z hlavných faktorov prispievajúcich k atraktívnosti aplikácie.
Prehrávanie a nahrávanie zvuku a videa
Na podporu práce s multimédiami sú na platforme Android pre vývojárov aplikácií k dispozícii triedy
- AudioManager – trieda umožňuje aplikáciám prehrávať zvukové efekty a zvukové súbory či ovládať hardvérové zariadenia súvisiace s prehrávaním zvuku, napríklad reproduktory a bezdrôtové slúchadlá
- SoundPool – trieda obsahuje kolekciu zvukových vzoriek alebo streamov; umožňuje miešať a hrať viac vzoriek súčasne
- RingtoneManager, Ringtone – na ovládanie zvukov vyzváňania a alarmov
- MediaPlayer – trieda umožňuje aplikáciám prehrávať audio- a videosúbory
- MediaRecorder – umožňuje aplikáciám záznam zvuku a obrazu
- Camera – umožňuje aplikáciám ovládanie hardvéru na snímanie fotografií
Príklad – prehratie videa
Na zobrazovanie videa sa využíva trieda VideoView, odvodená od triedy SurfaceView, ktorá vnútorne využíva MediaPlayer. Trieda VideoView dokáže načítať videoobsah z rôznych zdrojov a riadiť jeho prehrávanie. V aplikácii zobrazíme okno na prehrávanie videa a integrované ovládacie prvky na riadenie prehrávania. V zložke res vytvorte vnorenú zložku raw a do nej prekopírujte súbor s krátkym videom z internetu.
V layoute hlavnej aktivity bude iba prvok VideoView na prehrávanie videa.
<VideoView
android:id="@+id/prehravac"
android:layout_width="480dp"
android:layout_height="640dp"
android:layout_centerInParent="true"
android:gravity="center" >
</VideoView>
|
V metóde OnCreate aplikácia získa odkaz na prvok VideoView. Následne vytvára inštanciu triedy MediaController, ktorý obsahuje ovládacie prvky na ovládanie prehrávača. Video sa nahráva cez URI, ktoré odkazuje na súbor uložený v zložke res / raw. Metóda OnPreparedListener sa bude volať, len čo je súbor s videom načítaný a pripravený na prehrávanie.
Kompletný kód hlavnej aktivity:
public class MainActivity extends Activity
{
VideoView videoView = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
videoView = (VideoView) findViewById(R.id.prehravac);
final MediaController mediaController =
new MediaController(MainActivity.this, true);
mediaController.setEnabled(false);
videoView.setMediaController(mediaController);
videoView.setVideoURI(Uri.parse(
"android.resource://com.example.video1/raw/demo"));
videoView.setOnPreparedListener(new OnPreparedListener()
{
@Override
public void onPrepared(MediaPlayer mp)
{
mediaController.setEnabled(true);
}
});
}
@Override
protected void onPause()
{
if (videoView != null && videoView.isPlaying())
{
videoView.stopPlayback();
videoView = null;
}
super.onPause();
}
}
|
Príklad: Snímanie fotografie
V príklade budeme aktivovať zosnímanie obrázka tlačidlom a obrázok uložíme do súboru. Používateľské rozhranie bude obsahovať iba jedno tlačidlo.
<Button
android:id="@+id/captureFront"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="onClick"
android:text="FOTO" />
|
Táto aplikácia bude potrebovať v AndroidManifest.xml povolenie použitia kamery, pretože táto aktivita môže znamenať zásah do súkromia používateľa a zápis do externej pamäte, kam sa uloží zosnímaný obrázok.
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
Možno budete chcieť nastaviť, aby aplikácia mohla využiť ďalšie funkcie, ako napríklad autofókus či blesk.
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name= "android.hardware.camera.autofocus" />
|
Najskôr vytvoríme samostatnú triedu UlozFoto, ktorá bude mať na starosti uložiť zosnímaný obrázok. Názvy obrázkov sa budú generovať s využitím dátumu a času. Trieda bude implementáciou PictureCallback.
public class UlozFoto implements PictureCallback
{
private final Context context;
public UlozFoto(Context context)
{
this.context = context;
}
@SuppressLint("SimpleDateFormat")
@Override
public void onPictureTaken(byte[] data, Camera camera)
{
File pictureFileDir = dajAdresar();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs())
{
Toast.makeText(context, "Nemôžem vytvoriť adresár.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat format = new SimpleDateFormat("yyyymmddhhmmss");
String date = format.format(new Date());
String photoFile = "Obrazok_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try
{
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(context, "Uložený obrázok:" + photoFile,
Toast.LENGTH_LONG).show();
} catch (Exception error)
{
Toast.makeText(context, "Chyba ukladania obrázku.",
Toast.LENGTH_LONG).show();
}
}
private File dajAdresar()
{
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "FotoMojejAplikacie");
}
}
|
V kóde hlavnej aktivity v obsluhe zatlačenia tlačidla voláme metódu takePicture(). Tá definuje iba jeden callback – PictureCallback, ktorý má na starosti uloženie zosnímaného obrázka.
public class MainActivity extends Activity
{
private Camera camera;
private int id = 0;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA))
{
Toast.makeText(this, "Kamera nedostupná",
Toast.LENGTH_LONG).show();
} else
{
id = prednaKamera();
if (id < 0)
{
Toast.makeText(this, "Předna kamera nedostupna.",
Toast.LENGTH_LONG).show();
} else camera = Camera.open(id);
}
}
public void onClick(View view)
{
camera.takePicture(null, null, new UlozFoto(getApplicationContext()));
}
private int prednaKamera()
{
int camid = -1;
int pocetKamer = Camera.getNumberOfCameras();
for (int i = 0; i < pocetKamer; i++)
{
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT)
{
camid = i; break;
}
}
return camid;
}
@Override
protected void onPause()
{
if (camera != null)
{
camera.release();camera = null;
}
super.onPause();
}
}
|
Príklad: Snímanie fotografie s využitím externej aplikácie
V tomto príklade nebudeme riešiť fyzické zosnímanie obrázka z hardvéru. Aplikácia vytvorí intent, pomocou ktorého oznámi operačnému systému, že potrebuje zosnímať obrázok. Operačný systém vyberie vhodnú aplikáciu na tento účel. Ak je vhodných aplikácií schopných splniť požiadavku deklarovanú v intente viac, vhodnú aplikáciu vyberie používateľ. Používateľské rozhranie bude obsahovať tlačidlo na zosnímanie a prvok ImageView na zobrazenie obrázka.
<LinearLayout ... >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="FOTO" >
</Button>
<ImageView
android:id="@+id/obrazok"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_launcher" >
</ImageView>
</LinearLayout>
|
Keďže aplikácia priamo nepristupuje k hardvéru kamery, nepotrebuje povolenie v manifeste. Toto povolenie, samozrejme, musí mať aplikácia, ktorá preberie intent a vykoná zosnímanie obrázka.
public class MainActivity extends Activity
{
private static final int REQUEST_CODE = 1;
private Bitmap bitmap;
private ImageView imageView;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.obrazok);
}
public void onClick(View View)
{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
InputStream stream = null;
if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK)
try
{
if (bitmap != null) bitmap.recycle();
stream = getContentResolver().openInputStream(data.getData());
bitmap = BitmapFactory.decodeStream(stream);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e)
{
e.printStackTrace();
}
finally
{
if (stream != null)
try {stream.close();}
catch (IOException e) {e.printStackTrace();}
}
}
}
|
V budúcom pokračovaní seriálu sa budeme venovať zberu a spracovaniu údajov zo senzorov v telefóne alebo tablete.