安卓.如何将UUID信标值设置为正确的textview? [英] Android. How do I set UUID Beacon value to proper textview?

查看:66
本文介绍了安卓.如何将UUID信标值设置为正确的textview?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个愚蠢的问题,但是我有一个代码可以向我提供信标的列表,以及它们在TextView中的名称,地址,uuid,主要和次要信息.我正在计算uuid,主要和次要值(在下面的代码中).当我将这三个值设置为TextView时,它们正在与其他信标值交换.所以我的问题是,如何为适当的信标设置适当的uuid,主要和次要值?

This is a silly question, but I have a code which is giving me list of beacons with their names, addresses, uuids, majors and minors in TextView. I'm calculating uuid, major and minor values(in code below). And when I'm setting these three values into TextView they are swaping with other beacon values. So my question is, how do I set proper uuid, major and minor value to the proper beacon?

链接示例: http://i.stack.imgur.com/vlepI.jpg

我有两个信标.名称和地址是正确的,但是如您所见,uuid,major minor是相同的,并且在扫描过程中它们一直在相互交换信标值.

I have got two beacons. Names and adresses are correct, but as you can see uuid, major minor are the same and during scanning they keep swapping with each other beacon values.

代码在下面给出.

DeviceScanActivity

public class DeviceScanActivity extends ListActivity {

private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
private static final long SCAN_PERIOD = 10000;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getActionBar().setTitle(R.string.title_devices);
    mHandler = new Handler();

    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
        finish();
    }

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();

    if (mBluetoothAdapter == null) {
        Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
        finish();
        return;
    }
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.menu_scan:
            mLeDeviceListAdapter.clear();
            scanLeDevice(true);
            break;
        case R.id.menu_stop:
            scanLeDevice(false);
            break;
    }
    return true;
}

@Override
protected void onResume() {
    super.onResume();

    if (!mBluetoothAdapter.isEnabled()) {
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
    }

    mLeDeviceListAdapter = new LeDeviceListAdapter();
    setListAdapter(mLeDeviceListAdapter);
    scanLeDevice(true);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // User chose not to enable Bluetooth.
    if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
        finish();
        return;
    }
    super.onActivityResult(requestCode, resultCode, data);
}

@Override
protected void onPause() {
    super.onPause();
    scanLeDevice(false);
    mLeDeviceListAdapter.clear();
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
    if (device == null) return;
    //final Intent intent = new Intent(this, DeviceControlActivity.class);

    if (mScanning) {
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
        mScanning = false;
    }
    //startActivity(intent);
}

private void scanLeDevice(final boolean enable) {
    if (enable) {
        // Stops scanning after a pre-defined scan period.
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                invalidateOptionsMenu();
            }
        }, SCAN_PERIOD);

        mScanning = true;
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
    invalidateOptionsMenu();
}

private class LeDeviceListAdapter extends BaseAdapter {
    private ArrayList<BluetoothDevice> mLeDevices;
    private LayoutInflater mInflator;

    public LeDeviceListAdapter() {
        super();
        mLeDevices = new ArrayList<BluetoothDevice>();
        mInflator = DeviceScanActivity.this.getLayoutInflater();
    }

    public void addDevice(BluetoothDevice device) {
        if(!mLeDevices.contains(device)) {
            mLeDevices.add(device);
        }
    }

    public BluetoothDevice getDevice(int position) {
        return mLeDevices.get(position);
    }

    public void clear() {
        mLeDevices.clear();
    }

    @Override
    public int getCount() {
        return mLeDevices.size();
    }

    @Override
    public Object getItem(int i) {
        return mLeDevices.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;
        if (view == null) {
            view = mInflator.inflate(R.layout.listitem_device, null);
            viewHolder = new ViewHolder();
            viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
            viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
            viewHolder.deviceUUID = (TextView) view.findViewById(R.id.device_uuid);
            viewHolder.deviceMajor = (TextView) view.findViewById(R.id.device_major);
            viewHolder.deviceMinor = (TextView) view.findViewById(R.id.device_minor);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }

        BluetoothDevice device = mLeDevices.get(i);
        final String deviceName = device.getName();
        if (deviceName != null && deviceName.length() > 0)
            viewHolder.deviceName.setText(deviceName);
        else
            viewHolder.deviceName.setText(R.string.unknown_device);
       viewHolder.deviceAddress.setText(device.getAddress());
        viewHolder.deviceUUID.setText(uuid);
        viewHolder.deviceMajor.setText(major);
        viewHolder.deviceMinor.setText(minor);

        return view;
    }
}

