Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
Odsek za računarsku tehniku i računarske komunikacije
Projektovanje namenskihračunarskih struktura 1
Binder, IPC i servisi
Arhitektura Androida
App0 App1 App2 App3 App4
Application layer
Activity manager
Frameworks layerWindow manager
Content providers
View systemNotification
manager
Package manager
Resource manager
XMPP service
Surface manager
Runtime layer
OpenGL/ES
SGL
Media framework
Freetype
SSL
SQLite
Webkit
libc
Libraries Android runtime
CoreLibraries
Dalvik Virtual Machine (DVM)
Kernel layer
Display driver
USB driver
Mouse driver
Keyboard driver
Ethernet driver
WiFi driver
Flash memory driver
Audio drivers
Binder (IPC) driver
Power management
Hardware
Java
C, C
++, n
ativ
e co
de
Ass
emb
ler,
C
Graphics Audio Camera GPS ...
Hardware Abstraction Layer (HAL)
2020 2
Binder
Binder
Binder
Binder je novi, dvosmerni mehanizam međuprocesne komunikacije u Android
Nastao je od OpenBinder projekta
Ugrađen je u sam kernel, ali ne koristi postojeće mehanizme Linux
Omogućuje razmenu podataka, pozivanje udaljenih metoda i sinhronizaciju
Predstavlja ključni deo Android-a
Koristi se dominantno za sledeće namene
o Komunikacija aplikacija sa servisima korisničkih aplikacijai sa uslugama Android (npr. upravljanje prozorima, pozivom, itd.)
o Obaveštavanje aplikacija o korisničkoj akciji
o Javljanje uništenih klijenata
o Intent, ContentProvider – sve je to Binder ispod haube
Konceptualno koristi klijent-server arhitekturu (više detalja u dodatku)2020 3
Upotreba Binder
Najviše se koristi na relaciji aplikacija - radni okvir -nativni sloj
Koraci
o Pronalaženje i povezivanje sa prijemnikom
o Priprema podataka za slanje
o Slanje podataka
o Prijem podataka
o Raspakivanje primljenih podataka
o Obrada primljenih podataka
Priprema i slanje odgovora u dvosmernoj komunikaciji je veoma slična
2020 4
Mehanizam Binder
2020 5
Razni scenariji upotrebe Binder
2020 6
Binder terminologija
Binder drajver u jezgru
Binder protokol – komunikacija sa drajverom
IBinder interfejs – predefinisane metode koje Binder učesnici
moraju da implementiraju
AIDL – jezik za opis IBinder interfejsa
Binder token – 32-bitni identifikator učesnika u komunikaciji
Binder servis – strana koja pruža uslugu
Binder klijent – korisnik usluge
Transakcija – poziv udaljene usluge
Parcel – nosilac poruke
Marshall – pakovanje poruke za slanje
Unmarshalling – raspakivanje primljene poruke
Proxy – implementacija AIDL sprege za mapiranje poziva metode
IBinder na tranzakciju
Stub – parcijalna implementacija AIDL sprege za mapiranje
tranzakcija na odgovarajuće metode servisa
Context manager (servicemanager) služi kao registrator Binder
objekata2020 7
Servisi
Programske komponente koje rade u pozadini i koje obično nemaju interakciju sa korisnikom (tj. GUI)
Vrste:
o sistemski servisi
o aplikacioni servisi
Sa servisima se tipično komunicira preko Binder IPC!
Sistemski servisi postoje u uređaju i do njih se dolazi preko odgovarajućih menadžera:
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Aplikacioni servisi se naknadno instaliraju i njih pokreću ili aplikacije ili BroadcastReceiver-i
o na dalje ćemo pod pojmom servis misliti na aplikacioni servis
2020 8
Sistemski servisi
Veliki broj sistemskih servisa:
o alarm (za rad sa alarmom; kada se aktivira, šalje se Intent koji će neki servis pokupiti)
o audio (za rad sa audio podsistemom)
o clipboard (copy/paste)
o connectivity (rad sa mrežom – WiFi, GPRS, UMTS, itd.)
o download (za dugotrajno skidanje datoteka preko HTTP protokola)
o notification (za slanje obaveštenja korisniku preko zone na vrhu ekrana)
o location (za lociranje uređaja upotrebom GPS-a ili preko mreže)
o power (za upravljanje potrošnjom struje; npr. da se spreči automatsko zatamnjivanje
ekrana)
o sensor (za rad sa senzorima: orijentacija, blizina korisnika telefonu, ubrzanje, pritisak, temperatura, magnetno polje,...)
o telephony (za rad sa telefonom)
o USB (za rad sa USB uređajima – od v3.1 ili veće (proizvođači mogu da urade backportna niže verzije, ako žele)
o vibracija (upravljanje vibracijama)
o Wifi (za rad sa Wifi mrežama)
o display (za rad sa ekranom)
o ...
2020 9
Sistemski servisi – menadžeri
Svaki sistemski servis je reprezentovan odgovarajućim menadžerom
o menadžer predstavlja vezu između aplikacije i sistemskog servisa
o sistemski servis nije dostupan iz SDK, već samo iz izvornog koda Android OS
o menadžer sadrži sve javne metode sistemskog servisa, koje klijentske aplikacije mogu da pozovu
Servisi se po pravilu implementiraju u nativnom korisničkom prostoru
2020 10
Aplikacioni servisi
Postoje dve vrste servisa:
o lokalni servisi (Local Service)
o udaljeni servisi (Remote Service)
Lokalni servisi se izvršavaju u istom memorijskom prostoru gde i aplikacija koja ih je pozvala
Udaljeni servisi se izvršavaju u posebnom memorijskom prostoru i sa njima se komunicira upotrebom IPC (InterProcess Communication) mehanizma
Servisi se ne mogu posmatrati kao posebna programska nit ili poseban proces
Mogu imati duži životni vek od aplikacije koja ga koristi
2020 11
Lokalni servisi
Postoje dva načina komunikacije aplikacije sa lokalnim servisom:
o metode startService() i stopService(), kojima se startuje/zaustavlja servis
o metoda bindService(), koja se inače koristi i za udaljene servise
Metoda startService() kreira servis i poziva njegovu onCreate() metodu, nakon čega poziva onStartCommand() metodu
Metoda stopService() poziva onDestroy() metodu servisa, nakon čega se servis gasi
Ako je servis lokalni i nema IPC metoda, već se samo startuje/zaustavlja, može se i bindService() koristiti
o Metoda bindService() kreira servis i poziva onCreate() metodu
o U tom slučaju, moguća je dodatna interakcija sa servisom dok se izvršava, npr da se ispita stanje servisa
Dizajn odluka koji pristup se koristi, a zavisi od načina upotrebe i funkcije servisa2020 12
Lokalni servisi
Ako se startuje sa startService(), može da živi i duže od aplikacije koja ga je startovala
Zaustavlja se eksplicitno sa stopService() ili sa stopSelf()
Ako se aplikacija vezuje (bind) za servis, gasi se tek kada se poslednji korisnik odveže
o Koristi mogućnost Binder-a da obavesti server o ugašenim klijentima
Servis treba da podrži situaciju da bude zaustavljen i restartovan od strane sistema
Realizacija:
1. kreiranje klase
2. prijava u manifestu
3. pisanje klijentskog koda
2020 13
Upotreba lokalnih servisa
2020 14
Prijava servisa u manifestu
Servis se u manifest datoteci prijavljuje unutar application taga, kao service tag
Obavezan atribut
o android:name – puno ime servisa (fully qualified name), koje uključuje i naziv paketa i naziv klase
Opcioni atribut
o android:enabled – uključuje/isključuje servise deklarativno
Privatni servisi
o android:exported = false
2020 15
Pomoćna klasa IntentService
Realizuje obradu pojedinačnih zahteva
Sekvencijalna obrada u onHandleIntent()
U posebnoj niti – ne treba brinuti o višenitnom radu
Ne treba brinuti o startovanju i zaustavljanju servisa
Zahtevi se pakuju u Intent, sa parametrima zahteva
2020 16
Primeri
Primeri servisa se nalaze u dodatku na kraju prezentacije
2020 17
Udaljeni servis
Izvršava se u zasebnom memorijskom prostoru
Izložio je svoje metode klijentima preko IPC (Inter-Process Communication) mehanizma
Moguće opcije za IPC
o Mrežna komunikacija (engl. sockets)
o Cevi (engl. pipes)
o Deljena memorija (engl. shared memory)
o Memorijski mapirane datoteke
o Redovi poruka, itd.
Redosled operacija
o Klijenti se vezuju na udaljeni servis
o Klijenti pozivaju metode servisa
o Klijenti se odvezuju od udaljenog servisa
2020 18
IPC u Androidu
U Androidu je IPC implementiran preko Binder podsistema
Binder omogućuje komunikaciju među procesima, ali je potrebna serijalizacijaprogramskih struktura
Zasniva se na klijent-server arhitekturi
Klijent poziva metode servera, te moraju imati zajednički jezik - protokol
To se postiže pomoću AIDL datoteka sa opisima metoda koje poseduje server
interface IMyService {
void startCount(int number);
}
Specijalan prevodilac koji prevodi AIDL datoteke u Java kod
2020 19
Procedura razvoja udaljenog servisa
1. U AIDL datoteci se definišu metode servisa - to je ujedno i dizajn sprege
2. Realizuje se udaljeni servis na osnovu AIDL datoteke
3. Servis se prijavljuje u manifestu
4. Napiše se klijentski kod
1. veže se za servis
2. pozivaju se metode iz AIDL interfejsa
3. klijent se odvezuje od servisa
ServisKlijent
Stu
b/P
roxy
Stu
b/P
roxy
AIDLGenerateGenerate
2020 20
Šta je AIDL?
Android Interface Definition Language
o definicioni jezik za opis metoda servisa
o bazira se na IDL (Interface Definition Language), koji se koristi u CORBA sistemima
o uglavnom se definišu interfejsi koje će implementirati serverski deo, odn. servis
Sintaksa je slična Javinoj
o podržava sve Javine primitivne tipove, kao i String, List (implementiran kao ArrayList), Map(implementiran kao HashMap) i CharSequence
Jedan interfejs je implementiran od strane jednog servisa
Ako su klijent i server različiti projekti, potrebno je da se ista AIDL datoteka nalazi u oba projekta, u istoimenom paketu!
Proxy i Stub se generišu tokom prevođenja projekta!
2020 21
Primer AIDL
Servis koji pušta muziku u pozadini:
o IRemoteServiceExample.aidl
package com.rtrk.service.remote;
interface IRemoteServiceExample {
void startMusic();
void stopMusic();
}
2020 22
Udaljeni servisi upotrebom Messenger
IPC bez AIDL
Sekvencijalna obrada, bez paralelizma
Messenger zna da razmenjuje poruke
Handler obrađuje poruke
Primer u dodatku
2020 23
Callback
Binder omogućava callback - da servis može da pozove određenu metodu na povezanom klijentu
o ako je zadatak koji servis obavlja dugotrajan, onda se na serveru kreira AsyncTask, i odmah se vraća izvršenje na klijenta
o da bi klijent znao da je zadatak izvršen, servis će ga obavestiti preko callback poziva
Da bi se ovo realizovalo, potrebno je dodati još jednu AIDL datoteku i kod klijenta i kod servera, koja će sadržati metodu koju će server pozvati kada se posao završi
Alternativno, callback je moguće realizovati i pomoću Messenger!
2020 24
Rezime
Binder je ključni element Android za komunikaciju između aplikacija i sistema
Predstavlja mehanizam IPC koji ima niz pojavnih oblika
Često se koristi i u komunikaciji sa lokalnim i udaljenim servisima
Servisi su mehanizam za pozadinske procese, koji mogu biti
o Lokalni startovani
o Lokalni vezani (najsličniji udaljenima) i
o Udaljeni
Za opis sprege sa udaljenim servisima koristi se AIDL
U svakom slučaju, servisi obezbeđuju neke usluge aplikacijama, i mogu da imaju duži životni vek od istih
2020 25
DodatakDodatni detalji klijent-server arhitekture
2020 26
Klijent-server arhitektura
Predstavlja često korišćeni dizajn šablon
Nije ograničen samo na mrežne komunikacije
Centralizovan dizajn
o Odslikava logičku strukturu/arhitekturu sistema
o Serveri i klijenti su obično u različitim kontekstima
o Mogu biti dislocirani, ali mogu biti i deo istog procesa
o Komunikacija se može obaviti raznim IPC metodama, ne nužno mrežom
Heterogena struktura
o Čvorovi su po pravilu različiti (tehnologija, funkcije, performanse)
Server
Klijent 1
Klijent 2
2020 27
Osobine klijenata i servera
Klijenti
o Vremenski su nestalniji od servera
o Zahtevaju uslugu od servera
o Obično su mnogobrojniji od servera
Serveri
o Konstantniji su u vremenu
o Predstavljaju centar komunikacije
o Pružaju uslugu klijentima
Izazovi i moguće greške?
Server
Klijent 1 Klijent 2 Klijent 1
2020 28
Protokol komunikacije između klijenta i servera
Ključni momenat je protokol komunikacije razumljiv za sve elemente strukture (klijenta i servera)
Obično server diktira protokol, a klijenti se prilagođavaju
Protokol može da definiše
o Pronalaženje komponenti sistema (obično servera)
o Inicijaciju i održavanje sesije
o Razmenu i format podataka
Nekada je standardizovan, može biti i namenski
Izazovi, moguće greške?
ServerKlijent
1
2020 29
Primeri klijent-server arhitekture
Web server i browser, standard je HTTP
DLNA/UPnP Framework, standard je DLNA/UPnP
Network Time protokol, standard je NTP
VoIP, standard je npr. SIP
OS i korisnički programi, sprega je API (npr. POSIX)
Servisi u računarskom sistemu (npr. Android, Windows)
2020 30
DodatakPrimer lokalnog startovanog servisa
2020 31
Kreiranje klase lokalnog servisa
Nasledi se klasa Service i redefinišu odgovarajuće metode:• onCreate()
• ovde se odradi inicijalizacija• poziva se metodom startService() iz aktivnosti
• onStartCommand()• poziva se nakon inicijalizacije (onCreate() metoda)• vraća jednu od dve vrednosti:• START_STICKY – ako sistem zaustavi servis (nedostatak memorije i sl.), kasnije će
probati da ponovo kreira servis i da ponovo pozove onStartCommand() metodu• START_NON_STICKY – ako sistem zaustavi servis (nedostatak memorije i sl.), kasnije
neće ponovo kreirati servis, već je potrebno da se eksplicitno startuje ponovo• onDestroy()
• poziva se neposredno pre zaustavljanja servisa• servis se zaustavlja pozivom stopService() motode iz aktivnosti
2020 32
Kreiranje klase lokalnog servisa
Zadatak koji servis obavlja realizuje/poziva se unutar onCreate() ili onStartCommand() metoda
Ako je posao koji se realizuje dugotrajan, bitno je da se realizuje u posebnoj niti!
Zašto? Da se ne bi opteretila glavna nit programa, odakle je pozvan servis!
2020 33
Kreiranje klase lokalnog servisa
public class LocalServiceExample extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() finished");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand() invoked");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() finished");
}
}
2020 34
Prijava servisa u manifestu
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".ServicesExamplesActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:enabled="true" android:name="com.rtrk.service.local.LocalServiceExample" />
</application>
2020 35
Klijentski deo
Klijent startuje servis pozivom startService() metode
o argument je Intent koji identifikuje servis
localServiceIntent = new Intent(getApplicationContext(),LocalServiceExample.class);
Klijent zaustavlja servis pozivom stopService() metode
argument je Intent koji identifikuje servis
može se pozvati i iz samog servisa
2020 36
Klijentski kod
Intent localServiceIntent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
localServiceIntent = new Intent(getApplicationContext(), LocalServiceExample.class);
}
public void startLocal(View view) {
startService(localServiceIntent);
}
public void stopLocal(View view) {
stopService(localServiceIntent);
}
2020 37
Automatsko pokretanje servisa
Kako?
Automatsko pokretanje servisa prilikom paljenja uređaja:o registrovati BroadcastReceiver na događaj android.intent.action.BOOT_COMPLETED ili
android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE (ako je na SD kartici)o iz tog receiver-a startovati servis:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, MyService.class);
context.startService(service);
}
}
2020 38
DodatakPrimer lokalnog vezanog servisa
2020 39
Lokalni, vezani servisi
Ukoliko su klijent i servis u istom adresnom prostoru, i lokalni servis može biti vezan
Ne mora da se opterećuje sa IPC
onBind() mora da vrati instancu Bindera preko kojeg se pristupa javnim metodama servisa (getRandomNumber)
2020 40
Primer lokalnog, vezanog servisa
public class LocalService extends Service {
private final IBinder mBinder = new LocalBinder();
private final Random mGenerator = new Random();
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
2020 41
Povezivanje sa lokalnim servisom
bindService (intent, mConnection, Context.BIND_AUTO_CREATE);
Objekat ServiceConnection služi upravljanju vezom sa servisom
class LocalServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
}
Int n = mService.getRandomNumber();
2020 42
DodatakPrimer udaljenog servisa
2020 43
Prevođenje AIDL datoteke
Radi se automatski u integrisanom okruženju
Rezultat je mašinski generisana klasa koju ne modifikujemo!
public interface IRemoteServiceExample extends android.os.IInterface
{
public static abstract class Stub extends android.os.Binder implements
com.rtrk.service.remote.IRemoteServiceExample
{
...
private static class Proxy implements
com.rtrk.service.remote.IRemoteServiceExample {
private android.os.IBinder mRemote;
public void startMusic() throws android.os.RemoteException {
...
}
public void stopMusic() throws android.os.RemoteException {
...
}
2020 44
Implementacija udaljenog servisa
Ključna metoda u servisu je onBind()
o ona vraća instancu IBinder klase, koja će se koristiti za komunikaciju
o u ovoj metodi se kreira klasa naslednica klase IRemoteServiceExample.Stub i realizuju se sve metode navedene u AIDL interfejsu
Klasa IRemoteServiceExample.Stub je mašinski generisana klasa (nastala od AIDL interfejsa), i ona se nasleđuje da bi se realizovale sve metode navedene u AIDL interfejsu
Prilikom implementacije metoda iz AIDL interfejsa, voditi računa da se posao, ako je dugotrajan, realizuje preko AsyncTask klase!
2020 45
Implementacija udaljenog servisa
public class RemoteServiceExample extends Service {
@Override
public IBinder onBind(Intent intent) {
return new IRemoteServiceExample.Stub() {
@Override
public void startMusic() throws RemoteException {
}
@Override
public void stopMusic() throws RemoteException {
}
};
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
2020 46
Prijava servisa u manifestu
Servis se prijavljuje unutar application taga, kao service tag
Obavezan atribut:
o android:name – puno ime servisa (fully qualified name), koje uključuje i naziv paketa i naziv klase
Opcioni atributi:
o android:enabled – uključuje/isključuje servise deklarativno
o android:remote – definiše da li se servis izvršava u sopstvenom memorijskom prostoru
Intent filter – podtag koji definiše akcije koji startuju servis
o može se navesti konkretna klasa, a može i konstanta koja jedinstveno određuje servis
o tada klijent ne mora da zna tačan naziv klase
2020 47
Primer prijave servisa u manifestu
<application android:label="@string/app_name">
<service android:enabled="true" android:name=".RemoteServiceExample"
android:process=":remote" >
<intent-filter>
<action android:name="com.rtrk.service.remote.IRemoteServiceExample" />
<action android:name="com.rtrk.service.remote.REMOTE_SERVICE" />
</intent-filter>
</service>
</application>
2020 48
Klijentski kod - povezivanje
Poziva se metoda bindService(Intent, connection, flag), koja će vezati klijentsku aplikaciju za serviso prvi parametar je Intent kojim se identifikuje serviso drugi parametar je klasa koja predstavlja konekciju sa servisom, i koja će obezbediti pozivanje
metoda na serveruo treći parametar definiše da se servis kreira ovom komandom, ako pre toga nije postojao
Primer:
public void bindRemote(View view) {
conn = new BinderServiceConnection();
bindService(remoteServiceIntent, conn,
Context.BIND_AUTO_CREATE);
}
2020 49
Klijentski kod - povezivanje
Za komunikaciju klijenta sa servisom koristi se konekcija (drugi parametar metode bindService()), realizovana kao klasa koja nasleđuje ServiceConnection klasu
Ova klasa ima dve callback metode:
o onServiceConnected(), koja se poziva kada se uspostavi komunikacija sa servisom
o onServiceDisconnected(), koja se poziva kada se veza sa servisom raskine
Metoda onServiceConnected() se koristi da bi se inicijalizovala klasa koja poseduje metode servisa
o ova klasa implementira IRemoteServiceExample interfejs (mašinski generisan)
o ova klasa sadrži sve metode koje ima servis i omogućuje da se njihovim pozivom zapravo pozovu metode u servisu
2020 50
ServiceConnection
class BinderServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className,
IBinder boundService) {
service = IRemoteServiceExample.Stub.
asInterface((IBinder) boundService);
}
public void onServiceDisconnected(ComponentName className) {
service = null;
}
}
Varijabla service je atribut u klijentskoj aplikaciji i ona predstavlja vezu sa servisom:private IRemoteServiceExample service = null;
public void invokeRemote(View view) {
try {
service.startMusic();
} catch (RemoteException e) {
e.printStackTrace();
}
}
2020 51
Klijent raskida vezu sa servisom
Poziva se metoda unbindService(conn)
Ukoliko se poslednji klijent odjavio, servis se zaustavlja da udaljenoj strani
Ovaj poziv će izazvati poziv metode onServiceDisconnected() klase ServiceConnection na klijentu, ako je potrebno još nešto da se uradi prilikom gašenja veze sa servisom
2020 52
DodatakKomunikacija sa udaljenim servisom upotrebom Messenger
2020 53
Implementacija servisa upotrebom Messenger
public class MessengerService extends Service {
static final int MSG_SAY_HELLO = 1;
class IncomingHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger mMessenger = new Messenger(new IncomingHandler());
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}2020 54
Implementacija klijenta upotrebom Messenger
public class ActivityMessenger extends Activity {
Messenger mService = null;
boolean mBound;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName cName,IBinder service) {
mService = new Messenger(service); mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
mService = null; mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
Message msg = Message.obtain(null, MsgService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
2020 55
DodatakCallback iz servisa u klijent
2020 56
Callback primer
Primer:
o servis pušta muziku
o klijent startuje puštanje muzike
o muzika se pušta u pozadini
o servis ga obaveštava o završetku pesme pozivom metode notify() na klijentu
Dodaće se AIDL interfejs u klijentski projekat:
o ICallback.aidl
o ovaj interfejs ćemo prekopirati i u projekat servisa (da bi ga on mogao koristiti)
interface ICallback {
void notify(String text);
}
2020 57
Callback
Da bi servis mogao da pozove klijentski kod, potrebno je da mu se prosledi nekakva referenca na klijenta
o to se realizuje dodatnom metodom u IRemoteServiceExample.aidl datoteci
interface IRemoteServiceExample {
void setMusicFinishedCallback(in IBinder binder);
void startMusic();
void stopMusic();
}
Metoda setMusicFinishedCallback() kao parametar ima referencu na klijenta
o klijent će pozvati ovu metodu na server
o kao parametar će proslediti referencu na klijentski deo koda koji će server pozvati kada posao bude gotov
o Binder omogućava dvosmernu komunikaciju!
2020 58
Callback u servisu
Servis će zapamtiti referencu na klijenta da bi kasnije mogao da ga obavesti o završetku posla
Serverska implementacija metode setMusicFinishedCallback() će primiti referencu na klijenta, i zapamtiće je u atributu callback, tipa ICallback
o po završetku muzike, pozvaće metodu notify() na klijentu da ga obavesti da je posao gotov
2020 59
Callback u servisu
ICallback callback;
@Override
public IBinder onBind(Intent intent) {
return new IRemoteServiceExample.Stub() {
@Override
public void setMusicFinishedCallback(IBinder binder) throws RemoteException {
callback = ICallback.Stub.asInterface(binder);
}
...
}
}
2020 60
Callback u servisu
@Override
public void startMusic() throws RemoteException {
player.start();
player.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
try {
callback.notify("Song Ended");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
2020 61
Callback u klijentu
Klijent će po uspostavljanju konekcije sa servisom proslediti referencu na svoj kod koji će servis pozivatio taj kod implementira ICallback interfejs definisan u AIDL datoteci, i mašinski generisan kao
ICallback.Stub klasa
private Handler handler = new Handler();
private ICallback.Stub callback = new ICallback.Stub() {
@Override
public void notify(final String text) throws RemoteException {
handler.post(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), text,
Toast.LENGTH_LONG).show();
}
});
}
};
2020 62
Callback u klijentu
Ostaje još samo da klijentska aplikacija prosledi servisu referencu na svoj servis za callback
To se radi unutar metode onServiceConnected() u klasi naslednici ServiceConnection klase
o ova metoda se poziva kada se uspostavi veza sa servisom
o to je mesto gde se postavlja callback
2020 63
Callback u klijentu
class BinderServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className,
IBinder boundService) {
service = IRemoteServiceExample.Stub
.asInterface((IBinder) boundService);
try {
service.setMusicFinishedCallback(callback.asBinder());
} catch (DeadObjectException ex) {
Log.e(TAG, "DeadObjectException");
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className) {
service = null;
}
}
2020 64
Dijagram poziva udaljenih metoda sa callback
2020 65