Making the Device Details activity pretty

This commit is contained in:
Alexandros Schillings
2014-04-25 12:55:25 +01:00
parent e28d698ba9
commit cf48721d77
12 changed files with 436 additions and 90 deletions
@@ -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<AdRecord> 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);
}
}