Pairing with Bluetooth Scanning device using Bluetooth Scanner API

EMDK For Android 7.1

Overview

This guide will walk you through creating an EMDK For Android application that will use Bluetooth Scanner API introduced in EMDK V 3.1, to perform pairing with Bluetooth Scanning device using Bluetooth Pairing Utility of Bluetooth Scanner API.

Note: The Bluetooth Scanner API is a part of Barcode API.

Initially, the Bluetooth Scanner is not connected to the device. So the Bluetooth Pairing Utility would turn ON the Bluetooth of the device where the app is running (Ex. TC55) if not already turned ON. Once that is done, the utility will ask you to scan a Barcode in the app using Bluetooth Scanner (Ex. RS507). After scanning the Barcode, the utility will start pairing process and pair the Bluetooth Scanning device (Ex. RS507) with your device where the app is running (Ex. TC55).

In this tutorial, we will explore the Bluetooth Scanner API by using it for developing a basic application that will pair the device with Bluetooth Scanner by allowing Bluetooth Scanner to scan the Barcode in the app through Bluetooth Pairing Utility.

Note: The Bluetooth Scanner API does not use Profile Wizard to pair with Bluetooth Scanner and everything needs to be configured programmatically through code.

Creating The Project

Note: Provide "BluetoothScannerTutorial" as the project name for this tutorial.

Start by creating a new Android Studio project.

Enabling Android Permissions

  1. Modify the Application's Manifest.xml to use the EMDK library and to set permission for the EMDK to scan the barcodes.

    img

    You must first enable permissions for 'com.symbol.emdk.permission.EMDK':

    
    <uses-permission android:name="com.symbol.emdk.permission.EMDK" /> 
    

    Then you must enable the library for EMDK:

    
    <uses-library android:name="com.symbol.emdk" />
    

    When done, your manifest.xml should look like:

    img

