17

Goal: Build an Android app that discovers the names and addresses of BT devices within range and submits their values to a webservice. BT devices have not been previously bonded to the host device, I just want to poll everything as I walk about.

What I've done:

  1. Pored over documentation.
  2. Implemented a local instance of the host device's BT adapter.
  3. Implemented a notification to enable BT if it isn't enabled.
  4. Registered Broadcast Receivers and Intents to parse the ACTION_FOUNDs coming off of startDiscovery().
  5. Registered BLUETOOTH and BLUETOOTH_ADMIN permissions in the manifest.

Things work (as tested with incremental console logging) up until startDiscovery().


Frustration:

  • startDiscovery() -- I suspect I am passing this in the wrong context. What context does this method need to be placed within to function properly?

If you have been able to get this method working, I would very much appreciate your wisdom.

UPDATE - here's a stripped down simplified version of the code that is causing me grief; this simplification recapitulates my error. This code runs, it throws no cat.log errors or other errors, it simply doesn't give any output.

package aqu.bttest;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.Toast;

public class BT2Activity extends Activity {

private BluetoothAdapter mBTA;
private SingBroadcastReceiver mReceiver;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

  //register local BT adapter
    mBTA = BluetoothAdapter.getDefaultAdapter();
    //check to see if there is BT on the Android device at all
    if (mBTA == null){
        int duration = Toast.LENGTH_SHORT;
        Toast.makeText(this, "No Bluetooth on this handset", duration).show();
    }
    //let's make the user enable BT if it isn't already
    if (!mBTA.isEnabled()){
        Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBT, 0xDEADBEEF);
    }
    //cancel any prior BT device discovery
    if (mBTA.isDiscovering()){
        mBTA.cancelDiscovery();
    }
    //re-start discovery
    mBTA.startDiscovery();

    //let's make a broadcast receiver to register our things
    mReceiver = new SingBroadcastReceiver();
    IntentFilter ifilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    this.registerReceiver(mReceiver, ifilter);
}

private class SingBroadcastReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction(); //may need to chain this to a recognizing function
        if (BluetoothDevice.ACTION_FOUND.equals(action)){
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // Add the name and address to an array adapter to show in a Toast
            String derp = device.getName() + " - " + device.getAddress();
            Toast.makeText(context, derp, Toast.LENGTH_LONG);
        }
    }
}

}

Majid Golshadi
  • 2,576
  • 2
  • 17
  • 29
Lemminkainen
  • 175
  • 1
  • 1
  • 5
  • It would help to know the error you are getting... or at least what exactly is leading you to believe that `startDiscovery()` is functioning incorrectly. – Alex Lockwood May 12 '12 at 01:29

1 Answers1

22

What context does this method need to be placed within to function properly.

To put it simply, you should use startDiscovery() when you want your application to discover local Bluetooth devices... for instance, if you wanted to implement a ListActivity that scans and dynamically adds nearby Bluetooth devices to a ListView (see DeviceListActivity).

Your usage of the startDiscovery() method should look something like this:

  1. Define a class variable representing the local Bluetooth adapter.

    BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();
    
  2. Check to see if your device is already "discovering". If it is, then cancel discovery.

    if (mBtAdapter.isDiscovering()) {
        mBtAdapter.cancelDiscovery();
    }
    
  3. Immediately after checking (and possibly canceling) discovery-mode, start discovery by calling,

    mBtAdapter.startDiscovery();
    
  4. Be very careful in general about accidentally leaving your device in discovery-mode. Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources. For instance, you want to make sure you check/cancel discovery prior to attempting to make a connection. You most likely want to cancel discovery in your onDestroy method too.

Let me know if this helped... and if you are still having trouble, update your answer with your logcat output and/or any error messages you are getting, and maybe I can help you out a bit more.

Alex Lockwood
  • 81,274
  • 37
  • 197
  • 245
  • That helped. Also, passing results to an ArrayAdapter instead of a Toast definitely also helped. – Lemminkainen May 29 '12 at 21:33
  • is there any way to keep scanning continuous in BG service without put Timer...any system level API. – CoDe Jan 06 '14 at 06:26
  • @Shubh I don't think so. The reason why this restriction is put in place is to ensure that applications don't abuse `Bluetooth` by continuously scanning in the background. – Alex Lockwood Jan 06 '14 at 20:33
  • Very old... I am trying to do the same, but what could be the error ?- http://stackoverflow.com/questions/41987424/java-lang-securityexception-while-context-registerreceiver-in-uiautomator-ins – Rilwan Feb 01 '17 at 19:10