2017-08-24 91 views
0

我在手机上运行Android 7.0,Android Studio 2.3.3 build#AI-162.4069837 2017年6月6日和JDK 1.8.0_144。连接到Raspberry Pi Zero W,得到错误“java.io.IOException:读取失败,套接字可能关闭或超时,读取ret:-1”。当我下载并运行Android程序“BlueTerminal”时,该程序正确连接并传输数据。但是,这个程序失败了。这是Android代码。为什么我在蓝牙连接()上得到“java.io.IOException:读取失败,套接字可能关闭或超时,读取ret:-1”?

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; 
    } 
} 

当我运行“BlueTerminal”程序时,似乎需要比此程序更长的连接时间。难道它只是超时而已。如果是这样,是否有任何方法可以像使用Internet连接一样增加超时值?我不明白为什么它要尝试连接的Android代码,readInt()和readAll()全部在connect()上。不应该只有一个connect()可用吗? C++程序正在等待accept(),但它永远不会发生。

这里是堆栈跟踪:

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) 

这里是我连接到C++程序。

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;  

我关掉电源,然后打开手机,但没有帮助。 我删除了所有配对的设备,没有帮助。

回答

0

问题出在UUID。当我改变了代码:

MY_UUID = UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB"); 

MY_UUID = device.getUuids()[0].getUuid(); 

它的工作。

相关问题