package com.shlb.comb.adapter;
|
|
import android.bluetooth.BluetoothDevice;
|
import android.content.Context;
|
import android.os.ParcelUuid;
|
import android.util.SparseArray;
|
import android.view.View;
|
import android.view.ViewGroup;
|
import android.widget.ImageView;
|
import android.widget.LinearLayout;
|
import android.widget.TextView;
|
|
import com.blakequ.bluetooth_manager_lib.device.BluetoothLeDevice;
|
import com.blakequ.bluetooth_manager_lib.scan.bluetoothcompat.ScanRecordCompat;
|
import com.blakequ.bluetooth_manager_lib.util.ByteUtils;
|
import com.shlb.comb.R;
|
|
import java.util.List;
|
import java.util.Map;
|
|
|
public class HomeDeviceListAdapter extends BaseArrayListAdapter<BluetoothLeDevice> {
|
private setOnItemButtonClick onItemButtonClick;
|
|
|
private int scrodKey;
|
private int expandedPosition = -1;
|
|
public HomeDeviceListAdapter(Context context, setOnItemButtonClick onItemButtonClick) {
|
super(context);
|
this.onItemButtonClick = onItemButtonClick;
|
}
|
|
public void updateConfig(int scrodKey) {
|
this.scrodKey = scrodKey;
|
}
|
|
@Override
|
public View getView(int position, View view, ViewGroup parent) {
|
final ViewHolder viewHolder;
|
// General ListView optimization code.
|
if (view == null) {
|
view = mInflater.inflate(R.layout.home_list_bluetooth_item, parent, false);
|
viewHolder = new ViewHolder();
|
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
|
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
|
viewHolder.rssi = (TextView) view.findViewById(R.id.rssi);
|
viewHolder.deviceIcon = (ImageView) view.findViewById(R.id.device_icon);
|
viewHolder.ivDown = (ImageView) view.findViewById(R.id.iv_down);
|
viewHolder.llMainContent = (LinearLayout) view.findViewById(R.id.ll_main_content);
|
viewHolder.llMoreInfo = (LinearLayout) view.findViewById(R.id.ll_more_info);
|
viewHolder.tvDeviceType = (TextView) view.findViewById(R.id.tv_device_type);
|
viewHolder.tvAdvType = (TextView) view.findViewById(R.id.tv_adv_type);
|
viewHolder.tvFlags = (TextView) view.findViewById(R.id.tv_flags);
|
viewHolder.tvLocalName = (TextView) view.findViewById(R.id.tv_local_name);
|
viewHolder.tvTxPower = (TextView) view.findViewById(R.id.tv_tx_power);
|
viewHolder.tvServiceUuids = (TextView) view.findViewById(R.id.tv_service_uuids);
|
viewHolder.tvServiceData = (TextView) view.findViewById(R.id.tv_service_data);
|
viewHolder.tvManufacturerData = (TextView) view.findViewById(R.id.tv_manufacturer_data);
|
viewHolder.connBtn = view.findViewById(R.id.conn_btn);
|
view.setTag(viewHolder);
|
} else {
|
viewHolder = (ViewHolder) view.getTag();
|
}
|
|
viewHolder.connBtn.setOnClickListener(new View.OnClickListener() {
|
@Override
|
public void onClick(View view) {
|
onItemButtonClick.buttonClick(view, position);
|
}
|
});
|
|
final BluetoothLeDevice device = (BluetoothLeDevice) getItem(position);
|
final String deviceName = device.getName();
|
final String deviceAddress = device.getAddress();
|
final double rssi = device.getRssi();
|
|
|
if (deviceName != null && deviceName.length() > 0) {
|
viewHolder.deviceName.setText(deviceName);
|
} else {
|
viewHolder.deviceName.setText(R.string.unknown_device);
|
}
|
if (deviceAddress != null && deviceAddress.length() > 0) {
|
viewHolder.deviceAddress.setText(deviceAddress);
|
}
|
if (Math.abs(rssi) > 0) {
|
viewHolder.rssi.setText("-" + rssi + "dBm");
|
}
|
|
if (expandedPosition == position) {
|
viewHolder.llMoreInfo.setVisibility(View.VISIBLE);
|
viewHolder.ivDown.setRotation(180);
|
populateMoreInfo(viewHolder, device);
|
} else {
|
viewHolder.llMoreInfo.setVisibility(View.GONE);
|
viewHolder.ivDown.setRotation(0);
|
}
|
|
viewHolder.llMainContent.setOnClickListener(new View.OnClickListener() {
|
@Override
|
public void onClick(View v) {
|
if (expandedPosition == position) {
|
expandedPosition = -1;
|
} else {
|
expandedPosition = position;
|
}
|
notifyDataSetChanged();
|
}
|
});
|
|
|
return view;
|
}
|
|
private void populateMoreInfo(ViewHolder holder, BluetoothLeDevice device) {
|
holder.tvDeviceType.setText("设备类型: " + getDeviceType(device));
|
|
ScanRecordCompat record = ScanRecordCompat.parseFromBytes(device.getScanRecord());
|
if (record != null) {
|
holder.tvAdvType.setText("广播类型: Legacy");
|
holder.tvFlags.setText("标志 (Flags): " + getFlags(record));
|
holder.tvLocalName.setText("完整本地名称: " + (record.getDeviceName() != null ? record.getDeviceName() : "无"));
|
|
int txPower = record.getTxPowerLevel();
|
holder.tvTxPower.setText("发射功率: " + (txPower == Integer.MIN_VALUE ? "无" : txPower + " dBm"));
|
|
List<ParcelUuid> uuids = record.getServiceUuids();
|
if (uuids != null && !uuids.isEmpty()) {
|
StringBuilder sb = new StringBuilder("服务 UUID: ");
|
for (ParcelUuid uuid : uuids) {
|
sb.append(uuid.toString()).append("\n");
|
}
|
holder.tvServiceUuids.setVisibility(View.VISIBLE);
|
holder.tvServiceUuids.setText(sb.toString().trim());
|
} else {
|
holder.tvServiceUuids.setVisibility(View.GONE);
|
}
|
|
Map<ParcelUuid, byte[]> serviceData = record.getServiceData();
|
if (serviceData != null && !serviceData.isEmpty()) {
|
StringBuilder sb = new StringBuilder("服务数据: ");
|
for (Map.Entry<ParcelUuid, byte[]> entry : serviceData.entrySet()) {
|
sb.append(entry.getKey().toString()).append(": ")
|
.append(ByteUtils.byteArrayToHexString(entry.getValue())).append("\n");
|
}
|
holder.tvServiceData.setVisibility(View.VISIBLE);
|
holder.tvServiceData.setText(sb.toString().trim());
|
} else {
|
holder.tvServiceData.setVisibility(View.GONE);
|
}
|
|
holder.tvManufacturerData.setText("厂商数据: " + getManufacturerData(record));
|
} else {
|
holder.tvAdvType.setText("广播类型: 无");
|
holder.tvFlags.setText("标志 (Flags): 无");
|
holder.tvLocalName.setText("完整本地名称: 无");
|
holder.tvTxPower.setText("发射功率: 无");
|
holder.tvServiceUuids.setVisibility(View.GONE);
|
holder.tvServiceData.setVisibility(View.GONE);
|
holder.tvManufacturerData.setText("厂商数据: 无");
|
}
|
}
|
|
private String getDeviceType(BluetoothLeDevice device) {
|
int type = device.getDevice().getType();
|
switch (type) {
|
case BluetoothDevice.DEVICE_TYPE_CLASSIC:
|
return "仅经典蓝牙 (Classic)";
|
case BluetoothDevice.DEVICE_TYPE_LE:
|
return "仅低功耗蓝牙 (LE)";
|
case BluetoothDevice.DEVICE_TYPE_DUAL:
|
return "双模 (Dual Mode)";
|
default:
|
return "未知";
|
}
|
}
|
|
private String getFlags(ScanRecordCompat record) {
|
int flags = record.getAdvertiseFlags();
|
if (flags == -1) return "无";
|
StringBuilder sb = new StringBuilder();
|
if ((flags & 0x01) != 0) sb.append("LE 有限可发现模式, ");
|
if ((flags & 0x02) != 0) sb.append("LE 普通可发现模式, ");
|
if ((flags & 0x04) != 0) sb.append("不支持 BR/EDR, ");
|
if ((flags & 0x08) != 0) sb.append("控制器支持 LE 和 BR/EDR, ");
|
if ((flags & 0x10) != 0) sb.append("主机支持 LE 和 BR/EDR, ");
|
if (sb.length() > 2) sb.setLength(sb.length() - 2);
|
return sb.toString();
|
}
|
|
private String getManufacturerData(ScanRecordCompat record) {
|
SparseArray<byte[]> data = record.getManufacturerSpecificData();
|
if (data == null || data.size() == 0) return "无";
|
StringBuilder sb = new StringBuilder();
|
for (int i = 0; i < data.size(); i++) {
|
int id = data.keyAt(i);
|
byte[] bytes = data.valueAt(i);
|
sb.append(String.format("ID: 0x%04X, 数据: ", id));
|
sb.append(ByteUtils.byteArrayToHexString(bytes));
|
if (i < data.size() - 1) sb.append("\n");
|
}
|
return sb.toString();
|
}
|
|
public double calculateAccuracy(final int txPower, final double rssi) {
|
if (rssi == 0) {
|
return 0; // if we cannot determine accuracy, return -1.
|
}
|
|
final double ratio = rssi * 1.0 / txPower;
|
if (ratio < 1.0) {
|
return Math.pow(ratio, 10);
|
} else {
|
return (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
|
}
|
}
|
|
static class ViewHolder {
|
TextView deviceName;
|
TextView deviceAddress;
|
TextView rssi;
|
ImageView deviceIcon;
|
ImageView ivDown;
|
LinearLayout llMainContent;
|
LinearLayout llMoreInfo;
|
TextView tvDeviceType;
|
TextView tvAdvType;
|
TextView tvFlags;
|
TextView tvLocalName;
|
TextView tvTxPower;
|
TextView tvServiceUuids;
|
TextView tvServiceData;
|
TextView tvManufacturerData;
|
View connBtn;
|
}
|
|
public interface setOnItemButtonClick {
|
void buttonClick(View view, int position);
|
}
|
}
|