i want to search and listing bluetooth devices in android, my program now able to list all the active devices but not able to send pairing request to the other devices .I want to implement this onItemClick of list element.And also if bluetooth is not enabled of my device then show a permission to active device,if i go for yes then ok,but if i go for no then permission show again until i press yes..how can i do this?plz help with code..here is my code..
public class Main extends Activity {
TextView out;
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter btAdapter;
private ArrayList<BluetoothDevice> btDeviceList = new ArrayList<BluetoothDevice>();
private ArrayList<String> mylist= new ArrayList<String>();
private ListView lv;
private Button btn;
public Parcelable[] uuidExtra;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void search(View view)
{
//Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_UUID);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(ActionFoundReceiver, filter); // Don't forget to unregister during onDestroy
// Getting the Bluetooth adapter
btAdapter = BluetoothAdapter.getDefaultAdapter();
Toast.makeText(getApplicationContext(),"\nAdapter: " + btAdapter,5000).show();
CheckBTState();
}
private void setDeviceList(ArrayList<String> list) {
lv = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> adapter= new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,list);
lv.setAdapter(adapter);
}
/* This routine is called when an activity completes.*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENABLE_BT) {
CheckBTState();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (btAdapter != null) {
btAdapter.cancelDiscovery();
}
unregisterReceiver(ActionFoundReceiver);
}
private void CheckBTState() {
// Check for Bluetooth support and then check to make sure it is turned on
// If it isn't request to turn it on
// List paired devices
// Emulator doesn't support Bluetooth and will return null
if(btAdapter==null) {
Toast.makeText(getApplicationContext(),"\nBluetooth NOT supported. Aborting.",5000).show();
return;
} else {
if (btAdapter.isEnabled()) {
Toast.makeText(getApplicationContext(),"\nBluetooth is enabled...",5000).show();
// Starting the device discovery
btAdapter.startDiscovery();
} else if (!btAdapter.isEnabled()){
Intent enableBtIntent = new Intent(btAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
/* else{
Intent intent = new Intent(btAdapter.ACTION_STATE_CHANGED);
startActivityForResult(intent, RESULT_CANCELED);
}*/
}
}
private final BroadcastReceiver ActionFoundReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Toast.makeText(getApplicationContext(),"\n Device: " + device.getName() + ", " + device,5000).show();
mylist.add(device.getName());
setDeviceList(mylist);
} else {
if(BluetoothDevice.ACTION_UUID.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
for (int i=0; i<uuidExtra.length; i++) {
Toast.makeText(getApplicationContext(),"\n Device: " + device.getName() + ", " + device + ", Service: " + uuidExtra[i].toString(),5000).show();
}
} else {
if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Toast.makeText(getApplicationContext(),"\nDiscovery Started...",5000).show();
} else {
if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Toast.makeText(getApplicationContext(),"\nDiscovery Finished",5000).show();
Iterator<BluetoothDevice> itr = btDeviceList.iterator();
while (itr.hasNext()) {
// Get Services for paired devices
BluetoothDevice device = itr.next();
Toast.makeText(getApplicationContext(),"\nGetting Services for " + device.getName() + ", " + device,5000).show();
if(!device.fetchUuidsWithSdp()) {
Toast.makeText(getApplicationContext(),"\nSDP Failed for " + device.getName(),5000).show();
}
}
}
}
}
}
}
};
}
It's too late but here is code -> You need to use background thread to connect with bluetooth device as a client. and UUID is Universal Uniquely identification you can use online UUID generator. for secure connections and then get socket with device and connect with it;
ConnectWithDevice(context : ConnectWithBluetooth, device : BluetoothDevice) : Thread(){
private val mContext : ConnectWithBluetooth = context
private val mmSocket : BluetoothSocket
private val mmDevice : BluetoothDevice
// Default UUID
private val mmDefaultUUID = UUID.fromString("78c374fd-f84d-4a9e-aa5b-9b0b6292952e")
init {
var temp : BluetoothSocket? = null
mmDevice = device
try {
// Try here device.createInsecureConnect if it's work then start with this;
temp = device.createRfcommSocketToServiceRecord(mmDevice.uuids[0].uuid)
}catch (en : NullPointerException){
en.printStackTrace()
// Try here device.createInsecureConnect if it's work then start with this;
temp = device.createRfcommSocketToServiceRecord(mmDefaultUUID)
}catch (e : IOException){
e.printStackTrace()
Log.e("TAG","Socket's create() method failed",e)
}
mmSocket = temp!!
Log.i("TAG","Got the Socket")
}
override fun run() {
// Cancel discovery because it otherwise slows down the connection.
if(mContext.bluetoothAdapter != null){
mContext.bluetoothAdapter!!.cancelDiscovery()
}
try{
// Connect to the remote device through the socket. This call blocks
// until it succeeds or throws an exception.
Log.i("TAG","Connecting...")
mmSocket.connect()
Log.i("TAG","Bluetooth Successfully Connected")
}catch (connectException : IOException){
// Unable to connect; close the socket and return.
try{
mmSocket.close()
}catch (closeException : IOException){
Log.e("TAG","Could not close the client socket",closeException)
}
return
}
// The connection attempt succeeded. Perform work associated with
// the connection in a separate thread.
Log.i("TAG","Device is Connected")
//manageMyConnectedSocket(mmSocket)
}
// Closes the client socket and causes the thread to finish.
// Call this method from the main activity to shut down the connection.
fun cancel(){
try {
mmSocket.close()
} catch (e: IOException) {
Log.e(ContentValues.TAG, "Could not close the client socket", e)
}
}
}
Related
I create app which work with bluetooth and almost everything is ok but one this is not cool. So after I connect device do some staff save everything them disconnect it, my app stops seeing this device is no more on my list, but after 5-10 minutes device back on the list. What can be the issue?
public class MainActivity extends AppCompatActivity {
static final int SEND_TIMES = 1;
static final int SEND_DATE = 2;
List<BluetoothDevice> devices;
Spinner devicesSpinner = null;
BluetoothAdapter bluetoothAdapter = null;
BluetoothSocket clientSocket = null;
OutputStream outputData = null;
InputStream inputData = null;
List<String> devicesNames = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!bluetoothAdapter.isEnabled()) {
Intent enableRequest = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(enableRequest);
}
findDevices();
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(deviceFoundReceiver, filter);
registerReceiver(bondStateChangeReceiver, filter);
devices = new ArrayList();
devicesSpinner = findViewById(R.id.devices_list);
devicesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
try {
if(devices.get(i) == null)
return;
BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(devices.get(i).getAddress());
Method m = remoteDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
clientSocket = (BluetoothSocket) m.invoke(remoteDevice, 1);
outputData = clientSocket.getOutputStream();
inputData = clientSocket.getInputStream();
} catch (Exception e){
Log.i("REMOTE_DEVICE", "No such a method", e);
}
}
#Override
public void onNothingSelected (AdapterView<?> adapterView){
}
});
if(clientSocket != null)
Toast.makeText(this, "" + clientSocket.isConnected(), Toast.LENGTH_LONG);
}
public void connectDevice(View view) throws IOException {
if (isSocketConnected()) return;
bluetoothAdapter.cancelDiscovery();
if(!clientSocket.isConnected()){
try {
clientSocket.connect();
} catch (Exception e){
Toast.makeText(this, "Can not connect to this device try later!", Toast.LENGTH_LONG).show();
return;
}
TextView textView = (TextView) findViewById(R.id.boundedDevice);
textView.setText(clientSocket.getRemoteDevice().getName());
}
}
public void disconnectDevice(View view) throws IOException {
if(clientSocket.isConnected()){
clientSocket.close();
TextView textView = (TextView) findViewById(R.id.boundedDevice);
textView.setText("Device not connected");
}
}
}
That is my code which I am using for connection, what is wrong?
What I want to have is I would like to have my device straight away on my list after disconnection, to not waiting those 5-10 mins to let my app find it again.
This is client-side code and you need server-side code.So you need two device and one device must be a server another device must be a client.If you want to search available device you work in server side.First of all you must look at android developer bluetooth chat project in the official site.Then find out server-side code.
https://developer.android.com/samples/BluetoothChat/project.html
My app should pair with a BLE without showing any pairing request dialog. I am setting pin in the code. But actually dialog is showing for a sec and then disappearing. Pairing is happening, but i don't want this dialog to be shown. Is there a method to do that?
Since the SDK version 19 this is more difficult. I found a way to bypass it using a subclass of BroadcastReceiver.
public class BluetoothPairingRequest extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
// convert broadcast intent into activity intent (same action string)
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
Intent pairingIntent = new Intent();
pairingIntent.setClass(context, MainActivity.class);
pairingIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, type);
pairingIntent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
pairingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (device != null) {
try {
device.setPin("1111".getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
context.startActivity(pairingIntent);
}
}
}
Then you need register a bond receiver like this.
/**
* Lock used in synchronization purposes
*/
private final Object lock = new Object();
private String deviceAddress;
...
#Override
public void onCreate() {
super.onCreate();
...
final IntentFilter bondFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(bondStateBroadcastReceiver, bondFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
...
unregisterReceiver(bondStateBroadcastReceiver);
}
After this you can add this code when you want to initialize the bonding process.
...
BluetoothDevice newDevice = bluetoothAdapter.getRemoteDevice(device.getAddress());
deviceAddress = newDevice.getAddress();
createBond(newDevice);
...
The implementation of the createBond is here:
private final BroadcastReceiver bondStateBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
// Obtain the device and check it this is the one that we are connected to
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (!device.getAddress().equals(mDeviceAddress))
return;
// Read bond state
final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
if (bondState == BluetoothDevice.BOND_BONDING)
return;
requestCompleted = true;
// Notify waiting thread
synchronized (lock) {
lock.notifyAll();
}
}
};
private boolean createBond(final BluetoothDevice device) {
if (device.getBondState() == BluetoothDevice.BOND_BONDED)
return true;
boolean result;
requestCompleted = false;
sendLogBroadcast(LOG_LEVEL_VERBOSE, "Starting pairing...");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
result = device.createBond();
} else {
result = createBondApi18(device);
}
// We have to wait until device is bounded
try {
synchronized (lock) {
while (!requestCompleted) lock.wait();
}
} catch (final InterruptedException e) {
Log.e(TAG, "Sleeping interrupted", e);
}
return result;
}
private boolean createBondApi18(final BluetoothDevice device) {
/*
* There is a createBond() method in BluetoothDevice class but for now it's hidden. We will call it using reflections. It has been revealed in KitKat (Api19)
*/
try {
final Method createBond = device.getClass().getMethod("createBond");
if (createBond != null) {
return (Boolean) createBond.invoke(device);
}
} catch (final Exception e) {
Log.w(TAG, "An exception occurred while creating bond", e);
Log.e(TAG, e.toString());
}
return false;
}
Finally don't forget to add to your manifest these lines:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
And register the receiver:
<receiver android:name=".bluetooth.BluetoothPairingRequest">
<intent-filter>
<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<action android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
</intent-filter>
</receiver>
I have made an application that allows many-to-one communication using Bluetooth and it is working perfectly fine. Now, i wanted to use the service of the application in another application (e.g. Discovering Devices, Connecting to Device). So, I marked my project as library and added it as library in my new project. However, when i call the Discovering Device Activity (Available in library) from the application, the activity starts, but it doesn't discovers the devices ? Can someone help on this ?
I have included all the library project activity and permissions in my app's manifest.
Here is the sample code for the same -
In Library -
This is how the DeviceListActivity Looks like -
`
public class DeviceListActivity extends Activity{
String insecure="8ce255c0-200a-11e0-ac64-0800200c9a66";
private int flag=0;
int flag_toast=0;
ArrayList<Pair<String,String>> x=new ArrayList<Pair<String,String>>();
private static final String TAG = "DeviceListActivity";
ArrayList<String> temp=new ArrayList<String>();
Map<String, String> services = new HashMap<String, String>();
/**
* Return Intent extra
*/
public static String EXTRA_DEVICE_ADDRESS = "device_address";
/**
* Member fields
*/
private BluetoothAdapter mBtAdapter;
/**
* Newly discovered devices
*/
ImageView animation;
private ArrayList<BluetoothDevice> btDeviceList = new ArrayList<BluetoothDevice>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Setup the window
// requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_device_list);
// Set result CANCELED in case the user backs out
setResult(Activity.RESULT_CANCELED);
// Initialize the button to perform device discovery
animation=(ImageView)findViewById(R.id.imageAnimation);
/*scanButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
doDiscovery();
v.setVisibility(View.GONE);
}
});*/
// Initialize array adapters. One for already paired devices and
// one for newly discovered devices
//ArrayAdapter<String> pairedDevicesArrayAdapter =new ArrayAdapter<String>(this, R.layout.device_name);
//mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
//Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_UUID);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
/* this.registerReceiver(mReceiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
*/
// Get the local Bluetooth adapter
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
animation.setBackgroundResource(R.drawable.animation);
doDiscovery();
}
#Override
protected void onDestroy() {
super.onDestroy();
// Make sure we're not doing discovery anymore
if (mBtAdapter != null) {
mBtAdapter.cancelDiscovery();
}
// Unregister broadcast listeners
this.unregisterReceiver(mReceiver);
}
/**
* Start device discover with the BluetoothAdapter
*/
public void doDiscovery() {
Log.d(TAG, "doDiscovery()");
// If we're already discovering, stop it
if (mBtAdapter.isDiscovering()) {
mBtAdapter.cancelDiscovery();
}
// Request discover from BluetoothAdapter
mBtAdapter.startDiscovery();
}
private void connect_automatic(String name){
flag++;
Log.d(name,"Called " + Integer.toString(flag)+" times");
Log.d("Flag is = ",Integer.toString(flag));
int i,j;
for(i=0;i<x.size();i++){
for (j=i+1;j<x.size();j++)
if (x.get(i).getFirst().equals(x.get(j).getFirst())==true && x.get(i).getSecond().equals(x.get(j).getSecond())==true)
x.remove(j);
}
for(i=0;i<x.size();i++){
Log.d("Found "+x.get(i).getFirst(),x.get(i).getSecond());
}
Log.d("Size =",Integer.toString(x.size()));
if (x.size()>=1){
Log.d("Size is =",Integer.toString(x.size()));
String address = x.get(0).getFirst();
if (flag_toast==0)
Toast.makeText(DeviceListActivity.this, "Merchant Found", Toast.LENGTH_SHORT).show();
flag_toast++;
Log.d("Connecting to ",x.get(0).getFirst());
// Create the result Intent and include the MAC address
Intent intent = new Intent();
intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
// Set result and finish this Activity
setResult(Activity.RESULT_OK, intent);
finish();
}
}
/**
* The BroadcastReceiver that listens for discovered devices and changes the title when
* discovery is finished
*/
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#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
flag++;
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed already
//mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
btDeviceList.add(device);
// When discovery is finished, change the Activity title
}
else
{
Log.d("Action=",action.toString());
if(BluetoothDevice.ACTION_UUID.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
if(uuidExtra!=null)
for (int i=0; i<uuidExtra.length; i++) {
if(uuidExtra[i].toString().length()>0){
Log.d("\n Device: " + device.getName() + ", " + device, ", Service: " + uuidExtra[i].toString());
// services.put(device.getName(), uuidExtra[i].toString());
//flag=btDeviceList.size();
if (/*uuidExtra[i].toString().equals(secure)==true ||*/ uuidExtra[i].toString().equals(insecure)==true){
Pair<String,String> t=new Pair<String, String>(device.getAddress(), uuidExtra[i].toString());
x.add(t);
}
//connect_automatic();
}
}
Log.d("Device List =",Integer.toString(flag));
connect_automatic(device.getName());
//Log.d("Boolean",Boolean.toString(services.isEmpty()))
}
else
{
if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.d("Discovery","Started...");
}
else
{
if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.d("Discover","Finished");
//setProgressBarIndeterminateVisibility(false);
Iterator<BluetoothDevice> itr = btDeviceList.iterator();
while (itr.hasNext()) {
// Get Services for paired devices
BluetoothDevice device = itr.next();
temp.add(device.getName());
Log.d("ok","Getting Services for " + device.getName() + ", " + device);
if(!device.fetchUuidsWithSdp()) {
Log.d("!ok","SDP Failed for " + device.getName());
}
else{
Log.d("SDP Passed for ",device.getName());
}
}
//connect_automatic();
}
}
}
}
}
};}`
And here is how i call it in my new application -
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter != null)
{
ensureDiscoverable();
Intent intent = new Intent(this, DeviceListActivity.class);
startActivityForResult(intent, REQUEST_CONNECT_DEVICE_INSECURE);
}
}
I've been having this problem for a while and haven't been able to figure it out.
I have a android application that puts all paired devices in a listview. When you click one of the list items, it will initiate a request to connect to that bluetooth device.
I can get the list of devices with their addresses no problem.
The problem is that once I try to connect I get an IOException on socket.connect();
The error message is as follows:
"connect read failed, socket might closed or timeout, read ret: -1"
Here is my code. ANY suggestions would be appreciated. I'm pretty stuck on this.
fyi: the "onEvent" methods is a library that simplifies callbacks...that part works.
When the user clicks on a list items this method is called "public void onEvent(EventMessage.DeviceSelected event)"
public class EcoDashActivity extends BaseActivity {
public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 100;
private ArrayList<BluetoothDevice> mDevicesList;
private BluetoothDeviceDialog mDialog;
private ProgressDialog progressBar;
private int progressBarStatus = 0;
private Handler progressBarHandler = new Handler();
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
mDevicesList = new ArrayList<BluetoothDevice>();
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
setupBluetooth();
}
private void setupBluetooth() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
Toast.makeText(this, "Device does not support Bluetooth", Toast.LENGTH_SHORT).show();
}
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
searchForPairedDevices();
mDialog = new BluetoothDeviceDialog(this, mDevicesList);
mDialog.show(getFragmentManager(), "");
}
}
private void searchForPairedDevices() {
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mDevices.add(device.getName() + "\n" + device.getAddress());
mDevicesList.add(device);
}
}
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
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);
// Add the name and address to an array adapter to show in a ListView
mDevicesList.add(device);
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
Toast.makeText(this, "BT turned on!", Toast.LENGTH_SHORT).show();
searchForPairedDevices();
mDialog = new BluetoothDeviceDialog(this, mDevicesList);
mDialog.show(getFragmentManager(), "");
}
}
super.onActivityResult(requestCode, resultCode, data);
}
public void onEvent(EventMessage.DeviceSelected event) {
mDialog.dismiss();
BluetoothDevice device = event.getDevice();
ConnectThread connectThread = new ConnectThread(device);
connectThread.start();
}
public class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
setName("ConnectThread");
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
Log.d("kent", "trying to connect to device");
mmSocket.connect();
Log.d("kent", "Connected!");
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
Log.d("kent", "failed to connect");
mmSocket.close();
} catch (IOException closeException) { }
return;
}
Log.d("kent", "Connected!");
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
Here is my logcat. Pretty short.
07-22 10:37:05.129: DEBUG/kent(17512): trying to connect to device
07-22 10:37:05.129: WARN/BluetoothAdapter(17512): getBluetoothService() called with no BluetoothManagerCallback
07-22 10:37:05.129: DEBUG/BluetoothSocket(17512): connect(), SocketState: INIT, mPfd: {ParcelFileDescriptor: FileDescriptor[98]}
07-22 10:37:40.757: DEBUG/dalvikvm(17512): GC_CONCURRENT freed 6157K, 9% free 62793K/68972K, paused 7ms+7ms, total 72ms
07-22 10:38:06.975: DEBUG/kent(17512): failed to connect
07-22 10:38:06.975: DEBUG/kent(17512): read failed, socket might closed or timeout, read ret: -1
That last line is in the "Catch" section of a try/catch...I'm just logging the error message.
Please note, there is about a 20 second gap between "trying to connect to device" and "failed to connect"
The jelly bean bluetooth stack is markedly different from the other versions.
This might help: http://wiresareobsolete.com/wordpress/2010/11/android-bluetooth-rfcomm/
In gist:
The UUID is a value that must point to a published service on your embedded device, it is not just randomly generated. The RFCOMM SPP connection you want to access has a specific UUID that it publishes to identify that service, and when you create a socket it must match the same UUID.
If you are targeting 4.0.3 device and above , use fetchUuidsWithSdp() and getUuids() to find all the published services and their associated UUID values. For backward compatibility read the article
I got the same error message after connecting the socket a second time. I simply checked if the socket is already connected.
if(!mmSocket.isConnected())
mmSocket.connect();
I was testing on Android 4.4.2 (Moto G).
I am trying to sent message from android client to Mac OS X over bluetooth.
I am using bluecove 2.0.1 Java bluetooth library on Mac OS X Snow Leopard.
Code for Server:
public class EchoServer2 {
private static final String UUID_STRING = "00001101-0000-1000-8000-00805F9B34FB"; // 32 hex digits
private static final String SERVICE_NAME = "echoserver";
private LocalDevice mLocalDevice;
public EchoServer2() {
try {
mLocalDevice = LocalDevice.getLocalDevice();
} catch(IOException e) {
System.err.print("Error connection to bluetooth");
}
}
public void start() throws IOException {
StreamConnectionNotifier connectionNotifier =
(StreamConnectionNotifier) Connector.open(
"btspp://localhost:" + UUID_STRING +
";name=" + SERVICE_NAME + ";authenticate=false");
System.out.println("Bluetooth Address: " + mLocalDevice.getBluetoothAddress());
System.out.println("Waiting for a connection...");
StreamConnection streamConnection = connectionNotifier.acceptAndOpen();
System.out.println("Found a new device.");
RemoteDevice device = RemoteDevice.getRemoteDevice(streamConnection);
System.out.println("New Device connected: " + device.getFriendlyName(false).toString());
DataInputStream is = streamConnection.openDataInputStream();
byte[] bytes = new byte[1024];
int r;
while((r = is.read(bytes)) > 0) {
System.out.println(new String(bytes, 0, r));
}
}
}
Code for Android client:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
EditText editText;
TextView textView;
String send_msg;
String rcv_msg;
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // 32 hex digits
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate");
editText = (EditText) findViewById(R.id.edit_msg);
textView = (TextView) findViewById(R.id.rcv_msg);
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if(adapter == null) {
textView.append("Bluetooth NOT Supported!");
return;
}
// Request user to turn ON Bluetooth
if(!adapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, RESULT_OK);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void onClick(View view) {
Log.d(TAG, "onClick");
new SendMessageToServer().execute(send_msg);
}
private class SendMessageToServer extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... msg) {
Log.d(TAG, "doInBackground");
BluetoothSocket clientSocket = null;
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.enable();
// Client knows the server MAC address
BluetoothDevice mmDevice = mBluetoothAdapter.getRemoteDevice("00:25:00:C3:1C:FE");
Log.d(TAG, "got hold of remote device");
Log.d(TAG, "remote device: " + mmDevice.getName().toString());
try {
// UUID string same used by server
clientSocket = mmDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID);
Log.d(TAG, "bluetooth socket created");
mBluetoothAdapter.cancelDiscovery(); // Cancel, discovery slows connection
clientSocket.connect();
Log.d(TAG, "connected to server");
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
out.writeUTF(msg[0]); // Send message to server
Log.d(TAG, "Message Successfully sent to server");
return in.readUTF(); // Read response from server
} catch (Exception e) {
Log.d(TAG, "Error creating bluetooth socket");
Log.d(TAG, e.getMessage());
return "";
}
}
#Override
protected void onPostExecute(String result) {
Log.d(TAG, "onPostExecute");
rcv_msg = result;
textView.setText(rcv_msg);
}
}
}
I am not able to connect to server even though the UUID are same both for client and server.
Android throws an exception: Service Discovery failed.
However I am able to print the name of remote device (client) on the server. Hence acceptAndOpen() is unable to accept the socket connection.
Please help me in understanding as to why I am unable to clientSocket.connect(); on android ?
Im gonna take a guess and say it has something to do with the UUID numbers you used. They depend solely on the type of device you use. So make sure you look those up and that they are correct for the android device. When i was doing android this stumped me for a long time.
UUID is not something you set.
Here is a link
How can I get the UUID of my Android phone in an application?
Or this
Android - Get Bluetooth UUID for this device
If that is not it.
Did discovery fail on both ends? can you see the device on either end? Which side can you print the name?
You might want to take a look at google's bluetooth sample program. And use that to get you started.