public String uuid;
public int major_temp;
public int minor_temp;
public String major;
public String minor;


public static final char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

public BluetoothAdapter.LeScanCallback mLeScanCallback =
        new BluetoothAdapter.LeScanCallback() {

    @Override
    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mLeDeviceListAdapter.addDevice(device);
                mLeDeviceListAdapter.notifyDataSetChanged();
            }
        });

        int startByte = 2;
        boolean patternFound = false;
        while (startByte <= 5) {
            if (    ((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
                    ((int) scanRecord[startByte + 3] & 0xff) == 0x15) { //Identifies correct data length
                patternFound = true;
                break;
            }
            startByte++;
        }

        if (patternFound) {
            byte[] uuidBytes = new byte[16];
            System.arraycopy(scanRecord, startByte+4, uuidBytes, 0, 16);
            String hexString = bytesToHex(uuidBytes);

                //Here is your UUID
                uuid =  hexString.substring(0,8) + "-" +
                        hexString.substring(8,12) + "-" +
                        hexString.substring(12,16) + "-" +
                        hexString.substring(16,20) + "-" +
                        hexString.substring(20,32);

            major_temp = (scanRecord[startByte+20] & 0xff) * 0x100 + (scanRecord[startByte+21] & 0xff);
            major = Integer.toString(major_temp);
            minor_temp = (scanRecord[startByte+22] & 0xff) * 0x100 + (scanRecord[startByte+23] & 0xff);
            minor = Integer.toString(minor_temp);
          //   TextView textView1 = (TextView) findViewById(R.id.device_uuid);
            // textView1.setText(uuid+" Major: " + major + " Minor: " + minor);


        }

    }

};

static class ViewHolder {
    TextView deviceName;
    TextView deviceAddress;
    TextView deviceUUID;
    TextView deviceMajor;
    TextView deviceMinor;
}

}

和布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
    <TextView android:id="@+id/device_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="24dp"/>
    <TextView android:id="@+id/device_address"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="12dp"/>
    <TextView android:id="@+id/device_uuid"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="12dp"/>
    <TextView android:id="@+id/device_major"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="12dp"/>
    <TextView android:id="@+id/device_minor"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="12dp"/>
</LinearLayout>

推荐答案

如何处理找到的信标有问题.只需仔细查看一下,您在哪里为UUID分配了任何值(主要和次要),以及分配给ListAdapter的内容.

There's a problem in how you handle the beacons found. Just take a careful look at where you assign any value for the UUID, major and minor and what goes to the ListAdapter.

在您的 LeScanCallback 中,将找到的所有Bluetooth LE设备添加到列表适配器中.您将它们添加为 BluetoothDevice ,它只是一个通用模型,对iBeacon特定的UUID(主要和次要)一无所知.

In your LeScanCallback you add any found Bluetooth LE devices into the list adapter. You add them as a BluetoothDevice which is just a generic model and knows nothing about the iBeacon specific UUID, major and minor.

然后将UUID(主要和次要)提取到类的成员变量中.当找到的 BluetoothDevice 被识别为iBeacon时,始终执行此操作.在任何时候,您都只存储主要的和次要的 UUID一套.它们始终是找到的最新iBeacon的值.

You then exctract the UUID, major and minor into member variables of the class. This is done always when the found BluetoothDevice is recognised as an iBeacon. At any time you are storing just one set of UUID, major and minor. They are always values of the latest iBeacon found.

因此,如果您不希望以后再进行任何距离估算,则可以创建一个简单的类来表示iBeacon,该类具有UUID,主要,次要以及RSSI和TxPower,而不是具有BluetoothDevices列表.然后,在扫描回调中,不要将BluetoothDevices添加到列表中,而是在模式检查代码的末尾添加iBeacons.像这样:

