Predvajanje glasbe

Če želimo v naši aplikaciji predvajati večjo zvočno datoteko in želimo naenkrat predvajati le eno datoteko, uporabimo razred MediaPlayer. Primer takšnega obnašanja so na primer predvajalniki glasbe. Glasbene datoteke so velike tudi po 5 MB in več, tako da lahko z njimi zelo hitro zasedemo delovni pomnilnik naprave. Zato moramo paziti, da jih naenkrat ne predvajamo preveč in da na koncu predvajanja sprostimo pomnilnik.

Pa si poglejmo kar kodo. Najprej moramo dobiti pot do datoteke. Recimo, da imamo glasbeno datoteko sound.mp3:

File folder = Environment.getExternalStorageDirectory();
Uri uri = Uri.fromFile(new File(folder, "sound.mp3"));
Spremenljivka uri predstavlja pot do zvočne datoteke in zdaj bomo z njeno pomočjo ustvarili instanco razreda MediaPlayer:
MediaPlayer mp = MediaPlayer.create(context, uri);
if (mp == null) {
Toast.makeText(context, R.string.err_file_missing,
LENGTH_SHORT).show();
return;
}

Če datoteke ni na naslovu, na katerega kaže uri, ali pa je prišlo do kakšne napake pri branju, je spremenljivka mp enaka null. V tem primeru moramo uporabnika ustrezno obvestiti, predvajanja pa seveda tudi ne moremo izvesti.

Ne pozabimo: do datoteke ne moremo dostopati, če nimamo pravic za branje zunanjega pomnilnika:
android.permission.READ_EXTERNAL_STORAGE!]

Omenili smo že, da moramo paziti na to, da na koncu predvajanja sprostimo pomnilnik. To storimo tako, da predvajalniku dodamo kodo, ki se bo pognala ob koncu predvajanja:

mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});

To je to. Vse je pripravljeno za začetek predvajanja, samo še poženemo ga:
mp.start();
In že lahko uživamo v zvokih, ki prihajajo iz naše naprave.

Pretakanje

Glasba in film se še najbolj upirata temu, da bi z njima upravljali izključno v oblaku, predvsem zaradi velikosti. Vse hitrejše povezave pa odpravljajo še to omejitev, zato si poglejmo, kako lahko predvajamo zvoke kar neposredno z interneta. Običajno je pretakanje datotek bolj zapleteno od branja z lokalnih medijev, vendar tu ni tako. Postopek je namreč povsem enak kot pri predvajanju lokalnih datotek, vse, kar moramo spremeniti, je uri:

String url = “http://nekadomena.si/sound.mp3”;
Uri uri = Uri.parse(url);

Vidimo, da je ta del kode še celo bolj preprost kot v prejšnjem poglavju. Preostalo kodo ponovimo in že lahko poslušamo glasbo sproti, ko jo pretakamo s spleta. Da, to je to.

Ne pozabimo: tudi za dostop do interneta potrebujemo ustrezne pravice:
android.permission.INTERNET!]

Kratki zvoki

V igrah ali interaktivnih aplikacijah želimo predvajati veliko kratkih zvokov, kot so na primer zvoki živali, vozil, orožja, kakšna obvestila o dosežkih v igri, zvok ob pritisku na gumb itd. Te zvoke želimo predvajati v trenutku, ko se določena akcija zgodi, zato so običajno že vključeni v aplikaciji sami, da jih ni treba brati z zunanjega pomnilnika ali celo pretakati s spleta. Datoteke z zvoki v aplikaciji shranimo v mapi res/raw, nato pa nam jih Android SDK ponudi za dostop prek virov. Če na primer v to mapo shranimo datoteke sound_01.mp3, sound_02.mp3 in sound_03.mp3, lahko do njih dostopamo z viri R.raw.sound_01, R.raw.sound_02 in R.raw.sound_03.

