Updated the UI to support the runing average
This commit is contained in:
@@ -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 -->
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<color name="light_gray">#e0e0e0</color>
|
||||
</resources>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -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";
|
||||
}
|
||||
Reference in New Issue
Block a user