diff --git a/library/src/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java b/library/src/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java index 3f03cb2..5fcd915 100644 --- a/library/src/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java +++ b/library/src/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java @@ -66,7 +66,7 @@ public final class IBeaconManufacturerData { mUUID = calculateUUIDString(Arrays.copyOfRange(mData, 4, 20)); mMajor = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(mData, 20, 22)); mMinor = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(mData, 22, 24)); - mCalibratedTxPower = ByteUtils.getIntFromByte(data[24]); + mCalibratedTxPower = data[24]; } @@ -87,7 +87,7 @@ public final class IBeaconManufacturerData { return sb.toString(); } - public double getAccuracy(int rssi){ + public double getAccuracy(double rssi){ return calculateAccuracy(mCalibratedTxPower, rssi); } @@ -99,6 +99,22 @@ public final class IBeaconManufacturerData { return mCompanyIdentidier; } + public String getDistanceDescriptor(double accuracy){ + if(accuracy < 0){ + return "WTF"; + } + + if(accuracy < 0.5){ + return "IMMEDIATE"; + } + + if(accuracy < 3.0){ + return "NEAR"; + } + + return "FAR"; + } + public int getIBeaconAdvertisement(){ return mIBeaconAdvertisment; } @@ -116,7 +132,7 @@ public final class IBeaconManufacturerData { } // Code taken from: http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing - protected static double calculateAccuracy(int txPower, double rssi) { + private static double calculateAccuracy(int txPower, double rssi) { if (rssi == 0) { return -1.0; // if we cannot determine accuracy, return -1. } diff --git a/sample_app/res/layout/list_item_device.xml b/sample_app/res/layout/list_item_device.xml index acd990e..1f46b15 100644 --- a/sample_app/res/layout/list_item_device.xml +++ b/sample_app/res/layout/list_item_device.xml @@ -48,7 +48,8 @@ android:layout_height="wrap_content" android:paddingRight="5dp" android:text="@string/label_mac" - android:textSize="12sp" /> + android:textSize="12sp" + android:textStyle="bold" /> + android:textSize="12sp" + android:textStyle="bold" /> + android:textSize="12sp" + android:textStyle="bold" /> + android:textSize="12sp" + android:textStyle="bold" /> + android:textSize="12sp" + android:textStyle="bold" /> + android:textSize="12sp" + android:textStyle="bold" /> + android:textSize="12sp" + android:textStyle="bold" /> mLeDevices; - private final LayoutInflater mInflator; +// Adapter for holding devices found through scanning. +public class LeDeviceListAdapter extends BaseAdapter { + private static final DecimalFormat DOUBLE_TWO_DIGIT_ACCURACY = new DecimalFormat("#.##"); - public LeDeviceListAdapter(Activity activity) { - super(); - mLeDevices = new ArrayList(); - mInflator = activity.getLayoutInflater(); - } + private final List mLeDevices; + private final LayoutInflater mInflator; - public void addDevice(BluetoothLeDevice device) { - final int position = mLeDevices.indexOf(device); - if(position == -1){ - mLeDevices.add(device); - } else { - mLeDevices.set(position, device); - } - } + public LeDeviceListAdapter(Activity activity) { + super(); + mLeDevices = new ArrayList(); + mInflator = activity.getLayoutInflater(); + } - public BluetoothLeDevice getDevice(int position) { - return mLeDevices.get(position); - } + public void addDevice(BluetoothLeDevice device) { + final int position = mLeDevices.indexOf(device); + if(position == -1){ + mLeDevices.add(device); + } else { + mLeDevices.set(position, device); + } + } - public void clear() { - mLeDevices.clear(); - } + public BluetoothLeDevice getDevice(int position) { + return mLeDevices.get(position); + } - @Override - public int getCount() { - return mLeDevices.size(); - } + public void clear() { + mLeDevices.clear(); + } - @Override - public Object getItem(int i) { - return mLeDevices.get(i); - } + @Override + public int getCount() { + return mLeDevices.size(); + } - @Override - public long getItemId(int i) { - return i; - } + @Override + public Object getItem(int i) { + return mLeDevices.get(i); + } - @Override - public View getView(int i, View view, ViewGroup viewGroup) { - ViewHolder viewHolder; - // General ListView optimization code. - if (view == null) { - view = mInflator.inflate(R.layout.list_item_device, null); - viewHolder = new ViewHolder(); - viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address); - viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name); - viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi); - viewHolder.deviceIcon = (ImageView) view.findViewById(R.id.device_icon); - viewHolder.ibeaconMajor = (TextView) view.findViewById(R.id.ibeacon_major); - viewHolder.ibeaconMinor = (TextView) view.findViewById(R.id.ibeacon_minor); - viewHolder.ibeaconDistance = (TextView) view.findViewById(R.id.ibeacon_distance); - viewHolder.ibeaconUUID = (TextView) view.findViewById(R.id.ibeacon_uuid); - viewHolder.ibeaconTxPower = (TextView) view.findViewById(R.id.ibeacon_tx_power); - viewHolder.ibeaconSection = (View) view.findViewById(R.id.ibeacon_section); - view.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) view.getTag(); - } + @Override + public long getItemId(int i) { + return i; + } - final BluetoothLeDevice device = mLeDevices.get(i); - final String deviceName = device.getName(); + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + ViewHolder viewHolder; + // General ListView optimization code. + if (view == null) { + view = mInflator.inflate(R.layout.list_item_device, null); + viewHolder = new ViewHolder(); + viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address); + viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name); + viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi); + viewHolder.deviceIcon = (ImageView) view.findViewById(R.id.device_icon); + viewHolder.ibeaconMajor = (TextView) view.findViewById(R.id.ibeacon_major); + viewHolder.ibeaconMinor = (TextView) view.findViewById(R.id.ibeacon_minor); + viewHolder.ibeaconDistance = (TextView) view.findViewById(R.id.ibeacon_distance); + viewHolder.ibeaconUUID = (TextView) view.findViewById(R.id.ibeacon_uuid); + viewHolder.ibeaconTxPower = (TextView) view.findViewById(R.id.ibeacon_tx_power); + viewHolder.ibeaconSection = (View) view.findViewById(R.id.ibeacon_section); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } - if (deviceName != null && deviceName.length() > 0){ - viewHolder.deviceName.setText(deviceName); - } else{ - viewHolder.deviceName.setText(R.string.unknown_device); - } + final BluetoothLeDevice device = mLeDevices.get(i); + final String deviceName = device.getName(); + final double rssi = device.getRssi(); - if (IBeaconUtils.isThisAnIBeacon(device)){ - final IBeaconManufacturerData data = new IBeaconManufacturerData(device); - viewHolder.deviceIcon.setImageResource(R.drawable.ic_device_ibeacon); - viewHolder.ibeaconSection.setVisibility(View.VISIBLE); - viewHolder.ibeaconMajor.setText(String.valueOf(data.getMajor())); - viewHolder.ibeaconMinor.setText(String.valueOf(data.getMinor())); - viewHolder.ibeaconTxPower.setText(String.valueOf(data.getCalibratedTxPower())); - viewHolder.ibeaconUUID.setText(data.getUUID()); - viewHolder.ibeaconDistance.setText(String.valueOf(data.getAccuracy(device.getRssi()))); - } else { - viewHolder.deviceIcon.setImageResource(R.drawable.ic_bluetooth); - viewHolder.ibeaconSection.setVisibility(View.GONE); - } + if (deviceName != null && deviceName.length() > 0){ + viewHolder.deviceName.setText(deviceName); + } else{ + viewHolder.deviceName.setText(R.string.unknown_device); + } - viewHolder.deviceAddress.setText(device.getAddress()); - viewHolder.deviceRssi.setText(String.valueOf(device.getRssi()) + "db"); - return view; - } + if (IBeaconUtils.isThisAnIBeacon(device)){ + final IBeaconManufacturerData data = new IBeaconManufacturerData(device); + final double accuracy = data.getAccuracy(rssi); - static class ViewHolder { - TextView deviceName; - TextView deviceAddress; - TextView deviceRssi; - TextView ibeaconUUID; - TextView ibeaconMajor; - TextView ibeaconMinor; - TextView ibeaconTxPower; - TextView ibeaconDistance; - View ibeaconSection; - ImageView deviceIcon; - } + viewHolder.deviceIcon.setImageResource(R.drawable.ic_device_ibeacon); + viewHolder.ibeaconSection.setVisibility(View.VISIBLE); + viewHolder.ibeaconMajor.setText(String.valueOf(data.getMajor())); + viewHolder.ibeaconMinor.setText(String.valueOf(data.getMinor())); + viewHolder.ibeaconTxPower.setText(String.valueOf(data.getCalibratedTxPower())); + viewHolder.ibeaconUUID.setText(data.getUUID()); + viewHolder.ibeaconDistance.setText( + DOUBLE_TWO_DIGIT_ACCURACY.format(accuracy) + "m " + data.getDistanceDescriptor(accuracy)); + } else { + viewHolder.deviceIcon.setImageResource(R.drawable.ic_bluetooth); + viewHolder.ibeaconSection.setVisibility(View.GONE); + } - } \ No newline at end of file + viewHolder.deviceAddress.setText(device.getAddress()); + viewHolder.deviceRssi.setText(String.valueOf(rssi) + "db"); + return view; + } + + static class ViewHolder { + TextView deviceName; + TextView deviceAddress; + TextView deviceRssi; + TextView ibeaconUUID; + TextView ibeaconMajor; + TextView ibeaconMinor; + TextView ibeaconTxPower; + TextView ibeaconDistance; + View ibeaconSection; + ImageView deviceIcon; + } + +} \ No newline at end of file