From 92d6ee52413b0ffda57494ef92dab6a958efd4f9 Mon Sep 17 00:00:00 2001 From: Alexandros Schillings Date: Tue, 30 Aug 2016 18:05:44 +0100 Subject: [PATCH] Removed merge adapter, details screen now uses a recyclerview --- library/library.iml | 16 +- sample_app/build.gradle | 6 +- sample_app/sample_app.iml | 7 +- .../recyclerview/BaseRecyclerViewAdapter.java | 55 +++++ .../common/recyclerview/BaseViewBinder.java | 20 ++ .../common/recyclerview/BaseViewHolder.java | 18 ++ .../recyclerview/RecyclerViewBinderCore.java | 93 ++++++++ .../common/recyclerview/RecyclerViewItem.java | 4 + .../ui/control/DeviceControlActivity.java | 2 +- .../ui/details/DetailsRecyclerAdapter.java | 25 +++ .../ui/details/DeviceDetailsActivity.java | 202 ++++-------------- .../ui/details/RecyclerViewCoreFactory.java | 35 +++ .../recyclerview/binder/AdRecordBinder.java | 38 ++++ .../recyclerview/binder/DeviceInfoBinder.java | 57 +++++ .../recyclerview/binder/HeaderBinder.java | 27 +++ .../recyclerview/binder/IBeaconBinder.java | 66 ++++++ .../recyclerview/binder/RssiBinder.java | 46 ++++ .../recyclerview/binder/TextBinder.java | 27 +++ .../recyclerview/holder/AdRecordHolder.java | 35 +++ .../recyclerview/holder/DeviceInfoHolder.java | 53 +++++ .../recyclerview/holder/HeaderHolder.java | 23 ++ .../recyclerview/holder/IBeaconHolder.java | 53 +++++ .../recyclerview/holder/RssiInfoHolder.java | 47 ++++ .../recyclerview/holder/TextHolder.java | 23 ++ .../recyclerview/model/AdRecordItem.java | 31 +++ .../recyclerview/model/DeviceInfoItem.java | 40 ++++ .../recyclerview/model/HeaderItem.java | 15 ++ .../recyclerview/model/IBeaconItem.java | 47 ++++ .../details/recyclerview/model/RssiItem.java | 33 +++ .../details/recyclerview/model/TextItem.java | 15 ++ .../src/main/res/layout/activity_details.xml | 10 +- .../main/res/layout/list_item_view_header.xml | 2 +- .../res/layout/list_item_view_textview.xml | 2 +- 33 files changed, 986 insertions(+), 187 deletions(-) create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseRecyclerViewAdapter.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewBinder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/BaseViewHolder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewBinderCore.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/common/recyclerview/RecyclerViewItem.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/DetailsRecyclerAdapter.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/RecyclerViewCoreFactory.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/AdRecordBinder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/DeviceInfoBinder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/HeaderBinder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/IBeaconBinder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/RssiBinder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/binder/TextBinder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/AdRecordHolder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/DeviceInfoHolder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/HeaderHolder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/IBeaconHolder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/RssiInfoHolder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/holder/TextHolder.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/AdRecordItem.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/DeviceInfoItem.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/HeaderItem.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/IBeaconItem.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/RssiItem.java create mode 100644 sample_app/src/main/java/uk/co/alt236/btlescan/ui/details/recyclerview/model/TextItem.java 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 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 onCreateViewHolder(final ViewGroup parent, + final int viewType) { + return mCore.create(parent, viewType); + } + + @Override + public void onBindViewHolder(final BaseViewHolder holder, + final int position) { + + final int viewType = getItemViewType(position); + final BaseViewBinder 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> viewHolder, + final int layoutId) { + + mViewBinders.add(binder); + mViewHolderClasses.add(viewHolder); + mLayoutIds.add(layoutId); + } + + public BaseViewHolder 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) instantiate(clazz, itemView); + } + + public int getViewType(final T item) { + int result = INVALID_VIEWTYPE; + int count = 0; + + for (final BaseViewBinder binder : mViewBinders) { + + if (binder.canBind(item)) { + result = count; + break; + } + + count++; + } + + return result; + } + + public BaseViewBinder 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