Adding Some Code

  1. Now we will start to add some code.

    First you must add references to the libraries:

    
    import com.symbol.emdk.EMDKManager;
    import com.symbol.emdk.barcode.BarcodeManager;  
    

    Then you must make the activity to implement EMDKListener.

    After that you also need to implement BarcodeManager.​ScannerConnectionListener, which is an interface to notify the client when the scanner device (Ex. RS507) has been connected or disconnected to the mobile device (Ex. TC55). Override its onConnectionChange method, which would be called when the scanner gets connected or disconnected to the mobile device.

    
    public class MainActivity extends Activity EMDKManager.EMDKListener, BarcodeManager.ScannerConnectionListener {  
    
    
    .. .. .. .. .. .. ...  
    
    @Override
    public void onOpened(EMDKManager emdkManager) {
    
    }
    
    @Override
    public void onClosed() {
    
    }
    
    @Override
    public void onConnectionChange(ConnectionStatus connectionStatus) {
    
    }  
    
    }

    We will now create some global variables to hold the instance objects of EMDKManager and BarcodeManager. These variables would be used throughout the code.

    We will then add some UI elements, which is just a TextView for notifying intermediate status operations performed during pairing.

    
    // Text View to display status during pairing operation
    private TextView statusView = null;
    
    // Declare a variable to store EMDKManager object
    private EMDKManager emdkManager = null;
    
    // Declare a variable to store Barcode Manager object
    private BarcodeManager barcodeManager = null;
    
    // Declare a variable to hold scanner device to scan
    private Scanner scanner = null;
    

    The code till here looks like:

    img

  2. Now, let us design a simple UI that has simply has a TextView to indicate status during pairing operation.

    So, remove all the code, inside "res/layout/activity_main.xml" and add following XML layout code for UI.

    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dip"
    tools:context=".MainActivity" >
    
      <TextView
       android:id="@+id/textViewStatus"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_centerInParent="true"
       android:text="" />
    
      <TextView
       android:id="@+id/textViewStatusTitle"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_above="@+id/textViewStatus"
       android:layout_centerHorizontal="true"
       android:layout_marginBottom="15dp"
       android:text="Status:" />
    
    </RelativeLayout>
    

    The layout should look like:

    img

  3. In the onCreate method, we take reference of UI elements that are declared in "res/layout/activity_main.xml" in order to use them in our Activity. We then call getEMDKManager so that the EMDK can be initialized and checked to see if it is ready.

    
    // Reference to UI elements
    statusView = (TextView) findViewById(R.id.textViewStatus);
    
    // The EMDKManager object will be created and returned in the callback.
    EMDKResults results = EMDKManager.getEMDKManager(
            getApplicationContext(), this);
    
    // Check the return status of getEMDKManager and update the status Text
    // View accordingly
    if (results.statusCode != EMDKResults.STATUS_CODE.SUCCESS) {
        statusView.setText("Status: "
                + "EMDKManager object request failed!");
    }
    

    So the complete onCreate method looks like:

    img

  4. Get the EMDK Manager in the onOpened method, update the StatusView TextView with a message and add the ScannerConnectionListener to get the Connected/Disconnected events between Bluetooth Scanner and Mobile by adding following code in onOpened method.

    
    // Update status view with EMDK Open Success message
    statusView.setText("Status: " + "EMDK open success!");
    
    this.emdkManager = emdkManager;
    // Get the Barcode Manager Instance
    barcodeManager = (BarcodeManager) emdkManager
            .getInstance(EMDKManager.FEATURE_TYPE.BARCODE);
    // Add the Scanner Connection Listener to receive Connected/Disconnected events
    if (barcodeManager != null) {
        barcodeManager.addConnectionListener(this);
    }
    
    // Initialize Scanner
    initScanner();
    

    The onOpened method should look like:

    img

  5. You will see error as we have not added initScanner method for initializing Bluetooth Scanner of our mobile device (Ex TC55). initScanner method gets the number of supported devices in a list.

    
    List<ScannerInfo> deviceList = barcodeManager
                .getSupportedDevicesInfo();
    

    It then iterates through this list of devices and checks one with "Bluetooth Scanner" by refering friendly name. If the list has Bluetooth Scanner device, it initializes Scanner object with Bluetooth Scanner.

    
    for (ScannerInfo scannerInfo : deviceList){
            if(scannerInfo.getFriendlyName().equalsIgnoreCase("Bluetooth Scanner"))
                scanner = barcodeManager.getDevice(scannerInfo);
    }
    

    If the Scanner Object is still null after iteration, your device doesn't support Bluetooth Scanner. Finally, we enable the Bluetooth Scanner.

    
    scanner.enable();
    

    So the complete source code for initScanner method would look like:

    
    // Initialize Bluetooth Scanner
    private void initScanner() {
    
    
    if (scanner == null) {
        // Get a list of supported scanner devices
        List&lt;ScannerInfo&gt; deviceList = barcodeManager
                .getSupportedDevicesInfo();
    
        // Iterate through Scanner devices and check if it supports Bluetooth Scanner
        for (ScannerInfo scannerInfo : deviceList){
            if(scannerInfo.getFriendlyName().equalsIgnoreCase("Bluetooth Scanner"))
                scanner = barcodeManager.getDevice(scannerInfo);
        }
        // If null, then your device does not support Bluetooth Scanner
        if(scanner == null) {
            statusView.setText("Bluetooth Scanner not supported!!!");
            return;
        }else{
            // Supports Bluetooth Scanner
            try {
                // Enable the Scanner
                scanner.enable();
            } catch (ScannerException e) {
                statusView.setText("Status: " + e.getMessage());
            }
        }
    }
    
    }

    This should look like:

    img

  6. Now, we will add a method to de-initialize the Scanner named deInitScanner. This method will perform following operations in the same sequence.

    • Cancel any pending read operations.
    • Disable the Scanner.
    • Release the Scanner resource.
    • Eventually set the Scanner object to null.

    The source code for deInitScanner method should look like:

    
    // DeInitialize Scanner
    private void deInitScanner() {
        if (scanner != null) {
            try {
                // Cancel pending reads
                scanner.cancelRead();
                // Disable Scanner
                scanner.disable();
                // Release Scanner
                scanner.release();
    
    
        } catch (ScannerException e) {
            statusView.setText("Status: " + e.getMessage());
        }
    
        scanner = null;
    }
    
    }

    The method should look like:

    img

  7. Let's add an AsyncTask for asynchronously updating the StatusView. This would be useful in the onConnectionChange callback method that updates the status to Connected/Disconnected depending upon the result. So AsyncStatusUpdate is an AsyncTask that would simply update the Status View with following code.

    
    // AsyncTask for Updating Status in statusView during pairing operation
    private class AsyncStatusUpdate extends AsyncTask<String, Void, String> {
    
    
    @Override
    protected String doInBackground(String... params) {
        return params[0];
    }
    
    @Override
    protected void onPostExecute(String result) {
        // Update Status View
        statusView.setText("Status: " + result);
    }
    
    }

    The AsyncStatusUpdate should look like:

    img

  8. We would now add the code to update statusView in onConnectionChange callback method. This method would be invoked when the scanner device has been connected or disconnected to the mobile device.

    So we will first get the connection state and friendly name of the Scanner device received through onConnectionChange callback method.

    
    // Returns the Connection State for Bluetooth Scanner through callback
    String statusBT = connectionStatus.getConnectionState().toString();
    // Returns the Friendly Name of the Scanner through callback
    String scannerNameBT = connectionStatus.getScannerInfo()
            .getFriendlyName(); 
    

    If the friendly name is "Bluetooth Scanner", then we would update the statusView with the Scanner Name and its state.

    Later, if the state is CONNECTED, we would invoke initScanner method and deInitScanner method for the DISCONNECTED state.

    So the source code for onConnectionChange callback method with the above mentioned steps would look like:

    
    @Override
    public void onConnectionChange(ConnectionStatus connectionStatus) {
        String status = "";
        String scannerName = "";
    
    
    // Returns the Connection State for Bluetooth Scanner through callback
    String statusBT = connectionStatus.getConnectionState().toString();
    // Returns the Friendly Name of the Scanner through callback
    String scannerNameBT = connectionStatus.getScannerInfo()
            .getFriendlyName();
    
    // Get the friendly name of our device's Scanner
    scannerName = scanner.getScannerInfo().getFriendlyName();
    
    // Check for the Bluetooth Scanner
    if (scannerName.equalsIgnoreCase(scannerNameBT)) {
        // If Bluetooth Scanner, update the status view
        status = scannerNameBT + ":" + statusBT;
        new AsyncStatusUpdate().execute(status);
        // Initialize or De-Initialize Bluetooth Scanner
        // device based on Connection State
        switch (connectionStatus.getConnectionState()) {
            case CONNECTED:
                // Initialize Scanner
                initScanner();
                break;
            case DISCONNECTED:
                // De-Initialize Scanner
                deInitScanner();
                break;
        }
    }
    
    }

    The onConnectionChange method should look like:

    img

  9. Finally, release all the resources in onClosed method. So it would remove the ScannerConnectionListener and release the EMDKManager using following code.

    
    @Override
    public void onClosed() {
        if (emdkManager != null) {
            // Remove the connection listener
            if (barcodeManager != null) {
                barcodeManager.removeConnectionListener(this);
            }
            // Release EMDK Manager
            emdkManager.release();
            emdkManager = null;
        }
        statusView
                .setText("Status: "
                        + "EMDK closed unexpectedly! Please close and restart the application.");
    } 
    

    The onClosed method should look like:

    img

