I'm running Android 7.0 on my phone, Android Studio 2.3.3 build #AI-162.4069837 June 6, 2017, and JDK 1.8.0_144. Connecting to a Raspberry Pi Zero W, gets the error "java.io.IOException: read failed, socket might closed or timeout, read ret: -1". When I downloaded and ran the Android program "BlueTerminal", that program connects and transmits data properly. However, this program fails. Here is the Android code.
package com.terryneckar.sprinkon;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import static com.terryneckar.sprinkon.R.string.preference_file_key;
public class BluetoothSetup extends AppCompatActivity
{
private static final int REQUEST_ENABLE_BT = 1;
BluetoothAdapter btAdapter;
String bluetoothName = "";
Spinner spinner;
private static final UUID MY_UUID = UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth_setup);
Button saveButton = (Button) findViewById(R.id.id_savebtn);
Button connectButton = (Button) findViewById(R.id.id_connectbtn);
String ssid = getConfigData("SSID");
String password = getConfigData("Password");
String timezone = getConfigData("Timezone");
bluetoothName = getConfigData("BluetoothName");
TextView myTextView1 = (TextView)findViewById(R.id.id_ssid);
myTextView1.setText(ssid);
TextView myTextView2 = (TextView)findViewById(R.id.id_password);
myTextView2.setText(password);
TextView myTextView3 = (TextView)findViewById(R.id.id_timezone);
myTextView3.setText(timezone);
// Fill the spinner with a list of all of the bluetooth devices available.
List<String> bluetoothDevices = new ArrayList<String>();
btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
for (BluetoothDevice device : pairedDevices)
bluetoothDevices.add(device.getName());
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_spinner_item, bluetoothDevices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner = (Spinner) findViewById(R.id.id_bluetoothDevices);
spinner.setAdapter(adapter);
// Set the spinner to the value that was saved in the configuration.
if (!bluetoothName.equals(null))
{
int spinnerPosition = adapter.getPosition(bluetoothName);
spinner.setSelection(spinnerPosition);
}
saveButton.setOnClickListener(
new Button.OnClickListener()
{
public void onClick(View v)
{
String ssid = "";
String password = "";
String timezone = "";
EditText editText = (EditText) findViewById(R.id.id_ssid);
ssid = editText.getText().toString();
editText = (EditText) findViewById(R.id.id_password);
password = editText.getText().toString();
editText = (EditText) findViewById(R.id.id_timezone);
bluetoothName = spinner.getSelectedItem().toString();
timezone = editText.getText().toString();
writeToFile("SSID", ssid);
writeToFile("Password", password);
writeToFile("Timezone", timezone);
writeToFile("BluetoothName", bluetoothName);
Toast.makeText(getApplicationContext(), "Save was successful.", Toast.LENGTH_LONG).show();
}
});
connectButton.setOnClickListener(
new Button.OnClickListener()
{
public void onClick(View v)
{
String ssid = "";
String password = "";
String timezone = "";
BluetoothDevice device = null;
BluetoothSocket mSocket = null;
EditText editText = (EditText) findViewById(R.id.id_ssid);
ssid = editText.getText().toString();
editText = (EditText) findViewById(R.id.id_password);
password = editText.getText().toString();
editText = (EditText) findViewById(R.id.id_timezone);
bluetoothName = spinner.getSelectedItem().toString();
timezone = editText.getText().toString();
device = GetBluetoothDevice(btAdapter, bluetoothName);
if(device.getBondState()==device.BOND_BONDED)
{
try
{
mSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
//mSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
}
catch (IOException e1)
{
// TODO Auto-generated catch block
//Log.d(TAG,"socket not created");
e1.printStackTrace();
}
try
{
mSocket.connect();
Toast.makeText(getApplicationContext(), "Connect was successful.", Toast.LENGTH_SHORT).show();
}
catch(IOException e)
{
Log.e("SprinKon TAG", "STACKTRACE");
Log.e("SprinKon TAG", Log.getStackTraceString(e));
try
{
mSocket.close();
Toast.makeText(getApplicationContext(), "Cannot connect. \n" + e.getMessage(), Toast.LENGTH_LONG).show();
}
catch (IOException e1)
{
}
}
}
}
});
}
private void writeToFile(String data, String key)
{
Context context = BluetoothSetup.this;
SharedPreferences sharedPref = context.getSharedPreferences("SprinKonConfig", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(data, key);
editor.commit();
}
private String getConfigData(String key)
{
Context context = BluetoothSetup.this;
SharedPreferences sharedPref = context.getSharedPreferences("SprinKonConfig", Context.MODE_PRIVATE);
String data = sharedPref.getString(key, "DEFAULT");
return data;
}
private BluetoothDevice GetBluetoothDevice(BluetoothAdapter adapter, String deviceName)
{
Set<BluetoothDevice> devices = adapter.getBondedDevices();
BluetoothDevice result = null;
if (devices != null)
{
for (BluetoothDevice device : devices)
{
if (deviceName.equals(device.getName()))
{
result = device;
break;
}
}
}
return result;
}
}
When I run the "BlueTerminal" program, it seems that it takes longer to make a connect than this program does. Could it be that it's just timing out. If so, is there any way to increase the timeout value like can be done with an Internet connection? I don't understand why the Android code it is trying to do connect,readInt() and then a readAll() all on just a connect(). Shouldn't there just be a connect() available? The C++ program is waiting on the accept(), but it never occurs.
Here is the stack trace:
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:907)
android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:919)
android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:536)
com.terryneckar.sprinkon.BluetoothSetup$2.onClick(BluetoothSetup.java:153)
android.view.View.performClick(View.java:6207)
android.widget.TextView.performClick(TextView.java:11094)
android.view.View$PerformClick.run(View.java:23639)
android.os.Handler.handleCallback(Handler.java:751)
android.os.Handler.dispatchMessage(Handler.java:95)
android.os.Looper.loop(Looper.java:154)
android.app.ActivityThread.main(ActivityThread.java:6688)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
Here is the C++ program that I'm connecting to.
char buf[1024] = {0};
int bluetoothSocket, client, bytes_read;
struct sockaddr_rc loc_addr = {0};
struct sockaddr_rc client_addr = {0};
socklen_t opt = sizeof(client_addr);
bdaddr_t my_bdaddr_any = {0, 0, 0, 0, 0, 0};
bluetoothSocket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = (bdaddr_t)my_bdaddr_any;
loc_addr.rc_channel = (uint8_t) 1;
int ret = -1;
if ((ret = bind(bluetoothSocket, (struct sockaddr *)&loc_addr, sizeof(loc_addr))) == -1)
{
printf("Bluetooth bind failed. ERRNO=%d\n", errno);
char *errorMessage = strerror_r(errno, buf, 1024);
printf("%s\n", errorMessage);
return 0;
}
ret = -1;
if((ret = listen(bluetoothSocket, 1)) == -1)
{
printf("Bluetooth listen failed. ERRNO=%d\n", errno);
char *errorMessage = strerror_r(errno, buf, 1024);
printf("%s\n", errorMessage);
return 0;
}
printf("Waiting for new client to connect.\n");
client = accept(bluetoothSocket, (struct sockaddr *)&client_addr, &opt);
if (client == -1)
{
printf("Bluetooth connect failed.\n");
close(client);
return;
}
printf("Bluetooth connection made.\n");
ba2str(&client_addr.rc_bdaddr, buf);
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if (bytes_read > 0)
{
printf("Bluetooth bytes received [%s]\n", buf);
}
close(client);
close(bluetoothSocket);
return 0;
I did power off and on my phone, but that didn't help. I removed all paired devices, no help.