So instead of having a list of BluetoothDevices you could create a simple class representing an iBeacon with the UUID, major, minor and maybe RSSI and TxPower if you want to do any distance estimation later on. Then in the scan callback do not add BluetoothDevices to the list but add iBeacons at the end of the pattern checking code. Something like:

public BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

    @Override
    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
        /* Remove:
        runOnUiThread(new Runnable() {
        @Override
            public void run() {
                mLeDeviceListAdapter.addDevice(device);
                mLeDeviceListAdapter.notifyDataSetChanged();
            }
        });
        */
        int startByte = 2;
        boolean patternFound = false;
        while (startByte <= 5) {
            if (((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
                    ((int) scanRecord[startByte + 3] & 0xff) == 0x15) { //Identifies correct data length
                patternFound = true;
                break;
            }
            startByte++;
        }

        if (patternFound) {
            byte[] uuidBytes = new byte[16];
            System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);
            String hexString = bytesToHex(uuidBytes);

            //Here is your UUID
            uuid = hexString.substring(0, 8) + "-" +
                    hexString.substring(8, 12) + "-" +
                    hexString.substring(12, 16) + "-" +
                    hexString.substring(16, 20) + "-" +
                    hexString.substring(20, 32);

            major_temp = (scanRecord[startByte + 20] & 0xff) * 0x100 + (scanRecord[startByte + 21] & 0xff);
            major = Integer.toString(major_temp);
            minor_temp = (scanRecord[startByte + 22] & 0xff) * 0x100 + (scanRecord[startByte + 23] & 0xff);
            minor = Integer.toString(minor_temp);

            // Add:
            IBeacon iBeacon = new IBeacon(uuid, major, minor);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mLeDeviceListAdapter.addDevice(iBeacon);
                    mLeDeviceListAdapter.notifyDataSetChanged();
                }
            });
        }
    }
}

然后将您的列表适配器更改为使用iBeacon对象而不是BluetoothDevice对象,并在getView()中修复您的代码.目前,您从所说的成员变量中读取UUID,主要和次要,它们始终具有找到的最新iBeacon的值.

Then change your list adapter to use iBeacon objects and not BluetoothDevice objects and fix your code in getView(). At the moment you read the UUID, major and minor from the said member variables where they always have the values of the latest iBeacon found.

因此,请从现在包含iBeacon对象的mLeDevices列表中读取值.像这样:

So instead read the values from the mLeDevices list which now holds iBeacon objects. Something like:

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    ViewHolder viewHolder;
    if (view == null) {
        view = mInflator.inflate(R.layout.listitem_device, null);
        viewHolder = new ViewHolder();
        viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
        viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
        viewHolder.deviceUUID = (TextView) view.findViewById(R.id.device_uuid);
        viewHolder.deviceMajor = (TextView) view.findViewById(R.id.device_major);
        viewHolder.deviceMinor = (TextView) view.findViewById(R.id.device_minor);
        view.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) view.getTag();
    }

    BluetoothDevice device = mLeDevices.get(i);
    final String deviceName = device.getName();
    if (deviceName != null && deviceName.length() > 0) {
        viewHolder.deviceName.setText(deviceName);
    }
    else {
        viewHolder.deviceName.setText(R.string.unknown_device);
    }
    viewHolder.deviceAddress.setText(device.getAddress());
    // Change these:
    viewHolder.deviceUUID.setText(device.getUuid);
    viewHolder.deviceMajor.setText(device.getMajor);
    viewHolder.deviceMinor.setText(device.getMinor);

    return view;
}

然后,您需要修改列表适配器的addDevice以比较IBeacon对象而不是BluetoothDevice对象.

You would then need to modify your list adapter's addDevice to compare IBeacon objects instead of BluetoothDevice objects.

public void addDevice(IBeacon device) {
    // This probably won't without some extra work:        
    if(!mLeDevices.contains(device)) {
        mLeDevices.add(device);
    }
}

这篇关于安卓.如何将UUID信标值设置为正确的textview?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