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 { 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, null); 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); view.findViewById(R.id.conn_btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onItemButtonClick.buttonClick(view, position); } }); view.setTag(viewHolder); } else { viewHolder = (ViewHolder) view.getTag(); } 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 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 serviceData = record.getServiceData(); if (serviceData != null && !serviceData.isEmpty()) { StringBuilder sb = new StringBuilder("服务数据: "); for (Map.Entry 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 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; } public interface setOnItemButtonClick { void buttonClick(View view, int position); } }