mercoledì 30 aprile 2014

Errore Lint su esportazione di una applicazione Android

Al momento di esportare una applicazione da Eclipse mediante Android Tools, Lint ha deciso che per fare il suo lavoro dovevo effettuare la traduzione delle stringhe in tutte le lingue del mondo


Per ovviare al problema si puo' andare Window/Preference/Lint Error Checking e modificare l'errore Missing Translation da una Severity Fatal ad una Serverity Warning

Hotspot e Bluetooth su Android

Ed ecco che ho sperimentato un bel bug di Android. Usando contemporaneamente l'HotSpot WiFi e Bluetooth sul Motorola Moto G con Android KitKat 4.4.2 il sistema operativo interrompe la funzione HotSpot



Questo bug e' descritto in https://code.google.com/p/android/issues/detail?id=41631 e sembra che non sia presente un Android 4.3



Fluttuazione del segnale IBeacon


Iniziando a lavorare con le libreria IBeacon di Radius si nota chiaramente che i valori di distanza sono molto variabili ed ho fatto una piccolo test con una applicazione misurando (a geometria fissa quindi con la distanza tra IBeacon e telefono fissa) i valori getAccuracy


I risultati (48 misure per circa un minuto di test) sono riportati nel grafico soprastante. Il valore medio e' stato di 0.3 (i valori delle ordinate del grafico sono moltiplicate per 100) ma con una oscillazione massima di 1.01 e minima di 0.09. In definitiva la deviazione standard e' della stessa dimensione del valore medio

Cio' crea ovviamente problemi nella gestione della prossimita' al beacon

Il codice dell'applicazione puo' essere scaricato a questo indirizzo

lunedì 28 aprile 2014

April Beacon

Il dispositivo che mi sono trovato a testare e' un AprilBeacon 201 ai aprbrother.com basato sul modulo CC2540 BLE


L'alimentazione e' data da una pila CR2450 (da comprare a parte). Il modello e' completamente configurabile ed oltre a poter cambiare l'UUID (di default e' quello di test di Apple) e' possibile anche variare il Major e Minor Number la potenza di trasmissione

Usando la app AprilBeacon su Google Play si possono visualizzare i parametri di esercizio (per effettuare tale operazione si deve inserire il pin che e' 19566)

dalla applicazione si puo' vedere il livello della batteria, la potenza del segnale e le informazioni sul firmware



Al contrario dell'applicazione IOS (che si scarica da qui) non e' possibile modificare l'UUID. Il customer care della ditta dice che tale funzionalita' sara' disponibile tra circa un mese






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;
}
}
}

iBeacon con Linux, Yun e Raspberry


Trasformare un dispositivo basato su Linux in un IBeacon e' piuttosto semplice
Per prima cosa si deve avere un dongle USB Bluetooth LTE 4.0
La preparazione e' differente per i dispositivi ma una volta che sono installate le librerie BT i comandi successivi sono comunu

Preparazione Arduino YUN
Per trasformare Arduino Yun in un IBeacon si possono seguire le istruzioni a questo link
Una volta collegati in shell SSH con Yun si digitano i seguenti comandi per installare lo stack bluetooth

opkg update 
opkg install kmod-bluetooth
(Yun non ha abilitato SFTP e quindi e' meglio scaricare il file direttamente su Yun)
wget http://fibasile.github.io/images/arduino-yun-ibeacon/bluez_5.13-1_ar71xx.ipk
opkg install bluez_5.13-1_ar71xx.ipk



Preparazione Linux (Ubuntu 12.04) e Raspberry PI

In questo caso si deve aggiornare la libreria BT si default scaricando i sorgenti 
Si scarica quindi la libreria da qui (o versione successiva)

wget www.kernel.org/pub/linux/bluetooth/bluez-5.11.tar.gz (attualmente la piu' recente e' 5.18)

si compila con il classico 
configure --disable-systemd
make
make install 
soddisfacendo le dipendenze. Io ho dovuto eseguire 
apt-get  install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev





Parte Comune

da qui in poi i comandi sono comuni

hciconfig hci0 up
hciconfig hci0 leadv
hciconfig hci0 noscan
hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A 
FF 4C 00 02 15 E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 00 00 00 C8 00


dove la sintassi dell'ultimo comando e' la seguente 
hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 <UUID> <MAJOR> <MINOR> <POWER> 00

a questo punto il beacon e' rilevabile

giovedì 24 aprile 2014

Listview cliccabile su Android

Un esempio minimale di Listview cliccabile su Android che funziona sui Fragment





--------------------------------------------------------------
package com.example.lista;

import java.util.ArrayList;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {
public static ListView lista;

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

@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
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

/**
* A placeholder fragment containing a simple view.
*/
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);


lista = (ListView) rootView.findViewById(R.id.listView1);

       String[] cognome = new String[] { "Innocenti", "Scialla", "Parauda" };
      
       final ArrayList <String> listp = new ArrayList<String>();  
       for (int i = 0; i < cognome.length; ++i) {  
            listp.add(cognome[i]);  
       }  
       ArrayAdapter <String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, listp);  
       lista.setAdapter(adapter);
       
       lista.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
   Toast.makeText(getActivity(),((TextView) view).getText(), Toast.LENGTH_SHORT).show();

}
});
return rootView;
}
}

}



Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...