lunedì 28 aprile 2014

IBeacon con Radius Library

Per provare IBeacon su Android vale decisamente la pena di scaricare la libreria di Radius Networks http://developer.radiusnetworks.com/ibeacon/android/pro/download.html (esiste una versione open ed una pro a pagamento)


Attenzione: non si tratta del medesimo dispositivo listato due volte ma due IBeacon che condividono lo stesso UUID di prova
Per iniziare ad usare la libreria AndroidBeaconLibrary bisogna importarla in Eclipse come un normale progetto Android mediante File/Import/ExistingAndroidCode

A questo punto si crea un nuovo progetto Applicazione Android in cui si deve impostare la versione di Android ad almeno la nr 18 (Android 4.3 JellyBean)  e si aggiungono i seguenti permessi al Manifest

<uses-permission android:name="android.permission.BLUETOOTH"/> 
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

dopo al file project.properties si aggiunge

manifestmerger.enabled=true

a questo punto e' meglio fare fare Project/Clean, Project/Refresh

e si possono usare gli esempi riportati a questa pagina
http://developer.radiusnetworks.com/ibeacon/android/samples.html
(vedi sotto)

Se non si ha un iBeacon reale si puo' simulare mediante la macchina virtuale Virtualbox messa a disposizione sempre da Radius

Io ho utilizzato un dongle bluetooth 4 Broadcom BCM920702 che deve collegato alla macchina virtuale tra i dispositivi USB. Al termine del boot compare qualcosa di simile


Premedo un tasto si accede alla shell
Il servizio IBeacon si avvia e si stoppa con i comandi "start" e "stop". Nella directory di root si trova il file di configurazione ibeacon.conf che permette di  modificare i parametri.
Attenzione : di default la macchina virtuale ha un UUID di E2C56DB5-DFFB-48D2-B060-D0F5A71096E0 che e' quello di test come definito da Apple

Di seguito l'esempio Ranging. Ho effettuato una modifica (indicata in giallo) perche' cosi' come proposto da Radius il programma identifica solo il primo iBeacon che riesce a vedere mentre iterando la Collection si possono ottenere le informazioni di tutti gli iBeacon visibili
---------------------------------------------------
package com.example.ibea;
import java.util.Collection;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import com.radiusnetworks.ibeacon.IBeacon;
import com.radiusnetworks.ibeacon.IBeaconConsumer;
import com.radiusnetworks.ibeacon.IBeaconManager;
import com.radiusnetworks.ibeacon.Region;
import com.radiusnetworks.ibeacon.RangeNotifier;

public class MainActivity extends Activity {

private IBeaconManager iBeaconManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
       getFragmentManager().beginTransaction()
     .add(R.id.container, new PlaceholderFragment()).commit();
}
iBeaconManager.bind((IBeaconConsumer) this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
protected void onDestroy() {
super.onDestroy();
iBeaconManager.unBind((IBeaconConsumer) this);
}

public void onIBeaconServiceConnect() {
iBeaconManager.setRangeNotifier(new RangeNotifier() {

@Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons,Region arg1) {
if (iBeacons.size() > 0) {
    for (IBeacon iBeacon : iBeacons) {                              
              Log.d(TAG,iBeacon.getProximityUuid()+"  -  "+iBeacon.getAccuracy());

               }
   }
}
});
try {
iBeaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
} catch (RemoteException e) { }
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
}