Configurare
Inițializarea mediului de lucru presupune instanțierea unor obiecte care gestionează operațiile ce pot fi realizate la nivelul serviciilor de rețea, respectiv a unor obiecte ascultător pentru evenimentele care pot surveni în cadrul acestora.
JmDNS
JmDNS folosește pachete de tip multicast pentru a gestiona serviciile disponibile în rețea. Politica Android este de a dezactiva implicit astfel de transferuri, pentru a optimiza bateria, motiv pentru care această funcționalitate trebuie activată temporar, doar pe parcursul aplicației Android. În acest sens, trebuie obținut mutexul corespunzător operațiilor de acest tip, care va fi eliberat ulterior:
public class ChatActivity extends Activity {
* ...
protected WifiManager wifiManager = null;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
* ...
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
multicastLock = wifiManager.createMulticastLock(Constants.TAG);
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
}
@Override
protected void onDestroy() {
super.onDestroy();
* ...
if (multicastLock != null) {
multicastLock.relase();
multicastLock = null;
}
}
* ...
}
Configurarea JmDNS presupune crearea unei instanțe a unui obiect de tipul JmDNS, care oferă funcționalități referitoare la gestiunea serviciilor existente doar în cadrul rețelei locale. Se utilizează metoda statică create(InetAddress, String), care primește ca parametri:
- adresa mașinii, obținută prin intermediul metodei
getIpAddress()
apelată pe obiectulConnectionInfo
asociat obiectului care gestionează interfața pentru comunicația prin intermediul rețelei fără fir; - denumirea mașinii (determinată pe baza adresei, prin rezoluție inversă).
try {
WifiManager wifiManager = ((ChatActivity)context).getWifiManager();
InetAddress address = InetAddress.getByAddress(
ByteBuffer.allocate(4).putInt(
Integer.reverseBytes(wifiManager.getConnectionInfo().getIpAddress())
).array()
);
String name = address.getHostName();
Log.i(Constants.TAG, "address = " + address + " name = " + name);
jmDns = JmDNS.create(address, name);
} catch (IOException ioException) {
Log.e(Constants.TAG, "An exception has occurred: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
Note
Instanțierea unui obiect de tip JmDNS
trebuie să se
realizeze pe firul de execuție al comunicației prin rețea, în caz
contrar generându-se o excepție de tipul
android.os.NetworkOnMainThreadException
.
API-ul pe care îl pune la dispoziție un astfel de obiect este asincron, astfel încât metodele apelate în cadrul claselor ascultător pentru diferite evenimente (înregistrare, descoperire, rezolvare) sunt executate în contextul unor fire de execuție dedicate, așa cum trebuie procedat în condițiile unor operații ce implică comunicația prin rețea.
- înregistrare
- registerService(ServiceInfo) - folosită pentru înregistrarea unui serviciu, care să poată fi disponibil ulterior în cadrul rețelei locale;
- unregisterService(ServiceInfo) sau unregisterAllServices()- folosită pentru deînregistrarea unui serviciu, astfel încât acesta să nu mai poată fi accesat, atunci când nu mai este necesar sau aplicația Android este distrusă.
- descoperire
- addServiceListener(String, ServiceListener) - folosită pentru pornirea descoperirii de servicii accesibile în rețeaua locală, operație care va fi realizată permanent, până când se va specifica altfel (explicit), afectând resurse precum transferul de informații prin rețeaua locală (lățimea de bandă) și bateria; vor fi monitorizate doar serviciile de un anumit tip;
- removeServiceListener(ServiceListener) - folosită pentru oprirea descoperirii de servicii de un anumit tip, atunci când acesta nu mai este necesară sau aplicația Android este întreruptă temporar.
- rezolvare - requestServiceInfo(String, String), pentru a identifica parametrii de conexiune (adresă și port) ai unui serviciu pentru care se cunoaște tipul și denumirea.â
Se observă că de regulă aceste metode primesc parametrii de tip:
- ServiceInfo -
în care sunt stocate perechi de tipul (atribut, valoare) cu privire
la serviciul disponibil în rețea:
- denumire;
- tip / subtip;
- adresă / denumire dispozitiv care găzduiește serviciul;
- port pe care poate fi accesat serviciul;
- prioritate;
- protocol
- date
- URL.
- ascultător pentru diferite evenimente legate de operațiile cu serviciile accesibile în rețea (înregistrare, descoperire, rezolvare), fiecare definind metode care descriu comportamentul pentru fiecare rezultat posibil al acestora.
Resursele asociate obiectului de tip JmDNS
trebuie eliberate în
momentul în care acesta nu mai este necesar (aplicația Android este
distrusă):
try {
if (jmDns != null) {
jmDns.close();
jmDns = null;
}
} catch (IOException ioException) {
Log.e(Constants.TAG, "An exception has occurred: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
În fișierul AndroidManifest.xml
, permisiunile care trebuie oferite
aplicației vizează:
- accesul la Internet;
- schimbarea politicii cu privire la procesarea pachetelor de tip multi-cast (implicit dezactivate, pentru a optimiza consumul de energie);
- accesul la starea rețelei fără fir;
- accesul la starea rețelei cu fir.
<manifest xmlns:android="http:*schemas.android.com/apk/res/android"
package="ro.pub.cs.systems.eim.lab09.chatservice"
android:versionCode="1"
android:versionName="1.0">
<uses-permission
android:name="android.permission.INTERNET"/>
<uses-permission
android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission
android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- ... -->
</manifest>