diff --git a/library/library.iml b/library/library.iml
index eccbfd6..6040fb7 100644
--- a/library/library.iml
+++ b/library/library.iml
@@ -65,14 +65,6 @@
-
-
-
-
-
-
-
-
@@ -81,6 +73,14 @@
+
+
+
+
+
+
+
+
diff --git a/sample_app/build.gradle b/sample_app/build.gradle
index f2f4905..315c5ae 100644
--- a/sample_app/build.gradle
+++ b/sample_app/build.gradle
@@ -13,12 +13,16 @@ repositories {
maven {
url "https://repo.commonsware.com.s3.amazonaws.com"
}
+
+ maven {
+ url "https://s3.amazonaws.com/repo.commonsware.com"
+ }
}
dependencies {
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.android.support:appcompat-v7:24.2.0'
- compile 'com.commonsware.cwac:merge:1.1.0'
+ compile 'com.android.support:recyclerview-v7:24.2.0'
compile 'com.anthonycr.grant:permissions:1.0'
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':library')
diff --git a/sample_app/sample_app.iml b/sample_app/sample_app.iml
index 3685686..fa79116 100644
--- a/sample_app/sample_app.iml
+++ b/sample_app/sample_app.iml
@@ -88,6 +88,7 @@
+
@@ -96,8 +97,6 @@
-
-
@@ -106,7 +105,6 @@
-
@@ -121,6 +119,7 @@
+
@@ -131,8 +130,6 @@
-
-
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseRecyclerViewAdapter.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseRecyclerViewAdapter.java
new file mode 100644
index 0000000..6bf83dc
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseRecyclerViewAdapter.java
@@ -0,0 +1,55 @@
+package uk.co.alt236.btlescan.ui.common.recyclerview;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.ViewGroup;
+
+import java.util.List;
+
+public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter> {
+
+ private final List extends RecyclerViewItem> mItemList;
+ private final RecyclerViewBinderCore mCore;
+
+ public BaseRecyclerViewAdapter(final RecyclerViewBinderCore core,
+ final List items) {
+ mItemList = items;
+ mCore = core;
+ }
+
+ private static void bind(final BaseViewBinder binder,
+ final BaseViewHolder> holder,
+ final RecyclerViewItem item) {
+
+ //noinspection unchecked
+ binder.bind((BaseViewHolder) holder, (T) item);
+ }
+
+ @Override
+ public BaseViewHolder extends RecyclerViewItem> onCreateViewHolder(final ViewGroup parent,
+ final int viewType) {
+ return mCore.create(parent, viewType);
+ }
+
+ @Override
+ public void onBindViewHolder(final BaseViewHolder extends RecyclerViewItem> holder,
+ final int position) {
+
+ final int viewType = getItemViewType(position);
+ final BaseViewBinder extends RecyclerViewItem> binder = mCore.getBinder(viewType);
+ bind(binder, holder, getItem(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return mItemList.size();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mCore.getViewType(getItem(position));
+ }
+
+ public RecyclerViewItem getItem(final int position) {
+ return mItemList.get(position);
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewBinder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewBinder.java
new file mode 100644
index 0000000..ef4b23c
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewBinder.java
@@ -0,0 +1,20 @@
+package uk.co.alt236.btlescan.ui.common.recyclerview;
+
+import android.content.Context;
+
+public abstract class BaseViewBinder {
+
+ private final Context mContext;
+
+ public BaseViewBinder(final Context context) {
+ mContext = context;
+ }
+
+ public abstract void bind(BaseViewHolder holder, T item);
+
+ public abstract boolean canBind(RecyclerViewItem item);
+
+ protected Context getContext() {
+ return mContext;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewHolder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewHolder.java
new file mode 100644
index 0000000..b8617c6
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewHolder.java
@@ -0,0 +1,18 @@
+package uk.co.alt236.btlescan.ui.common.recyclerview;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
+
+ private final View mItemView;
+
+ public BaseViewHolder(final View itemView) {
+ super(itemView);
+ mItemView = itemView;
+ }
+
+ public View getView() {
+ return mItemView;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewBinderCore.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewBinderCore.java
new file mode 100644
index 0000000..c76983d
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewBinderCore.java
@@ -0,0 +1,93 @@
+package uk.co.alt236.btlescan.ui.common.recyclerview;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RecyclerViewBinderCore {
+ public static final int INVALID_VIEWTYPE = -1;
+
+ private final List>> mViewHolderClasses;
+ private final List> mViewBinders;
+ private final List mLayoutIds;
+
+ public RecyclerViewBinderCore() {
+ mViewBinders = new ArrayList<>();
+ mViewHolderClasses = new ArrayList<>();
+ mLayoutIds = new ArrayList<>();
+ }
+
+ public void clear() {
+ mViewBinders.clear();
+ mViewHolderClasses.clear();
+ mLayoutIds.clear();
+ }
+
+ public void add(
+ final BaseViewBinder binder,
+ final Class extends BaseViewHolder> viewHolder,
+ final int layoutId) {
+
+ mViewBinders.add(binder);
+ mViewHolderClasses.add(viewHolder);
+ mLayoutIds.add(layoutId);
+ }
+
+ public BaseViewHolder extends RecyclerViewItem> create(ViewGroup parent, final int viewType) {
+ if (viewType == INVALID_VIEWTYPE) {
+ throw new IllegalArgumentException("Invalid viewType: " + viewType);
+ }
+
+ final Class> clazz = mViewHolderClasses.get(viewType);
+ final int layoutId = mLayoutIds.get(viewType);
+ final View itemView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
+
+ return (BaseViewHolder extends RecyclerViewItem>) instantiate(clazz, itemView);
+ }
+
+ public int getViewType(final T item) {
+ int result = INVALID_VIEWTYPE;
+ int count = 0;
+
+ for (final BaseViewBinder extends RecyclerViewItem> binder : mViewBinders) {
+
+ if (binder.canBind(item)) {
+ result = count;
+ break;
+ }
+
+ count++;
+ }
+
+ return result;
+ }
+
+ public BaseViewBinder extends RecyclerViewItem> getBinder(int viewType) {
+ if (viewType == INVALID_VIEWTYPE) {
+ throw new IllegalArgumentException("Invalid viewType: " + viewType);
+ }
+
+ return mViewBinders.get(viewType);
+ }
+
+ @SuppressWarnings("TryWithIdenticalCatches")
+ private static Object instantiate(
+ final Class> clazz, View parentView) {
+ try {
+ final Constructor> constructor
+ = clazz.getDeclaredConstructors()[0];
+ return constructor.newInstance(parentView);
+ } catch (InstantiationException e) {
+ throw new IllegalStateException(e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewItem.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewItem.java
new file mode 100644
index 0000000..32b5df9
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewItem.java
@@ -0,0 +1,4 @@
+package uk.co.alt236.btlescan.ui.common.recyclerview;
+
+public interface RecyclerViewItem {
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/control/DeviceControlActivity.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/control/DeviceControlActivity.java
index aadb9fa..98ce4ca 100644
--- a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/control/DeviceControlActivity.java
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/control/DeviceControlActivity.java
@@ -55,7 +55,7 @@ import uk.co.alt236.btlescan.services.BluetoothLeService;
* Bluetooth LE API.
*/
public class DeviceControlActivity extends AppCompatActivity {
- public static final String EXTRA_DEVICE = "extra_device";
+ public static final String EXTRA_DEVICE = DeviceControlActivity.class.getName() + ".EXTRA_DEVICE";
private final static String TAG = DeviceControlActivity.class.getSimpleName();
private static final String LIST_NAME = "NAME";
private static final String LIST_UUID = "UUID";
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DetailsRecyclerAdapter.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DetailsRecyclerAdapter.java
new file mode 100644
index 0000000..fa094a5
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DetailsRecyclerAdapter.java
@@ -0,0 +1,25 @@
+package uk.co.alt236.btlescan.ui.details;
+
+import java.util.List;
+
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseRecyclerViewAdapter;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewBinderCore;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+
+/*package*/ class DetailsRecyclerAdapter extends BaseRecyclerViewAdapter {
+ public DetailsRecyclerAdapter(RecyclerViewBinderCore core, List items) {
+ super(core, items);
+ }
+
+// private static List validate(RecyclerViewBinderCore core, List items) {
+// final List retVal = new ArrayList<>();
+//
+// for (final RecyclerViewItem item : items) {
+// if (core.getViewType(item) != RecyclerViewBinderCore.INVALID_VIEWTYPE) {
+// retVal.add(item);
+// }
+// }
+//
+// return retVal;
+// }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DeviceDetailsActivity.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DeviceDetailsActivity.java
index 585411b..5a8a68a 100644
--- a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DeviceDetailsActivity.java
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DeviceDetailsActivity.java
@@ -2,172 +2,50 @@ package uk.co.alt236.btlescan.ui.details;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import com.commonsware.cwac.merge.MergeAdapter;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.Locale;
+import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
-import uk.co.alt236.bluetoothlelib.device.BluetoothService;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconManufacturerData;
-import uk.co.alt236.bluetoothlelib.resolvers.CompanyIdentifierResolver;
-import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewBinderCore;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
import uk.co.alt236.btlescan.ui.control.DeviceControlActivity;
-import uk.co.alt236.btlescan.util.TimeFormatter;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.AdRecordItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.DeviceInfoItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.HeaderItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.IBeaconItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.RssiItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.TextItem;
public class DeviceDetailsActivity extends AppCompatActivity {
- public static final String EXTRA_DEVICE = "extra_device";
- @Bind(android.R.id.list)
- protected ListView mList;
- @Nullable
- @Bind(android.R.id.empty)
- protected View mEmpty;
+ public static final String EXTRA_DEVICE = DeviceDetailsActivity.class.getName() + ".EXTRA_DEVICE";
+ private static final int LAYOUT_ID = R.layout.activity_details;
+
+ @Bind(R.id.recycler)
+ protected RecyclerView mRecycler;
private BluetoothLeDevice mDevice;
- private void appendAdRecordView(final MergeAdapter adapter, final String title, final AdRecord record) {
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_adrecord, null);
- final TextView tvString = (TextView) lt.findViewById(R.id.data_as_string);
- final TextView tvArray = (TextView) lt.findViewById(R.id.data_as_array);
- final TextView tvTitle = (TextView) lt.findViewById(R.id.title);
-
- tvTitle.setText(title);
-
- tvString.setText(getString(R.string.formatter_single_quoted_string,
- AdRecordUtils.getRecordDataAsString(record)));
- tvArray.setText(getString(R.string.formatter_single_quoted_string,
- ByteUtils.byteArrayToHexString(record.getData())));
-
- adapter.addView(lt);
- }
-
- private void appendDeviceInfo(final MergeAdapter adapter, final BluetoothLeDevice device) {
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_device_info, null);
- final TextView tvName = (TextView) lt.findViewById(R.id.deviceName);
- final TextView tvAddress = (TextView) lt.findViewById(R.id.deviceAddress);
- final TextView tvClass = (TextView) lt.findViewById(R.id.deviceClass);
- final TextView tvMajorClass = (TextView) lt.findViewById(R.id.deviceMajorClass);
- final TextView tvServices = (TextView) lt.findViewById(R.id.deviceServiceList);
- final TextView tvBondingState = (TextView) lt.findViewById(R.id.deviceBondingState);
-
- tvName.setText(device.getName());
- tvAddress.setText(device.getAddress());
- tvClass.setText(device.getBluetoothDeviceClassName());
- tvMajorClass.setText(device.getBluetoothDeviceMajorClassName());
- tvBondingState.setText(device.getBluetoothDeviceBondState());
-
- final String supportedServices;
- if (device.getBluetoothDeviceKnownSupportedServices().isEmpty()) {
- supportedServices = getString(R.string.no_known_services);
- } else {
- final StringBuilder sb = new StringBuilder();
-
- for (final BluetoothService service : device.getBluetoothDeviceKnownSupportedServices()) {
- if (sb.length() > 0) {
- sb.append(", ");
- }
-
- sb.append(service);
- }
- supportedServices = sb.toString();
- }
-
- tvServices.setText(supportedServices);
-
- adapter.addView(lt);
- }
-
- private void appendHeader(final MergeAdapter adapter, final String title) {
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_header, null);
- final TextView tvTitle = (TextView) lt.findViewById(R.id.title);
- tvTitle.setText(title);
-
- adapter.addView(lt);
- }
-
- private void appendIBeaconInfo(final MergeAdapter adapter, final IBeaconManufacturerData iBeaconData) {
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_ibeacon_details, null);
- final TextView tvCompanyId = (TextView) lt.findViewById(R.id.companyId);
- final TextView tvAdvert = (TextView) lt.findViewById(R.id.advertisement);
- final TextView tvUUID = (TextView) lt.findViewById(R.id.uuid);
- final TextView tvMajor = (TextView) lt.findViewById(R.id.major);
- final TextView tvMinor = (TextView) lt.findViewById(R.id.minor);
- final TextView tvTxPower = (TextView) lt.findViewById(R.id.txpower);
-
- tvCompanyId.setText(
- CompanyIdentifierResolver.getCompanyName(iBeaconData.getCompanyIdentifier(), getString(R.string.unknown))
- + " (" + hexEncode(iBeaconData.getCompanyIdentifier()) + ")");
- tvAdvert.setText(iBeaconData.getIBeaconAdvertisement() + " (" + hexEncode(iBeaconData.getIBeaconAdvertisement()) + ")");
- tvUUID.setText(iBeaconData.getUUID());
- tvMajor.setText(iBeaconData.getMajor() + " (" + hexEncode(iBeaconData.getMajor()) + ")");
- tvMinor.setText(iBeaconData.getMinor() + " (" + hexEncode(iBeaconData.getMinor()) + ")");
- tvTxPower.setText(iBeaconData.getCalibratedTxPower() + " (" + hexEncode(iBeaconData.getCalibratedTxPower()) + ")");
-
- adapter.addView(lt);
- }
-
- private void appendRssiInfo(final MergeAdapter adapter, final BluetoothLeDevice device) {
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_rssi_info, null);
- final TextView tvFirstTimestamp = (TextView) lt.findViewById(R.id.firstTimestamp);
- final TextView tvFirstRssi = (TextView) lt.findViewById(R.id.firstRssi);
- final TextView tvLastTimestamp = (TextView) lt.findViewById(R.id.lastTimestamp);
- final TextView tvLastRssi = (TextView) lt.findViewById(R.id.lastRssi);
- final TextView tvRunningAverageRssi = (TextView) lt.findViewById(R.id.runningAverageRssi);
-
- tvFirstTimestamp.setText(formatTime(device.getFirstTimestamp()));
- tvFirstRssi.setText(formatRssi(device.getFirstRssi()));
- tvLastTimestamp.setText(formatTime(device.getTimestamp()));
- tvLastRssi.setText(formatRssi(device.getRssi()));
- tvRunningAverageRssi.setText(formatRssi(device.getRunningAverageRssi()));
-
- adapter.addView(lt);
- }
-
- private void appendSimpleText(final MergeAdapter adapter, final byte[] data) {
- appendSimpleText(adapter, ByteUtils.byteArrayToHexString(data));
- }
-
- private void appendSimpleText(final MergeAdapter adapter, final String data) {
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_textview, null);
- final TextView tvData = (TextView) lt.findViewById(R.id.data);
-
- tvData.setText(data);
-
- adapter.addView(lt);
- }
-
-
- private String formatRssi(final double rssi) {
- return getString(R.string.formatter_db, String.valueOf(rssi));
- }
-
- private String formatRssi(final int rssi) {
- return getString(R.string.formatter_db, String.valueOf(rssi));
- }
-
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_details);
+ setContentView(LAYOUT_ID);
ButterKnife.bind(this);
- mList.setEmptyView(mEmpty);
-
+ mRecycler.setLayoutManager(new LinearLayoutManager(this));
mDevice = getIntent().getParcelableExtra(EXTRA_DEVICE);
pupulateDetails(mDevice);
@@ -195,50 +73,44 @@ public class DeviceDetailsActivity extends AppCompatActivity {
}
private void pupulateDetails(final BluetoothLeDevice device) {
- final MergeAdapter adapter = new MergeAdapter();
+ final DetailsRecyclerAdapter detailsRecyclerAdapter;
+
+ final List list = new ArrayList<>();
if (device == null) {
- appendHeader(adapter, getString(R.string.header_device_info));
- appendSimpleText(adapter, getString(R.string.invalid_device_data));
+ list.add(new HeaderItem(getString(R.string.header_device_info)));
+ list.add(new TextItem(getString(R.string.invalid_device_data)));
} else {
- appendHeader(adapter, getString(R.string.header_device_info));
- appendDeviceInfo(adapter, device);
+ list.add(new HeaderItem(getString(R.string.header_device_info)));
+ list.add(new DeviceInfoItem(device));
- appendHeader(adapter, getString(R.string.header_rssi_info));
- appendRssiInfo(adapter, device);
+ list.add(new HeaderItem(getString(R.string.header_rssi_info)));
+ list.add(new RssiItem(device));
- appendHeader(adapter, getString(R.string.header_scan_record));
- appendSimpleText(adapter, device.getScanRecord());
+ list.add(new HeaderItem(getString(R.string.header_scan_record)));
+ list.add(new TextItem(ByteUtils.byteArrayToHexString(device.getScanRecord())));
final Collection adRecords = device.getAdRecordStore().getRecordsAsCollection();
if (adRecords.size() > 0) {
- appendHeader(adapter, getString(R.string.header_raw_ad_records));
+ list.add(new HeaderItem(getString(R.string.header_raw_ad_records)));
for (final AdRecord record : adRecords) {
- appendAdRecordView(
- adapter,
- "#" + record.getType() + " " + record.getHumanReadableType(),
- record);
+ final String title = "#" + record.getType() + " " + record.getHumanReadableType();
+ list.add(new AdRecordItem(title, record));
}
}
final boolean isIBeacon = BeaconUtils.getBeaconType(device) == BeaconType.IBEACON;
if (isIBeacon) {
final IBeaconManufacturerData iBeaconData = new IBeaconManufacturerData(device);
- appendHeader(adapter, getString(R.string.header_ibeacon_data));
- appendIBeaconInfo(adapter, iBeaconData);
+ list.add(new HeaderItem(getString(R.string.header_ibeacon_data)));
+ list.add(new IBeaconItem(iBeaconData));
}
}
- mList.setAdapter(adapter);
- }
- private static String formatTime(final long time) {
- return TimeFormatter.getIsoDateTime(time);
- }
-
- private static String hexEncode(final int integer) {
- return "0x" + Integer.toHexString(integer).toUpperCase(Locale.US);
+ final RecyclerViewBinderCore core = RecyclerViewCoreFactory.create(this);
+ mRecycler.setAdapter(new DetailsRecyclerAdapter(core, list));
}
}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/RecyclerViewCoreFactory.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/RecyclerViewCoreFactory.java
new file mode 100644
index 0000000..c0dca9b
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/RecyclerViewCoreFactory.java
@@ -0,0 +1,35 @@
+package uk.co.alt236.btlescan.ui.details;
+
+import android.content.Context;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewBinderCore;
+import uk.co.alt236.btlescan.ui.details.recyclerview.binder.AdRecordBinder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.binder.DeviceInfoBinder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.binder.HeaderBinder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.binder.IBeaconBinder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.binder.RssiBinder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.binder.TextBinder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.AdRecordHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.DeviceInfoHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.HeaderHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.IBeaconHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.RssiInfoHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.TextHolder;
+
+/*protected*/ final class RecyclerViewCoreFactory {
+
+ public static RecyclerViewBinderCore create(final Context context) {
+ final RecyclerViewBinderCore core = new RecyclerViewBinderCore();
+
+ core.add(new TextBinder(context), TextHolder.class, R.layout.list_item_view_textview);
+ core.add(new HeaderBinder(context), HeaderHolder.class, R.layout.list_item_view_header);
+ core.add(new AdRecordBinder(context), AdRecordHolder.class, R.layout.list_item_view_adrecord);
+ core.add(new RssiBinder(context), RssiInfoHolder.class, R.layout.list_item_view_rssi_info);
+ core.add(new DeviceInfoBinder(context), DeviceInfoHolder.class, R.layout.list_item_view_device_info);
+ core.add(new IBeaconBinder(context), IBeaconHolder.class, R.layout.list_item_view_ibeacon_details);
+
+ return core;
+ }
+
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/AdRecordBinder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/AdRecordBinder.java
new file mode 100644
index 0000000..eb145b5
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/AdRecordBinder.java
@@ -0,0 +1,38 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.binder;
+
+import android.content.Context;
+
+import uk.co.alt236.bluetoothlelib.util.ByteUtils;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewBinder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.AdRecordHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.AdRecordItem;
+
+public class AdRecordBinder extends BaseViewBinder {
+
+ public AdRecordBinder(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void bind(BaseViewHolder holder, AdRecordItem item) {
+ final AdRecordHolder actualHolder = (AdRecordHolder) holder;
+
+ actualHolder.getTitleTextView().setText(item.getTitle());
+
+ actualHolder.getStringTextView().setText(
+ getContext().getString(R.string.formatter_single_quoted_string,
+ item.getDataAsString()));
+
+ actualHolder.getArrayTextView().setText(
+ getContext().getString(R.string.formatter_single_quoted_string,
+ ByteUtils.byteArrayToHexString(item.getData())));
+ }
+
+ @Override
+ public boolean canBind(RecyclerViewItem item) {
+ return item instanceof AdRecordItem;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/DeviceInfoBinder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/DeviceInfoBinder.java
new file mode 100644
index 0000000..5b3ba90
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/DeviceInfoBinder.java
@@ -0,0 +1,57 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.binder;
+
+import android.content.Context;
+
+import uk.co.alt236.bluetoothlelib.device.BluetoothService;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewBinder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.DeviceInfoHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.DeviceInfoItem;
+
+public class DeviceInfoBinder extends BaseViewBinder {
+
+ public DeviceInfoBinder(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void bind(BaseViewHolder holder, DeviceInfoItem item) {
+ final DeviceInfoHolder actualHolder = (DeviceInfoHolder) holder;
+
+ actualHolder.getName().setText(item.getName());
+ actualHolder.getAddress().setText(item.getAddress());
+ actualHolder.getDeviceClass().setText(item.getBluetoothDeviceClassName());
+ actualHolder.getMajorClass().setText(item.getBluetoothDeviceMajorClassName());
+ actualHolder.getBondingState().setText(item.getBluetoothDeviceBondState());
+ actualHolder.getServices().setText(createSupportedDevicesString(item));
+ }
+
+
+ private String createSupportedDevicesString(DeviceInfoItem item) {
+ final String retVal;
+
+ if (item.getBluetoothDeviceKnownSupportedServices().isEmpty()) {
+ retVal = getContext().getString(R.string.no_known_services);
+ } else {
+ final StringBuilder sb = new StringBuilder();
+
+ for (final BluetoothService service : item.getBluetoothDeviceKnownSupportedServices()) {
+ if (sb.length() > 0) {
+ sb.append(", ");
+ }
+
+ sb.append(service);
+ }
+ retVal = sb.toString();
+ }
+
+ return retVal;
+ }
+
+ @Override
+ public boolean canBind(RecyclerViewItem item) {
+ return item instanceof DeviceInfoItem;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/HeaderBinder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/HeaderBinder.java
new file mode 100644
index 0000000..1144977
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/HeaderBinder.java
@@ -0,0 +1,27 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.binder;
+
+import android.content.Context;
+
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewBinder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.HeaderHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.HeaderItem;
+
+public class HeaderBinder extends BaseViewBinder {
+
+ public HeaderBinder(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void bind(BaseViewHolder holder, HeaderItem item) {
+ final HeaderHolder actualHolder = (HeaderHolder) holder;
+ actualHolder.getTextView().setText(item.getText());
+ }
+
+ @Override
+ public boolean canBind(RecyclerViewItem item) {
+ return item instanceof HeaderItem;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/IBeaconBinder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/IBeaconBinder.java
new file mode 100644
index 0000000..ed3d2cf
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/IBeaconBinder.java
@@ -0,0 +1,66 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.binder;
+
+import android.content.Context;
+
+import java.util.Locale;
+
+import uk.co.alt236.bluetoothlelib.resolvers.CompanyIdentifierResolver;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewBinder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.IBeaconHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.IBeaconItem;
+import uk.co.alt236.btlescan.util.TimeFormatter;
+
+public class IBeaconBinder extends BaseViewBinder {
+ private static final String STRING_FORMAT = "%s (%s)";
+
+ public IBeaconBinder(Context context) {
+ super(context);
+ }
+
+ private static String formatTime(final long time) {
+ return TimeFormatter.getIsoDateTime(time);
+ }
+
+ private static String getWithHexEncode(final String first, final int value) {
+ return createLine(first, hexEncode(value));
+ }
+
+ private static String getWithHexEncode(final int value) {
+ return createLine(String.valueOf(value), hexEncode(value));
+ }
+
+ private static String createLine(final String first, final String second) {
+ return String.format(Locale.US, STRING_FORMAT, first, second);
+ }
+
+ private static String hexEncode(final int integer) {
+ return "0x" + Integer.toHexString(integer).toUpperCase(Locale.US);
+ }
+
+ @Override
+ public void bind(BaseViewHolder holder, IBeaconItem item) {
+ final IBeaconHolder actualHolder = (IBeaconHolder) holder;
+
+
+ final String companyName = CompanyIdentifierResolver.getCompanyName(
+ item.getCompanyIdentifier(),
+ getContext().getString(R.string.unknown));
+
+ actualHolder.getCompanyId().setText(
+ getWithHexEncode(companyName, item.getCompanyIdentifier()));
+
+ actualHolder.getAdvert().setText(getWithHexEncode(item.getIBeaconAdvertisement()));
+ actualHolder.getUuid().setText(item.getUuid());
+ actualHolder.getMajor().setText(getWithHexEncode(item.getMajor()));
+ actualHolder.getMinor().setText(getWithHexEncode(item.getMinor()));
+ actualHolder.getTxPower().setText(getWithHexEncode(item.getCalibratedTxPower()));
+ }
+
+ @Override
+ public boolean canBind(RecyclerViewItem item) {
+ return item instanceof IBeaconItem;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/RssiBinder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/RssiBinder.java
new file mode 100644
index 0000000..007c70e
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/RssiBinder.java
@@ -0,0 +1,46 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.binder;
+
+import android.content.Context;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewBinder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.RssiInfoHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.RssiItem;
+import uk.co.alt236.btlescan.util.TimeFormatter;
+
+public class RssiBinder extends BaseViewBinder {
+
+ public RssiBinder(Context context) {
+ super(context);
+ }
+
+ private static String formatTime(final long time) {
+ return TimeFormatter.getIsoDateTime(time);
+ }
+
+ @Override
+ public void bind(BaseViewHolder holder, RssiItem item) {
+ final RssiInfoHolder actualHolder = (RssiInfoHolder) holder;
+
+ actualHolder.getFirstTimestamp().setText(formatTime(item.getFirstTimestamp()));
+ actualHolder.getFirstRssi().setText(formatRssi(item.getFirstRssi()));
+ actualHolder.getLastTimestamp().setText(formatTime(item.getTimestamp()));
+ actualHolder.getLastRssi().setText(formatRssi(item.getRssi()));
+ actualHolder.getRunningAverageRssi().setText(formatRssi(item.getRunningAverageRssi()));
+ }
+
+ @Override
+ public boolean canBind(RecyclerViewItem item) {
+ return item instanceof RssiItem;
+ }
+
+ private String formatRssi(final double rssi) {
+ return getContext().getString(R.string.formatter_db, String.valueOf(rssi));
+ }
+
+ private String formatRssi(final int rssi) {
+ return getContext().getString(R.string.formatter_db, String.valueOf(rssi));
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/TextBinder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/TextBinder.java
new file mode 100644
index 0000000..8a68ee6
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/TextBinder.java
@@ -0,0 +1,27 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.binder;
+
+import android.content.Context;
+
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewBinder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+import uk.co.alt236.btlescan.ui.details.recyclerview.holder.TextHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.TextItem;
+
+public class TextBinder extends BaseViewBinder {
+
+ public TextBinder(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void bind(BaseViewHolder holder, TextItem item) {
+ final TextHolder actualHolder = (TextHolder) holder;
+ actualHolder.getTextView().setText(item.getText());
+ }
+
+ @Override
+ public boolean canBind(RecyclerViewItem item) {
+ return item instanceof TextItem;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/AdRecordHolder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/AdRecordHolder.java
new file mode 100644
index 0000000..20e2246
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/AdRecordHolder.java
@@ -0,0 +1,35 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.holder;
+
+import android.view.View;
+import android.widget.TextView;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.AdRecordItem;
+
+public class AdRecordHolder extends BaseViewHolder {
+
+ private final TextView mStringTextView;
+ private final TextView mArrayTextView;
+ private final TextView mTitleTextView;
+
+ public AdRecordHolder(View itemView) {
+ super(itemView);
+
+ mStringTextView = (TextView) itemView.findViewById(R.id.data_as_string);
+ mArrayTextView = (TextView) itemView.findViewById(R.id.data_as_array);
+ mTitleTextView = (TextView) itemView.findViewById(R.id.title);
+ }
+
+ public TextView getStringTextView() {
+ return mStringTextView;
+ }
+
+ public TextView getArrayTextView() {
+ return mArrayTextView;
+ }
+
+ public TextView getTitleTextView() {
+ return mTitleTextView;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/DeviceInfoHolder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/DeviceInfoHolder.java
new file mode 100644
index 0000000..62853d4
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/DeviceInfoHolder.java
@@ -0,0 +1,53 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.holder;
+
+import android.view.View;
+import android.widget.TextView;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.DeviceInfoItem;
+
+public class DeviceInfoHolder extends BaseViewHolder {
+
+ private final TextView mName;
+ private final TextView mAddress;
+ private final TextView mClass;
+ private final TextView mMajorClass;
+ private final TextView mServices;
+ private final TextView mBondingState;
+
+ public DeviceInfoHolder(View itemView) {
+ super(itemView);
+
+ mName = (TextView) itemView.findViewById(R.id.deviceName);
+ mAddress = (TextView) itemView.findViewById(R.id.deviceAddress);
+ mClass = (TextView) itemView.findViewById(R.id.deviceClass);
+ mMajorClass = (TextView) itemView.findViewById(R.id.deviceMajorClass);
+ mServices = (TextView) itemView.findViewById(R.id.deviceServiceList);
+ mBondingState = (TextView) itemView.findViewById(R.id.deviceBondingState);
+ }
+
+ public TextView getName() {
+ return mName;
+ }
+
+ public TextView getAddress() {
+ return mAddress;
+ }
+
+ public TextView getDeviceClass() {
+ return mClass;
+ }
+
+ public TextView getMajorClass() {
+ return mMajorClass;
+ }
+
+ public TextView getServices() {
+ return mServices;
+ }
+
+ public TextView getBondingState() {
+ return mBondingState;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/HeaderHolder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/HeaderHolder.java
new file mode 100644
index 0000000..4e3d10c
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/HeaderHolder.java
@@ -0,0 +1,23 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.holder;
+
+import android.view.View;
+import android.widget.TextView;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.HeaderItem;
+
+public class HeaderHolder extends BaseViewHolder {
+
+ private final TextView mText;
+
+ public HeaderHolder(View itemView) {
+ super(itemView);
+
+ mText = (TextView) itemView.findViewById(R.id.text);
+ }
+
+ public TextView getTextView() {
+ return mText;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/IBeaconHolder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/IBeaconHolder.java
new file mode 100644
index 0000000..2167615
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/IBeaconHolder.java
@@ -0,0 +1,53 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.holder;
+
+import android.view.View;
+import android.widget.TextView;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.IBeaconItem;
+
+public class IBeaconHolder extends BaseViewHolder {
+
+ private final TextView mCompanyId;
+ private final TextView mAdvert;
+ private final TextView mUuid;
+ private final TextView mMajor;
+ private final TextView mMinor;
+ private final TextView mTxPower;
+
+ public IBeaconHolder(View itemView) {
+ super(itemView);
+
+ mCompanyId = (TextView) itemView.findViewById(R.id.companyId);
+ mAdvert = (TextView) itemView.findViewById(R.id.advertisement);
+ mUuid = (TextView) itemView.findViewById(R.id.uuid);
+ mMajor = (TextView) itemView.findViewById(R.id.major);
+ mMinor = (TextView) itemView.findViewById(R.id.minor);
+ mTxPower = (TextView) itemView.findViewById(R.id.txpower);
+ }
+
+ public TextView getCompanyId() {
+ return mCompanyId;
+ }
+
+ public TextView getAdvert() {
+ return mAdvert;
+ }
+
+ public TextView getUuid() {
+ return mUuid;
+ }
+
+ public TextView getMajor() {
+ return mMajor;
+ }
+
+ public TextView getMinor() {
+ return mMinor;
+ }
+
+ public TextView getTxPower() {
+ return mTxPower;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/RssiInfoHolder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/RssiInfoHolder.java
new file mode 100644
index 0000000..b36125b
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/RssiInfoHolder.java
@@ -0,0 +1,47 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.holder;
+
+import android.view.View;
+import android.widget.TextView;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.RssiItem;
+
+public class RssiInfoHolder extends BaseViewHolder {
+
+ private final TextView mTvFirstTimestamp;
+ private final TextView mTvFirstRssi;
+ private final TextView mTvLastTimestamp;
+ private final TextView mTvLastRssi;
+ private final TextView mTvRunningAverageRssi;
+
+ public RssiInfoHolder(View itemView) {
+ super(itemView);
+
+ mTvFirstTimestamp = (TextView) itemView.findViewById(R.id.firstTimestamp);
+ mTvFirstRssi = (TextView) itemView.findViewById(R.id.firstRssi);
+ mTvLastTimestamp = (TextView) itemView.findViewById(R.id.lastTimestamp);
+ mTvLastRssi = (TextView) itemView.findViewById(R.id.lastRssi);
+ mTvRunningAverageRssi = (TextView) itemView.findViewById(R.id.runningAverageRssi);
+ }
+
+ public TextView getFirstTimestamp() {
+ return mTvFirstTimestamp;
+ }
+
+ public TextView getFirstRssi() {
+ return mTvFirstRssi;
+ }
+
+ public TextView getLastTimestamp() {
+ return mTvLastTimestamp;
+ }
+
+ public TextView getLastRssi() {
+ return mTvLastRssi;
+ }
+
+ public TextView getRunningAverageRssi() {
+ return mTvRunningAverageRssi;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/TextHolder.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/TextHolder.java
new file mode 100644
index 0000000..48f2e96
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/TextHolder.java
@@ -0,0 +1,23 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.holder;
+
+import android.view.View;
+import android.widget.TextView;
+
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.ui.common.recyclerview.BaseViewHolder;
+import uk.co.alt236.btlescan.ui.details.recyclerview.model.TextItem;
+
+public class TextHolder extends BaseViewHolder {
+
+ private final TextView mText;
+
+ public TextHolder(View itemView) {
+ super(itemView);
+
+ mText = (TextView) itemView.findViewById(R.id.text);
+ }
+
+ public TextView getTextView() {
+ return mText;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/AdRecordItem.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/AdRecordItem.java
new file mode 100644
index 0000000..68be76e
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/AdRecordItem.java
@@ -0,0 +1,31 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.model;
+
+import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
+import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+
+public class AdRecordItem implements RecyclerViewItem {
+
+ private final String mTitle;
+ private final byte[] mData;
+ private final String mDataAsString;
+
+ public AdRecordItem(final String title,
+ final AdRecord record) {
+ mTitle = title;
+ mData = record.getData();
+ mDataAsString = AdRecordUtils.getRecordDataAsString(record);
+ }
+
+ public String getTitle() {
+ return mTitle;
+ }
+
+ public byte[] getData() {
+ return mData;
+ }
+
+ public String getDataAsString() {
+ return mDataAsString;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/DeviceInfoItem.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/DeviceInfoItem.java
new file mode 100644
index 0000000..b7cda0b
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/DeviceInfoItem.java
@@ -0,0 +1,40 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.model;
+
+import java.util.Set;
+
+import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
+import uk.co.alt236.bluetoothlelib.device.BluetoothService;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+
+public class DeviceInfoItem implements RecyclerViewItem {
+
+ private final BluetoothLeDevice mDevice;
+
+ public DeviceInfoItem(BluetoothLeDevice device) {
+ mDevice = device;
+ }
+
+ public Set getBluetoothDeviceKnownSupportedServices() {
+ return mDevice.getBluetoothDeviceKnownSupportedServices();
+ }
+
+ public String getBluetoothDeviceBondState() {
+ return mDevice.getBluetoothDeviceBondState();
+ }
+
+ public String getBluetoothDeviceMajorClassName() {
+ return mDevice.getBluetoothDeviceClassName();
+ }
+
+ public String getBluetoothDeviceClassName() {
+ return mDevice.getBluetoothDeviceClassName();
+ }
+
+ public String getAddress() {
+ return mDevice.getAddress();
+ }
+
+ public String getName() {
+ return mDevice.getName();
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/HeaderItem.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/HeaderItem.java
new file mode 100644
index 0000000..46b7db6
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/HeaderItem.java
@@ -0,0 +1,15 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.model;
+
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+
+public class HeaderItem implements RecyclerViewItem {
+ private final CharSequence mText;
+
+ public HeaderItem(CharSequence text) {
+ mText = text;
+ }
+
+ public CharSequence getText() {
+ return mText;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/IBeaconItem.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/IBeaconItem.java
new file mode 100644
index 0000000..9db95de
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/IBeaconItem.java
@@ -0,0 +1,47 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.model;
+
+import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconManufacturerData;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+
+public class IBeaconItem implements RecyclerViewItem {
+
+ private final int mMajor;
+ private final int mMinor;
+ private final String mUuid;
+ private final int mCompanyIdentifier;
+ private final int mIBeaconAdvertisement;
+ private final int mCalibratedTxPower;
+
+ public IBeaconItem(final IBeaconManufacturerData iBeaconData) {
+ mMajor = iBeaconData.getMajor();
+ mMinor = iBeaconData.getMinor();
+ mUuid = iBeaconData.getUUID();
+ mCompanyIdentifier = iBeaconData.getCompanyIdentifier();
+ mIBeaconAdvertisement = iBeaconData.getIBeaconAdvertisement();
+ mCalibratedTxPower = iBeaconData.getCalibratedTxPower();
+ }
+
+ public int getCompanyIdentifier() {
+ return mCompanyIdentifier;
+ }
+
+ public int getMajor() {
+ return mMajor;
+ }
+
+ public int getMinor() {
+ return mMinor;
+ }
+
+ public String getUuid() {
+ return mUuid;
+ }
+
+ public int getIBeaconAdvertisement() {
+ return mIBeaconAdvertisement;
+ }
+
+ public int getCalibratedTxPower() {
+ return mCalibratedTxPower;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/RssiItem.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/RssiItem.java
new file mode 100644
index 0000000..0271a50
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/RssiItem.java
@@ -0,0 +1,33 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.model;
+
+import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+
+public class RssiItem implements RecyclerViewItem {
+
+ private final BluetoothLeDevice mDevice;
+
+ public RssiItem(BluetoothLeDevice device) {
+ mDevice = device;
+ }
+
+ public int getRssi() {
+ return mDevice.getRssi();
+ }
+
+ public double getRunningAverageRssi() {
+ return mDevice.getRunningAverageRssi();
+ }
+
+ public int getFirstRssi() {
+ return mDevice.getFirstRssi();
+ }
+
+ public long getFirstTimestamp() {
+ return mDevice.getFirstTimestamp();
+ }
+
+ public long getTimestamp() {
+ return mDevice.getTimestamp();
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/TextItem.java b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/TextItem.java
new file mode 100644
index 0000000..730fcc9
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/TextItem.java
@@ -0,0 +1,15 @@
+package uk.co.alt236.btlescan.ui.details.recyclerview.model;
+
+import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
+
+public class TextItem implements RecyclerViewItem {
+ private final CharSequence mText;
+
+ public TextItem(CharSequence text) {
+ mText = text;
+ }
+
+ public CharSequence getText() {
+ return mText;
+ }
+}
diff --git a/sample_app/src/main/res/layout/activity_details.xml b/sample_app/src/main/res/layout/activity_details.xml
index 3100292..56ddbc9 100644
--- a/sample_app/src/main/res/layout/activity_details.xml
+++ b/sample_app/src/main/res/layout/activity_details.xml
@@ -6,9 +6,9 @@
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
-
-
+
+
\ No newline at end of file
diff --git a/sample_app/src/main/res/layout/list_item_view_header.xml b/sample_app/src/main/res/layout/list_item_view_header.xml
index 1958014..133d44f 100644
--- a/sample_app/src/main/res/layout/list_item_view_header.xml
+++ b/sample_app/src/main/res/layout/list_item_view_header.xml
@@ -7,7 +7,7 @@
android:paddingBottom="5dp">
\ No newline at end of file