Da pa lahko te zvoke hitro in enostavno predvajamo, ima Android priročen razred SoundPool, ki omogoča hitro in preprosto predvajanje enega ali več zvokov hkrati. Najprej ustvarimo SoundPool:

SoundPool soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC,
0);

Prvi parameter pove, da bomo lahko hkrati predvajali tudi do deset zvokov, drugi parameter, da gre za glasbo (in ne recimo za zvonjenje telefona), tretji pa predstavlja kakovost predvajanja, vendar pri trenutnih verzijah Androida to še nima učinka.
Zdaj dodamo zvoke v ta bazen:

int soundId_01 = soundPool.load(context, R.raw.sound_01, 1);
int soundId_02 = soundPool.load(context, R.raw.sound_02, 1);
int soundId_03 = soundPool.load(context, R.raw.sound_03, 1);

Metoda load sprejme vir zvoka, številka 1 pa predstavlja prioriteto predvajanja, vendar tudi to še nima učinka. Kar pa ta metoda vrne, je identifikacijska številka, ki jo uporabimo za predvajanje posameznega zvoka. Če želimo na primer predvajati zvok sound_02.mp3, pokličemo:

soundPool.play(soundId_02, 1, 1, 1, 0, 1);

Metoda play najprej sprejme identifikacijsko številko zvoka, naslednji dve številki predstavljata glasnost (med 0 in 1), potem je prioriteta zvoka (če presežemo deset predvajanih zvokov naenkrat, se prekine predvajanja zvoka z najnižjo prioriteto), nato je število ponovitev (0 pomeni, da se bo zvok predvajal le enkrat, 1 pomeni, da se bo potem še enkrat ponovil itd.), zadnja številka pa je hitrost predvajanja (0.5 predvaja zvok s polovično hitrostjo, 2 ga predvaja z dvojno). Ko je predvajanje zvokov končano (na primer ob koncu stopnje v igri), moramo spet sprostiti pomnilnik tako, da kličemo:

soundPool.release();

Snemanje

Poleg predvajanja pa lahko zvok tudi snemamo. Tudi snemanje je preprosto: najprej napravimo instanco razreda MediaRecorder in ji povemo, s katerega vira naj snema in v kateri format naj shrani zvok:

MediaRecorder mr = new MediaRecorder();
mr.setAudioSource(MediaRecorder.AudioSource.MIC);
mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

Nato določimo še pot datoteke, v katero želimo posnetek shraniti (na primer v datoteko soud.3gp na pomnilniški kartici):

String folder =
Environment.getExternalStorageDirectory().getAbsolutePath();
mr.setOutputFile(folder + "/sound.3gp");

In če je datoteka na tem mestu zapisljiva, lahko začnemo snemati, v nasprotnem primeru pa obvestimo uporabnika:

try {
mr.prepare();
mr.start();
} catch (IOException e) {
Toast.makeText(getActivity(), R.string.err_writing_file,
LENGTH_SHORT).show();
}

To je to, naprava zdaj snema zvok prek mikrofona. Ko želimo snemanje končati, pokličemo:
mr.stop();
mr.release();

Posnetek je zdaj zapisan v izbrano datoteko in lahko ga predvajamo z metodo, ki smo jo opisali na začetku članka.

Ne pozabimo: za snemanje potrebujemo pravice za snemanje in pravice za pisanje datotek na zunanji pomnilnik:
android.permission.RECORD_AUDIO
android.permission.WRITE_EXTERNAL_STORAGE!]

Zaključek
Z zgornjimi metodami smo pokrili predvajanje glasbe tako v obliki predvajalnika glasbe – lokalne ali spletne – kot tudi zvoke v igrah in aplikacijah. Obstaja še nekaj dodatnih metod za upravljanje, kot so na primer pause, seekTo, setLooping itd., a je njihova uporaba tako preprosta, kot je preprosto samo predvajanje, tako da ne potrebuje dodatne razlage. Vso zgornjo kodo najdete na GitHubu: http://git.io/tq4aww.

Moj mikro, november – december 2014 | Rok Končina