That's it!!! We are done with all the coding part that will let us perform pairing with Bluetooth Scanning device using Bluetooth Pairing Utility of Bluetooth Scanner API introduced in EMDK V 3.1. Now let us run the application.

Running the Application

  1. Connect the device (having latest EMDK runtime) to USB port.

    Note:
    Make sure the device is in USB debug.

  2. Run the application.

    Note: Initially the bluetooth of the device is turned OFF.

    img

    So it displays a Toast saying bluetooth scanner is not connected, which would start Bluetooth Pairing Utility to pair devices.

  3. It will first ask you to enable the Bluetooth of the device.

    img

  4. Click "Allow" and the Bluetooth Scanning Utility would turn your device's Bluetooth ON.

    img

  5. It would display a screen with a Barcode, which needs to be scanned to pair with this device.

    img

  6. You can take a Bluetooth Scanning device (Ex RS507) and scan the Barcode shown on the screen of your app (App is on TC55) and Bluetooth Scanning Utility would pair these two devices.

    img

  7. You can see a Toast confirming that the two devices (TC55 & RS507) have been paired and connected to each other along with the updated status on statusView.

  8. Now, lets check under Bluetooth Settings of the Mobile device (TC55) for further confirmation. So go to device's Settings -> Bluetooth.

    img

  9. You can see RS507 under Paired devices that further confirms pairing. This is how we can perform pairing of Mobile device (Ex. TC55) with Bluetooth Scanning device (Ex. RS507) using Bluetooth Pairing Utility of Bluetooth Scanner API

Important Programming Tips

  1. It is required to do the following changes in the application's AndroidManifest.xml:

    Note:

    • Include the permission for EMDK:
    
    <uses-permission android:name="com.symbol.emdk.permission.EMDK"/>
    

    Note:

    • Use the EMDK library:
    
    <uses-library android:name="com.symbol.emdk"/>
    
  2. Installing the EMDK for Android application without deploying the EMDK runtime on the Symbol device will fail because of missing shared library on the device.

What's Next

Now that you have learned how to perform pairing with Bluetooth Scanning device using Bluetooth Pairing Utility of Bluetooth Scanner API, in the next tutorial we would concentrate on ScanAndPair APIs and develop an application to demonstrate its use.