From cf48721d779954b0c37183393952c14cc0a9d4cc Mon Sep 17 00:00:00 2001 From: Alexandros Schillings Date: Fri, 25 Apr 2014 12:55:25 +0100 Subject: [PATCH] Making the Device Details activity pretty --- sample_app/libs/merge-1.0.1.jar | Bin 0 -> 9144 bytes sample_app/libs/sacklist-1.0.0.jar | Bin 0 -> 2628 bytes sample_app/res/layout/activity_details.xml | 13 +- .../res/layout/list_item_view_adrecord.xml | 43 ++++ .../res/layout/list_item_view_device_info.xml | 56 +++++ .../res/layout/list_item_view_header.xml | 23 ++ .../layout/list_item_view_ibeacon_details.xml | 76 +++++++ .../res/layout/list_item_view_rssi_info.xml | 66 ++++++ .../res/layout/list_item_view_textview.xml | 13 ++ sample_app/res/values/strings.xml | 7 + sample_app/res/values/styles.xml | 24 +- .../activities/DeviceDetailsActivity.java | 205 +++++++++++------- 12 files changed, 436 insertions(+), 90 deletions(-) create mode 100644 sample_app/libs/merge-1.0.1.jar create mode 100644 sample_app/libs/sacklist-1.0.0.jar create mode 100644 sample_app/res/layout/list_item_view_adrecord.xml create mode 100644 sample_app/res/layout/list_item_view_device_info.xml create mode 100644 sample_app/res/layout/list_item_view_header.xml create mode 100644 sample_app/res/layout/list_item_view_ibeacon_details.xml create mode 100644 sample_app/res/layout/list_item_view_rssi_info.xml create mode 100644 sample_app/res/layout/list_item_view_textview.xml diff --git a/sample_app/libs/merge-1.0.1.jar b/sample_app/libs/merge-1.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..fb49c1530e930d1ecd8d3e5670605574c9ef0883 GIT binary patch literal 9144 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 Lp^gwpe}4Nf5CZB@ literal 0 HcmV?d00001 diff --git a/sample_app/libs/sacklist-1.0.0.jar b/sample_app/libs/sacklist-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..3a49a76111a23f313ed0f4c3926d77ea1d6ad4da GIT binary patch literal 2628 zcmWIWW@h1HVBp|j*c{U5%m4&TAOZ+Df!NnI#8KDN&rP41Apk|;rh2A#(m(~0KrDi+ z(AUw=)6F$FM9Elt5rC=zs>{vKD=tqgO2w;Q6pQ-g^2B7kn&fb4Do#w!&dDq;!O%UA=Us0((EU-s zkTWBwI~Zt;e_B{(YI(6^N@77tYLQ-YPGWKK)R5Tx+aVHleRIunXVtBb_ihxsF>Q&w zWU9fn^=q~7-qMRs)YR4GIqAFSobp!X+nJi%57;uP=sjRlIl|kacyN^w=MLvb`#-P? zB-tD!O{4N44 zx2?Rd@jmC}w^iFhmn_xJe!BJ1tTgFQ)&^Y7=Ygj(@U-`&tl}_uY1XvT^4=e7pAVM`ps@t z%KnliYLRc_>@zzB?_RsB8h&5!MdH1>h(P1*#@f;4U-#&w1)nV9xxT?C@1@QA?vTlv z%WgY1vrN8o(6O4KBIO&m*L}TdiR&V!q@QcjY!$Pa;rs3MiijoOm#z19;y9x^{nd)~ zrm*E?I@L>t8c<0vDWF@W1fJmyM;%V@fRNi^!_%66uIr_QHDB zIih#hr}lig^!n+y_p1t>j!d;)A8(j4`*+syj2JV6zPL5VF1F@9i;`@y zynXH4Q)_i4m+C-c58+|zftFh@buT}ZR>oYXywv_iu^-#voIXGe%zL`qJcowIA> zV*NdnuY3QSz>^p8bm81hkNF~XcIJwFS*UP7B`YH6zL3T5`t|IV{V8uHS;Op#Ba6R$ zn2>xVGOxPiMdmdwR?8b(lXasP3bm~*?kSJ-zB*Ap{YHP({axFegr8=$y$pHyJm$8+ z_R6gWXY3=?|5q_}<*?pY|FLudd*QpAjO+exscGZ*-+Z9r7lV>+UCX38hEnCi29EEq z&LlkYp5yVK!Bu9Fb-|}qjT*uk$3#A+8=UBy`>>j4dcmaS z&R^atr#Gp0Jvk)Y)4aX9%gm8KVC|;~d08Tdofztcytry-DF&@Lww)($J%{YWpukJ6 zya$pNq)6uOc((ETuSCW4>VW?A9n-gd(6vo$o%i&eh#&jcoe~$eosd%DySU=Pyyt3~ z(tAH#O*YY0^yT(e2o^3{$GoBVp1Hu}g!T@un&8&b(}zE$9%a&LEa{lQDIj&}`^6C1 zn%@xx&Js3F7ZrZE=1WOTUeTu`>+Q%H9B@eF*bPnjWD|h}E3QiXK7M2B1l#7#SKpXU zeE*mIck!DQ{U0r>?<$0b?E0uZOI?|H;{6Nr{d(@Y=NLVj%j?2-aZysOLXrNQ332-0 zoWK26{`M<*QT?Gqb+0zg|6J(&?P5dhyLr!7K6)FMAhycf`*~(}Me%KxkK#drdtBag z&)}IdkN=sQZ_S6?&|UE|-r>BQR}JoJ`dpXZH_`dX)LD%`Ul|@Yf6N>0^3R%igKN-< z*>cql*Lv4&W8U&VsP$`XMYQ%|^>X*A9hE<|@5Fyndj5|QQM{v1P75CLHz+YhNp!Wi zKW=0ya8y67q;cX}kM896i;~)!_#Z5mNO5%ZUMTza-o1NwpI`sY-jMu8g=2$gvQYAD zfw}Q#-mT~O;vjL(_i9Ak&7Rj`Z0C5L{)dE~nkU$__ivBDIbTK2#UY`ecIg&J-v1b5 zojOVCVCk{!s~_VHxA?D8lv#FY%9*{Fcq2YW8Et&jWEx|WeKjKN#H9_9t4ki5RfKd4 zI~8T$iaOza^=QxkE6cq99b%6-Y?b(He}woIQ{%I%S$ChD9uy(7u>FAiu5N+A@(szh zN8Y*L6>0Abp7GqFXN(5CGCK z3&;fNK(4>>=?2x`5CGDB3dls)4X(}c83C%zApm5=e;^a95%9Vl-7NIF9cJ2=Mq6O| z#%~s`njYN_keRT?7bw#~0LZ-@Y=rCpXF+rW(X$}T$SsZD#2JW@Ap^WwfjU8LLr#W% Kpj+p&gLnWyLdL29 literal 0 HcmV?d00001 diff --git a/sample_app/res/layout/activity_details.xml b/sample_app/res/layout/activity_details.xml index 011edb7..e853847 100644 --- a/sample_app/res/layout/activity_details.xml +++ b/sample_app/res/layout/activity_details.xml @@ -7,16 +7,9 @@ android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" > - - - - - + \ No newline at end of file diff --git a/sample_app/res/layout/list_item_view_adrecord.xml b/sample_app/res/layout/list_item_view_adrecord.xml new file mode 100644 index 0000000..ed0adc6 --- /dev/null +++ b/sample_app/res/layout/list_item_view_adrecord.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample_app/res/layout/list_item_view_device_info.xml b/sample_app/res/layout/list_item_view_device_info.xml new file mode 100644 index 0000000..04ddfe7 --- /dev/null +++ b/sample_app/res/layout/list_item_view_device_info.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample_app/res/layout/list_item_view_header.xml b/sample_app/res/layout/list_item_view_header.xml new file mode 100644 index 0000000..b218ade --- /dev/null +++ b/sample_app/res/layout/list_item_view_header.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/sample_app/res/layout/list_item_view_ibeacon_details.xml b/sample_app/res/layout/list_item_view_ibeacon_details.xml new file mode 100644 index 0000000..cd07cc9 --- /dev/null +++ b/sample_app/res/layout/list_item_view_ibeacon_details.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample_app/res/layout/list_item_view_rssi_info.xml b/sample_app/res/layout/list_item_view_rssi_info.xml new file mode 100644 index 0000000..5b515cf --- /dev/null +++ b/sample_app/res/layout/list_item_view_rssi_info.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample_app/res/layout/list_item_view_textview.xml b/sample_app/res/layout/list_item_view_textview.xml new file mode 100644 index 0000000..1f00684 --- /dev/null +++ b/sample_app/res/layout/list_item_view_textview.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/sample_app/res/values/strings.xml b/sample_app/res/values/strings.xml index 4c6cd43..5d57739 100644 --- a/sample_app/res/values/strings.xml +++ b/sample_app/res/values/strings.xml @@ -44,5 +44,12 @@ Bluetooth LE Scan Results (%s) Please find attached the scan results. Please select your email client: + iBeacon Data + Raw Ad Records + Scan Record + RSSI Info + Device Info + Invalid Device Data! + unknown \ No newline at end of file diff --git a/sample_app/res/values/styles.xml b/sample_app/res/values/styles.xml index 6ce89c7..9cf5fd9 100644 --- a/sample_app/res/values/styles.xml +++ b/sample_app/res/values/styles.xml @@ -1,4 +1,4 @@ - + - + + + + + + + \ No newline at end of file diff --git a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java b/sample_app/src/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java index 2581279..75e91b7 100644 --- a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java +++ b/sample_app/src/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java @@ -1,32 +1,121 @@ package uk.co.alt236.btlescan.activities; import java.util.Collection; +import java.util.Locale; import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice; import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord; import uk.co.alt236.bluetoothlelib.device.mfdata.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.bluetoothlelib.util.IBeaconUtils; import uk.co.alt236.btlescan.R; -import uk.co.alt236.btlescan.util.Constants; -import android.app.Activity; +import uk.co.alt236.btlescan.util.TimeFormatter; +import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; +import android.widget.LinearLayout; import android.widget.TextView; import butterknife.ButterKnife; -import butterknife.InjectView; -public class DeviceDetailsActivity extends Activity{ - private static final String SECTION_LINE = "------------------------------"; +import com.commonsware.cwac.merge.MergeAdapter; + +public class DeviceDetailsActivity extends ListActivity{ public static final String EXTRA_DEVICE = "extra_device"; - @InjectView(R.id.tvDetails) TextView mTvDetails; - private BluetoothLeDevice mDevice; + private void appendAdRecordView(MergeAdapter adapter, String title, 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("'" + AdRecordUtils.getRecordDataAsString(record) + "'"); + tvArray.setText("'" + ByteUtils.byteArrayToHexString(record.getData()) + "'"); + + adapter.addView(lt); + } + + private void appendDeviceInfo(MergeAdapter adapter, 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 tvBondingState = (TextView) lt.findViewById(R.id.deviceBondingState); + + tvName.setText(device.getName()); + tvAddress.setText(device.getAddress()); + tvClass.setText(device.getBluetoothDeviceClassName()); + tvBondingState.setText(device.getBluetoothDeviceBondState()); + + adapter.addView(lt); + } + + private void appendHeader(MergeAdapter adapter, 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(MergeAdapter adapter, 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().toString()); + 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(MergeAdapter adapter, 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(MergeAdapter adapter, byte data[]){ + appendSimpleText(adapter, ByteUtils.byteArrayToHexString(data)); + } + + private void appendSimpleText(MergeAdapter adapter, 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(double rssi){ return getString(R.string.formatter_db, String.valueOf(rssi)); } @@ -35,11 +124,6 @@ public class DeviceDetailsActivity extends Activity{ return getString(R.string.formatter_db, String.valueOf(rssi)); } - private String formatTime(long time){ - return android.text.format.DateFormat.format( - Constants.TIME_FORMAT, new java.util.Date(time)).toString(); - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -62,11 +146,11 @@ public class DeviceDetailsActivity extends Activity{ switch (item.getItemId()) { case R.id.menu_connect: - final Intent intent = new Intent(this, DeviceControlActivity.class); - intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, mDevice.getName()); - intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, mDevice.getAddress()); + final Intent intent = new Intent(this, DeviceControlActivity.class); + intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, mDevice.getName()); + intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, mDevice.getAddress()); - startActivity(intent); + startActivity(intent); break; } @@ -74,85 +158,50 @@ public class DeviceDetailsActivity extends Activity{ } private void pupulateDetails(BluetoothLeDevice device) { - final StringBuilder sb = new StringBuilder(); + final MergeAdapter adapter = new MergeAdapter(); if(device == null){ - append(sb, "Invalid Device Data!", null); + appendHeader(adapter, getString(R.string.header_device_info)); + appendSimpleText(adapter, getString(R.string.invalid_device_data)); } else { - append(sb, "Device Info", null); - append(sb, SECTION_LINE, null); - append(sb, "Device Name", device.getName()); - append(sb, "Device Address", device.getAddress()); + appendHeader(adapter, getString(R.string.header_device_info)); + appendDeviceInfo(adapter, device); - append(sb, "", null); - append(sb, "Device Class", device.getBluetoothDeviceClassName()); - append(sb, "Bonding State", device.getBluetoothDeviceBondState()); - - - append(sb, "", null); - append(sb, "RSSI Info", null); - append(sb, SECTION_LINE, null); - append(sb, "First Timestamp", formatTime(device.getFirstTimestamp())); - append(sb, "First RSSI", formatRssi(device.getFirstRssi())); - append(sb, "Current Timestamp", formatTime(device.getTimestamp())); - append(sb, "Current RSSI", formatRssi(device.getRssi())); - append(sb, "Running Average RSSI", formatRssi(device.getRunningAverageRssi())); - - append(sb, "", null); - append(sb, "Scan Record", null); - append(sb, SECTION_LINE, null); - append(sb, device.getScanRecord()); - - append(sb, "", null); - append(sb, "Raw Ad Records As String", null); - append(sb, SECTION_LINE, null); + appendHeader(adapter, getString(R.string.header_rssi_info)); + appendRssiInfo(adapter, device); + appendHeader(adapter, getString(R.string.header_scan_record)); + appendSimpleText(adapter, device.getScanRecord()); final Collection adRecords = device.getAdRecordStore().getRecordsAsCollection(); + if(adRecords.size() > 0){ + appendHeader(adapter, getString(R.string.header_raw_ad_records)); - for(final AdRecord record : adRecords){ - append(sb, "#" +record.getType() + " " + record.getHumanReadableType(), null); - append(sb, " As String: '" + AdRecordUtils.getRecordDataAsString(record) + "'", null); - append(sb, " As Array : " + ByteUtils.byteArrayToHexString(record.getData()), null); - append(sb, "", null); + for(final AdRecord record : adRecords){ + + appendAdRecordView( + adapter, + "#" + record.getType() + " " + record.getHumanReadableType(), + record); + } } - append(sb, "Additional", null); - append(sb, SECTION_LINE, null); - final boolean isIBeacon = IBeaconUtils.isThisAnIBeacon(device); - append(sb, "Is iBeacon", isIBeacon); - + final boolean isIBeacon = IBeaconUtils.isThisAnIBeacon(device); if(isIBeacon){ final IBeaconManufacturerData iBeaconData = new IBeaconManufacturerData(device); - append(sb, "Company ID", iBeaconData.getCompanyIdentifier() + " (" + Integer.toHexString( iBeaconData.getCompanyIdentifier() ) + ")"); - append(sb, "Advertisment", iBeaconData.getIBeaconAdvertisement() + " (" + Integer.toHexString( iBeaconData.getIBeaconAdvertisement() ) + ")"); - append(sb, "UUID", iBeaconData.getUUID().toString()); - append(sb, "Major", iBeaconData.getMajor() + " (" + Integer.toHexString( iBeaconData.getMajor() ) + ")"); - append(sb, "Minor", iBeaconData.getMinor() + " (" + Integer.toHexString( iBeaconData.getMinor() ) + ")"); - append(sb, "TX Power", iBeaconData.getCalibratedTxPower() + " (" + Integer.toHexString( iBeaconData.getCalibratedTxPower() ) + ")"); + appendHeader(adapter, getString(R.string.header_ibeacon_data)); + appendIBeaconInfo(adapter, iBeaconData); } + } - - mTvDetails.setText(sb.toString()); + getListView().setAdapter(adapter); } - private static void append(StringBuilder sb, byte[] value){ - append(sb, ByteUtils.byteArrayToHexString(value), null); + private static String formatTime(long time){ + return TimeFormatter.getIsoDateTime(time); } - private static void append(StringBuilder sb, String label, boolean value) { - append(sb, label, String.valueOf(value)); - } - - private static void append(StringBuilder sb, String label, String value){ - if(value != null){ - sb.append("\u2022" + padRight(label, 10) +":\t" + value + "\n"); - } else { - sb.append(label + "\n"); - } - } - - public static String padRight(String s, int n) { - return String.format("%1$-" + n + "s", s); + private static String hexEncode(int integer){ + return "0x" + Integer.toHexString(integer).toUpperCase(Locale.US); } }