Updated the UI to support the runing average

This commit is contained in:
Alexandros Schillings
2014-03-18 15:23:14 +00:00
parent 83ee1eab66
commit e2294ca926
8 changed files with 103 additions and 79 deletions
+3 -8
View File
@@ -17,11 +17,12 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:gravity="top"
android:orientation="horizontal" >
<ImageView
android:id="@+id/device_icon"
android:paddingTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dp"
@@ -57,12 +58,6 @@
android:layout_height="wrap_content"
android:textSize="12sp"
android:typeface="monospace" />
</GridLayout>
<GridLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:columnCount="4" >
<TextView
android:layout_width="wrap_content"
@@ -82,7 +77,6 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="@string/label_rssi"
android:textSize="12sp"
@@ -100,6 +94,7 @@
android:id="@+id/ibeacon_section"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/light_gray"
android:columnCount="4" >
<!-- ROW 1 -->
+3
View File
@@ -0,0 +1,3 @@
<resources>
<color name="light_gray">#e0e0e0</color>
</resources>
+6
View File
@@ -11,11 +11,17 @@
<string name="no_data">No data</string>
<string name="unknown_device">Unknown Device</string>
<!-- Formatters -->
<string name="formatter_meters">%sm</string>
<string name="formatter_db">%sdb</string>
<!-- Menu items -->
<string name="menu_connect">Connect</string>
<string name="menu_disconnect">Disconnect</string>
<string name="menu_scan">Scan</string>
<string name="menu_stop">Stop</string>
<!-- List Items -->
<string name="label_distance">Distance:</string>
<string name="label_tx_power">TX Power:</string>
<string name="label_minor">Minor:</string>
@@ -9,6 +9,7 @@ import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
import uk.co.alt236.btlescan.R;
import uk.co.alt236.btlescan.util.Constants;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
@@ -16,6 +17,7 @@ import butterknife.ButterKnife;
import butterknife.InjectView;
public class DetailsActivity extends Activity{
private static final String SECTION_LINE = "------------------------------";
public static final String EXTRA_DEVICE = "extra_device";
@InjectView(R.id.tvDetails) TextView mTvDetails;
@@ -33,6 +35,19 @@ public class DetailsActivity extends Activity{
pupulateDetails(mDevice);
}
private String formatTime(long time){
return android.text.format.DateFormat.format(
Constants.TIME_FORMAT, new java.util.Date(time)).toString();
}
private String formatRssi(int rssi){
return getString(R.string.formatter_db, String.valueOf(rssi));
}
private String formatRssi(double rssi){
return getString(R.string.formatter_db, String.valueOf(rssi));
}
private void pupulateDetails(BluetoothLeDevice device) {
final StringBuilder sb = new StringBuilder();
@@ -46,14 +61,24 @@ public class DetailsActivity extends Activity{
append(sb, "Device Class", device.getBluetoothDeviceClassName());
append(sb, "Bonding State", device.getBluetoothDeviceBondState());
append(sb, "", null);
append(sb, "RSSI Info", null);
append(sb, SECTION_LINE, null);
append(sb, "First Timestamp", formatTime(device.getFirstTimestamp()));
append(sb, "First RSSI", formatRssi(device.getFirstRssi()));
append(sb, "Current Timestamp", formatTime(device.getTimestamp()));
append(sb, "Current RSSI", formatRssi(device.getRssi()));
append(sb, "Running Average RSSI", formatRssi(device.getRunningAverageRssi()));
append(sb, "", null);
append(sb, "Scan Record", null);
append(sb, "-----------------", null);
append(sb, SECTION_LINE, null);
append(sb, device.getScanRecord());
append(sb, "", null);
append(sb, "Raw Ad Records As String", null);
append(sb, "-----------------", null);
append(sb, SECTION_LINE, null);
final Collection<AdRecord> adRecords = device.getAdRecordStore().getRecordsAsCollection();
@@ -65,14 +90,14 @@ public class DetailsActivity extends Activity{
}
append(sb, "Additional", null);
append(sb, "-----------------", null);
append(sb, SECTION_LINE, null);
final boolean isIBeacon = IBeaconUtils.isThisAnIBeacon(device);
append(sb, "Is iBeacon", isIBeacon);
if(isIBeacon){
final IBeaconManufacturerData iBeaconData = new IBeaconManufacturerData(device);
append(sb, "Company ID", iBeaconData.getCompanyIdentifier() + " (" + Integer.toHexString( iBeaconData.getCompanyIdentifier() ) + ")");
append(sb, "iBeacon Advertisment", iBeaconData.getIBeaconAdvertisement() + " (" + Integer.toHexString( iBeaconData.getIBeaconAdvertisement() ) + ")");
append(sb, "Advertisment", iBeaconData.getIBeaconAdvertisement() + " (" + Integer.toHexString( iBeaconData.getIBeaconAdvertisement() ) + ")");
append(sb, "UUID", iBeaconData.getUUID().toString());
append(sb, "Major", iBeaconData.getMajor() + " (" + Integer.toHexString( iBeaconData.getMajor() ) + ")");
append(sb, "Minor", iBeaconData.getMinor() + " (" + Integer.toHexString( iBeaconData.getMinor() ) + ")");
@@ -91,17 +116,25 @@ public class DetailsActivity extends Activity{
append(sb, label, String.valueOf(value));
}
private static void append(StringBuilder sb, String label, int value) {
append(sb, label, String.valueOf(value));
}
// private static void append(StringBuilder sb, String label, double value) {
// append(sb, label, String.valueOf(value));
// }
//
// private static void append(StringBuilder sb, String label, int value) {
// append(sb, label, String.valueOf(value));
// }
//
// private static void append(StringBuilder sb, String label, long value) {
// append(sb, label, String.valueOf(value));
// }
private static void append(StringBuilder sb, String label, long value) {
append(sb, label, String.valueOf(value));
public static String padRight(String s, int n) {
return String.format("%1$-" + n + "s", s);
}
private static void append(StringBuilder sb, String label, String value){
if(value != null){
sb.append("\u2022" + label +":\t" + value + "\n");
sb.append("\u2022" + padRight(label, 10) +":\t" + value + "\n");
} else {
sb.append(label + "\n");
}
@@ -1,11 +1,9 @@
package uk.co.alt236.btlescan.activities;
import java.util.ArrayList;
import java.util.List;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.btlescan.R;
import uk.co.alt236.btlescan.adapters.LeDeviceListAdapter;
import uk.co.alt236.btlescan.containers.BluetoothLeDeviceStore;
import uk.co.alt236.btlescan.util.BluetoothLeScanner;
import uk.co.alt236.btlescan.util.BluetoothUtils;
import uk.co.alt236.btlescan.views.RadarView;
@@ -30,10 +28,7 @@ public class MainActivity extends ListActivity {
private BluetoothUtils mBluetoothUtils;
private BluetoothLeScanner mScanner;
private LeDeviceListAdapter mLeDeviceListAdapter;
private List<BluetoothLeDevice> mDeviceList;
private BluetoothLeDeviceStore mDeviceStore;
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
@@ -44,17 +39,18 @@ public class MainActivity extends ListActivity {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapter.addDevice(deviceLe);
mDeviceStore.addDevice(deviceLe);
mLeDeviceListAdapter.clear();
mLeDeviceListAdapter.addAll(mDeviceStore.getDeviceList());
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final BluetoothLeDevice device = mLeDeviceListAdapter.getDevice(position);
final BluetoothLeDevice device = mLeDeviceListAdapter.getItem(position);
if (device == null) return;
@@ -69,8 +65,8 @@ public class MainActivity extends ListActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
mDeviceList = new ArrayList<BluetoothLeDevice>();
mDeviceStore = new BluetoothLeDeviceStore();
mBluetoothUtils = new BluetoothUtils(this);
mScanner = new BluetoothLeScanner(mLeScanCallback, mBluetoothUtils);
}
@@ -134,8 +130,9 @@ public class MainActivity extends ListActivity {
private void startScan(){
final boolean mIsBluetoothOn = mBluetoothUtils.isBluetoothOn();
final boolean mIsBluetoothLePresent = mBluetoothUtils.isBluetoothLeSupported();
mDeviceStore.clear();
mLeDeviceListAdapter = new LeDeviceListAdapter(this);
mLeDeviceListAdapter = new LeDeviceListAdapter(this, mDeviceStore.getDeviceList());
setListAdapter(mLeDeviceListAdapter);
mBluetoothUtils.askUserToEnableBluetoothIfNeeded();
@@ -1,60 +1,38 @@
package uk.co.alt236.btlescan.adapters;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.bluetoothlelib.device.IBeaconDevice;
import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
import uk.co.alt236.btlescan.R;
import uk.co.alt236.btlescan.util.Constants;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
// Adapter for holding devices found through scanning.
public class LeDeviceListAdapter extends BaseAdapter {
private static final DecimalFormat DOUBLE_TWO_DIGIT_ACCURACY = new DecimalFormat("#.##");
private static final String TIME_FORMAT = "yyyy-MM-dd hh:mm:ss";
private final List<BluetoothLeDevice> mLeDevices;
public class LeDeviceListAdapter extends ArrayAdapter<BluetoothLeDevice> {
private final LayoutInflater mInflator;
private final Activity mActivity;
public LeDeviceListAdapter(Activity activity) {
super();
mLeDevices = new ArrayList<BluetoothLeDevice>();
public LeDeviceListAdapter(Activity activity, List<BluetoothLeDevice> list) {
super(activity, R.layout.list_item_device, list);
mInflator = activity.getLayoutInflater();
mActivity = activity;
}
public void addDevice(BluetoothLeDevice device) {
final int position = mLeDevices.indexOf(device);
if(position == -1){
mLeDevices.add(device);
} else {
mLeDevices.set(position, device);
}
}
public BluetoothLeDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
@Override
public int getCount() {
return mLeDevices.size();
}
@Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
// public void addDevice(BluetoothLeDevice device) {
// final int position = mLeDevices.indexOf(device);
// if(position == -1){
// mLeDevices.add(device);
// } else {
// mLeDevices.set(position, device);
// }
// }
@Override
public long getItemId(int i) {
@@ -85,7 +63,7 @@ public class LeDeviceListAdapter extends BaseAdapter {
viewHolder = (ViewHolder) view.getTag();
}
final BluetoothLeDevice device = mLeDevices.get(i);
final BluetoothLeDevice device = getItem(i);
final String deviceName = device.getName();
final double rssi = device.getRssi();
@@ -96,11 +74,8 @@ public class LeDeviceListAdapter extends BaseAdapter {
}
if (IBeaconUtils.isThisAnIBeacon(device)){
// Alternatively you can just call
// IBeaconManufacturerData data = new IBeaconManufacturerData(device);
final IBeaconDevice iBeacon = new IBeaconDevice(device);
final double accuracy = iBeacon.getAccuracy();
final String accuracy = Constants.DOUBLE_TWO_DIGIT_ACCURACY.format(iBeacon.getAccuracy());
viewHolder.deviceIcon.setImageResource(R.drawable.ic_device_ibeacon);
viewHolder.ibeaconSection.setVisibility(View.VISIBLE);
@@ -108,17 +83,22 @@ public class LeDeviceListAdapter extends BaseAdapter {
viewHolder.ibeaconMinor.setText(String.valueOf(iBeacon.getMinor()));
viewHolder.ibeaconTxPower.setText(String.valueOf(iBeacon.getCalibratedTxPower()));
viewHolder.ibeaconUUID.setText(iBeacon.getUUID());
viewHolder.ibeaconDistance.setText(DOUBLE_TWO_DIGIT_ACCURACY.format(accuracy) + "m");
viewHolder.ibeaconDistance.setText(
mActivity.getString(R.string.formatter_meters, accuracy));
viewHolder.ibeaconDistanceDescriptor.setText(iBeacon.getDistanceDescriptor().toString());
} else {
viewHolder.deviceIcon.setImageResource(R.drawable.ic_bluetooth);
viewHolder.ibeaconSection.setVisibility(View.GONE);
}
final String rssiString = mActivity.getString(R.string.formatter_db, String.valueOf(rssi));
final String runningAverageRssiString = mActivity.getString(R.string.formatter_db, String.valueOf(device.getRunningAverageRssi()));
viewHolder.deviceLastUpdated.setText(
android.text.format.DateFormat.format(TIME_FORMAT, new java.util.Date(device.getTimestamp())));
android.text.format.DateFormat.format(
Constants.TIME_FORMAT, new java.util.Date(device.getTimestamp())));
viewHolder.deviceAddress.setText(device.getAddress());
viewHolder.deviceRssi.setText(String.valueOf(rssi) + "db");
viewHolder.deviceRssi.setText(rssiString + " / " + runningAverageRssiString);
return view;
}
@@ -1,4 +1,4 @@
package uk.co.alt236.btlescan.util;
package uk.co.alt236.btlescan.containers;
import java.util.ArrayList;
import java.util.Collections;
@@ -12,23 +12,26 @@ import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
public class BluetoothLeDeviceStore {
private final Map<String, BluetoothLeDevice> mDeviceMap;
public BluetoothLeDeviceStore(){
mDeviceMap = new HashMap<String, BluetoothLeDevice>();
}
public void addDevice(BluetoothLeDevice device){
if(mDeviceMap.containsKey(device.getAddress())){
mDeviceMap.get(device.getAddress()).updateRssiReading(device.getTimestamp(), device.getRssi());
} else {
mDeviceMap.put(device.getAddress(), device);
}
}
public void clear(){
mDeviceMap.clear();
}
public List<BluetoothLeDevice> getDeviceList(){
final List<BluetoothLeDevice> methodResult = new ArrayList<BluetoothLeDevice>(mDeviceMap.values());
Collections.sort(methodResult, new Comparator<BluetoothLeDevice>() {
@Override
@@ -37,7 +40,6 @@ public class BluetoothLeDeviceStore {
}
});
return methodResult;
}
}
@@ -0,0 +1,8 @@
package uk.co.alt236.btlescan.util;
import java.text.DecimalFormat;
public class Constants {
public static final DecimalFormat DOUBLE_TWO_DIGIT_ACCURACY = new DecimalFormat("#.##");
public static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
}