JuiCe
JuiCe

Reputation: 4191

Finding UUIDs in Android 2.0

I am writing a program which needs to be run in Android 2.0. I am currently trying to connect my android device to an embedded bluetooth chip. I have been given information as to use fetchuidsWithSDP(), or getUuids(), but the page I read explained that these methods are hidden in the 2.0 SDK, and must be called using reflection. I have no idea what that means and there is no explanation. There is example code given, but very little explanation behind it. I was hoping someone could help me understand what is actually going on here, as I am very new to Android development.

String action = "android.bleutooth.device.action.UUID";
IntentFilter filter = new IntentFilter( action );
registerReceiver( mReceiver, filter );

The page I read also says that in the first line bluetooth is spelled "bleutooth" on purpose. If anyone can explain that, I would appreciate that as well as it makes no sense to me, unless the developers made a typo.

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive( Context context, Intent intent ) {
    BluetoothDevice deviceExtra = intent.getParcelableExtra("android.bluetooth.device.extra.Device");
    Parcelable[] uuidExtra = intent.getParcelableArrayExtra("android.bluetooth.device.extra.UUID");
}

};

I am having trouble grasping how exactly I find the correct UUID for my embedded bluetooth chip. If anyone could help it'd be greatly appreciated.

EDIT: I am going to add the rest of my onCreate() method so you can see what I'm working with.

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set up window View
    setContentView(R.layout.main);

    // Initialize the button to scan for other devices.
    btnScanDevice = (Button) findViewById( R.id.scandevice );

    // Initialize the TextView which displays the current state of the bluetooth
    stateBluetooth = (TextView) findViewById( R.id.bluetoothstate );
    startBluetooth();

    // Initialize the ListView of the nearby bluetooth devices which are found.
    listDevicesFound = (ListView) findViewById( R.id.devicesfound );
    btArrayAdapter = new ArrayAdapter<String>( AndroidBluetooth.this,
            android.R.layout.simple_list_item_1 );
    listDevicesFound.setAdapter( btArrayAdapter );

    CheckBlueToothState();

    // Add an OnClickListener to the scan button.
    btnScanDevice.setOnClickListener( btnScanDeviceOnClickListener );

    // Register an ActionFound Receiver to the bluetooth device for ACTION_FOUND
    registerReceiver( ActionFoundReceiver, new IntentFilter( BluetoothDevice.ACTION_FOUND ) );

    // Add an item click listener to the ListView
    listDevicesFound.setOnItemClickListener( new OnItemClickListener()
    {
      public void onItemClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) 
      {
          // Save the device the user chose.
          myBtDevice = btDevicesFound.get( arg2 );

          // Open a socket to connect to the device chosen.
          try {
              btSocket = myBtDevice.createRfcommSocketToServiceRecord( MY_UUID );
          } catch ( IOException e ) {
              Log.e( "Bluetooth Socket", "Bluetooth not available, or insufficient permissions" );
          } catch ( NullPointerException e ) {
              Log.e( "Bluetooth Socket", "Null Pointer One" );
          }

          // Cancel the discovery process to save battery.
          myBtAdapter.cancelDiscovery();

          // Update the current state of the Bluetooth.
          CheckBlueToothState();

          // Attempt to connect the socket to the bluetooth device.
          try {
              btSocket.connect();                 
              // Open I/O streams so the device can send/receive data.
              iStream = btSocket.getInputStream();
              oStream = btSocket.getOutputStream();
          } catch ( IOException e ) {
              Log.e( "Bluetooth Socket", "IO Exception" );
          } catch ( NullPointerException e ) {
              Log.e( "Bluetooth Socket", "Null Pointer Two" );
          }
      } 
  });
}

Upvotes: 1

Views: 5345

Answers (2)

Vineeth Kartha
Vineeth Kartha

Reputation: 11

I also faced the same issue and this is how I solved it for Android 2.3.3. I think the same solution will work for android 2.2 also.

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @SuppressLint("NewApi")
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        // When discovery finds a device
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            Toast.makeText(getApplicationContext(),"Device: "+device.getName(),Toast.LENGTH_SHORT).show();
            devices.add(device.getName() + "\n" + device.getAddress());
            list.add(device);

        }
        else if(BluetoothDevice.ACTION_UUID.equals(action)){
            Toast.makeText(getApplicationContext(),"I am Here",Toast.LENGTH_SHORT).show();
        }
        else {
            if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                Toast.makeText(getApplicationContext(),"Done Scanning..",Toast.LENGTH_SHORT).show();
                Iterator<BluetoothDevice> itr = list.iterator();
                while(itr.hasNext())
                {
                    BluetoothDevice dev=itr.next();
                    if(dev.fetchUuidsWithSdp())
                    {
                        Parcelable a[]=dev.getUuids();
                        Toast.makeText(getApplicationContext(),dev.getName()+":"+a[0],Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }       
    }
};

Upvotes: -1

devunwired
devunwired

Reputation: 63293

You're probably better off using the synchronous version so you don't have to deal with all the moving parts of setting up the BroadcastReceiver. Since you are always doing this on the heels of discovery, the cached data will always be fresh.

Here the functionality of getting the UUID data encapsulated up into a method. This code was in one of the comments of the blog post you linked:

//In SDK15 (4.0.3) this method is now public as
//Bluetooth.fetchUuisWithSdp() and BluetoothDevice.getUuids()
public ParcelUuid[] servicesFromDevice(BluetoothDevice device) {
    try {
        Class cl = Class.forName("android.bluetooth.BluetoothDevice");
        Class[] par = {};
        Method method = cl.getMethod("getUuids", par);
        Object[] args = {};
        ParcelUuid[] retval = (ParcelUuid[]) method.invoke(device, args);
        return retval;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

You can then call this method anywhere in your code, passing it a BluetoothDevice and getting back an array of UUIDs for that device's services (typically for small embedded stacks the array is only 1 item); something like:

  // Save the device the user chose.
  myBtDevice = btDevicesFound.get( arg2 );
  //Query the device's services
  ParcelUuid[] uuids = servicesFromDevice(myBtDevice);

  // Open a socket to connect to the device chosen.
  try {
      btSocket = myBtDevice.createRfcommSocketToServiceRecord(uuids[0].getUuid());
  } catch ( IOException e ) {
      Log.e( "Bluetooth Socket", "Bluetooth not available, or insufficient permissions" );
  } catch ( NullPointerException e ) {
      Log.e( "Bluetooth Socket", "Null Pointer One" );
  }

in the block you posted above.

As a side note, calling all this code in the manner you have will make your application sad later. The block of code calling connect() and obtaining the streams should be done on a background thread because that method will block for a period of time and calling this code on the main thread will freeze your UI temporarily. You should move that code into an AsyncTask or a Thread like the BluetoothChat sample in the SDK does.

HTH

Upvotes: 5

Related Questions