Non avendo a disposizione un telefono con Bluetooth 4.0 (od LE che si dica) ho provato a ricreare un sistema di prossimita' legato a Bluetooth che faccia un po' il verso a IBeacon e simili
Per simulare un IBeacon ed un ricevitore bisogna prevedere un trasmettitore BT sempre visibile ed un ricevitore che sai in grado di misurare la qualita' del segnale di ricezione senza la necessita' di un precedente accoppiamento con il trasmettitore
|
Esempio di scoperta Bluetoorh |
Android permette di calcolare la qualita' del segnale del ricevitore (RSSI) anche senza la necessita' di accoppiamento per tutte le versioni di Bluetooth mentre MacOSX e Linux permetto di essere impostati per avere bluetooth sempre visibile (senza timeout). Quindi c'e' tutto per fare la prova
Il programma per Android (prendendo come base
il seguente link) e' il seguente
AndroidManifest.xml
----------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.luca.innocenti.bttester"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.luca.innocenti.bttester.MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
----------------------------------------------------------
fragment_main.xml
----------------------------------------------------------
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.luca.innocenti.bttester.MainActivity$PlaceholderFragment" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp"
android:text="Ricerca" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/button1"
android:layout_centerHorizontal="true"
android:layout_marginTop="90dp"
android:text=" " />
</RelativeLayout>
----------------------------------------------------------
MainActivity.java
----------------------------------------------------------
package com.luca.innocenti.bttester;
import android.support.v7.app.ActionBarActivity;
import android.support.v4.app.Fragment;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
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.widget.Button;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
private static TextView rssi_msg;
private static BluetoothAdapter BTAdapter = BluetoothAdapter.getDefaultAdapter();
@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();
}
registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
private final BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)) {
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
rssi_msg.setText(rssi_msg.getText() + name + " => " + rssi + "dBm\n");
}
}
};
@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) {
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);
rssi_msg = (TextView) rootView.findViewById(R.id.textView1);
Button cerca= (Button) rootView.findViewById(R.id.button1);
cerca.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
BTAdapter.startDiscovery();
}
});
return rootView;
}
}
}
----------------------------------------------------------
A questo punto per completare l'opera e' sufficiente di richiamare la funzione startDiscovery all'interno di un timer e gestire un evento in funzione della qualita' del segnale e del nome dell'emettitore