A Comprehensive Scanning Example

Blog Post 4: Comprehensive Scanning

In this series of posts I’m describing the implementation of an Android application that scans for BLE devices and displays the result in a list. In this post I’ve started a new GitHub Repo to contain the code because the code is getting more comprehensive and I wanted to keep my simple application. The code for the application is here. The basic application works the same as the original, it just has more features and more code.

I’ve written several BLE Apps. With most devices, the advertisement is not what a device is all about. Normally its the Services and Characteristics you are after, not the advertisement. I’ve done lots of work to read and write characteristics, but I’ve never really delved into all the intricacies of a devices advertisement(s). Thats what this post is about.

I’ve modified the App in a couple of ways. Now when a scan finds a device, the app displays a little more information for the device. See the screenshot below. All the information we show on this screen comes form the BluetoothDevice that is returned on the BluetoothAdapter.LeScanCallback. bleexample2.png

Here’s the adapter code that creates each table entry for the scan. Its found in the ScanActivity Class. Notice that almost all the data displayed comes from the BluetoothDevice and not the advertisement. References to the device are in turquoise and references to the advertisement are in red. Notice the use of the class BleUtility. This utility class has lots of methods for formatting various standard numbers, characteristics and services published by the Bluetooth.org.

 @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null){
      convertView = inflater.inflate(R.layout.device_item, null);
    }
    DeviceScanData data = this.getItem(position);
    BluetoothDevice device = data.getDevice();
    TextView nameTextView = (TextView) convertView.findViewById(R.id.tvName);

    if (device.getName() != null){
      nameTextView.setText(device.getName());
    } else {
      nameTextView.setText("Name not Present");
    }

    TextView companyTextView = (TextView) convertView.findViewById(R.id.tvCompanyName);
    TextView beaconTextView = (TextView) convertView.findViewById(R.id.tvBeacon);

    // do we recognize as beacon
    IBeaconAdvertisement beacon = data.getAdvertisement().getBeacon();
    if (beacon != null){
      beaconTextView.setVisibility(View.VISIBLE);
    } else {
      beaconTextView.setVisibility(View.GONE);
    }
    companyTextView.setText(data.getAdvertisement().getCompany());

    TextView viewAddress = (TextView) convertView.findViewById(R.id.tvDeviceAddress);
    TextView viewBluetoothClass = (TextView) convertView.findViewById(R.id.tvBluetoothClass);
    TextView viewBondState = (TextView) convertView.findViewById(R.id.tvBondState);
    TextView viewType = (TextView) convertView.findViewById(R.id.tvType);

    viewAddress.setText(device.getAddress());

    String deviceClass = BleUtility.formatDeviceClass(device.getBluetoothClass().getMajorDeviceClass());
    viewBluetoothClass.setText(deviceClass);

    String bond = BleUtility.formatBondState(device.getBondState());
    viewBondState.setText(bond);

    String type = BleUtility.formatDeviceType(device.getType());
    viewType.setText(type);
    return convertView;

  }
}

When a row in the table is tapped, a new activity will be launched to show as much detail as possible on the device advertisement. The activity layout is found in activity_ble_advertisement.xml. This layout has lots of controls. I’ve tried to create a set of layouts for every possible data that *might* appear in a device advertisement. Of course most of the data is not found in a specific device advertisement. So one of the main jobs of BleAdvertisementActivity is to hide all they layouts that don’t have any data. In practice most device advertisements have only a very small amount of data. Here’s a screenshot of a Apple IBeacon Advertisment.

ibeacon.png

Here’s a snapshot of a Fitbit Advertisement.

fitbit.png

Ive talke about most of the classes for this example in previous posts, but a new class the I’ve added specifically for this example is BleUtility. Its a utility classs with all the following

  • Format types for all BLE characteristics
  • UUIDs for all the standard BLE Services and a name<->UUID mapping
  • UUIDs for all the standard BLE Characteristics and a name<->UUID mapping
  • A Complete, program readable type map for all the standard Characteristics
  • Formatting routines to produce readable strings from Bluetooth BondState codes, Status codes, etc.

Of all the pieces of code in this example BleUtility has the most value. Feel free to use.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s