2015-01-17 16 views
0

我正在开发一款Android应用程序,我需要通过蓝牙发送文本。我已经想出了一段代码来实现这一点。我的问题是,它发送消息到设备后抛出StringIndexOutOfBoundsException它崩溃。如何解决this.My完整的代码:正在向另一个蓝牙设备发送短信时获取StringIndexOutOfBoundsException

package com.example.blueremote; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.ArrayList; 
import java.util.UUID; 

import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Handler; 
import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothServerSocket; 
import android.bluetooth.BluetoothSocket; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.ImageButton; 
import android.widget.ListView; 
import android.widget.TextView; 

public class MainActivity extends Activity { 
    private BluetoothAdapter btadapter; 
    private BluetoothSocket socket; 
    private Button btnSend; 
    private ArrayList<BluetoothDevice> foundDevices; 
    private ArrayAdapter<BluetoothDevice> aa; 
    private Handler handler = new Handler(); 

    private ListView list; 
    private TextView tvmsg; 
    private static int DISCOVERY_REQUEST = 1; 
    private UUID uuid = UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666"); 
    ImageButton up; 
    private String address = "D8:50:E6:8A:16:0F"; 

    private String text = "up"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     btadapter = BluetoothAdapter.getDefaultAdapter(); 
     Intent disc; 
     disc = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); 
     startActivityForResult(disc, DISCOVERY_REQUEST); 
     up = (ImageButton) findViewById(R.id.btn_up); 

     registerReceiver(discoveryResult, new IntentFilter(
       BluetoothDevice.ACTION_FOUND)); 
     AsyncTask<Integer, Void, Void> connectTask = new AsyncTask<Integer, Void, Void>() { 

      @Override 
      protected Void doInBackground(Integer... params) { 
       // TODO Auto-generated method stub 
       try { 
        Log.v("Main Activity", " AsyncTask started"); 
        BluetoothDevice device = btadapter.getRemoteDevice(address); 

        socket = device.createRfcommSocketToServiceRecord(uuid); 
        Log.v("Main Activity", "Socket Created"); 
        socket.connect(); 

        Log.v("Main Activity", "Socket Connected"); 
       } catch (IOException e) { 
        Log.d("BLUETOOTH_CLIENT", e.getMessage()); 
       } 
       return null; 
      } 

      @Override 
      protected void onPostExecute(Void result) { 
       // Log.v("Main Activity", "Invoking switchUI"); 
       // switchUI(); 

      } 
     }; 
     connectTask.execute(); 
     up.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 
       Log.v("Main Activity", "In up Button"); 
       // Log.v("Main Activity", "Invoking switchUI"); 
       switchUI(); 
      } 
     }); 
    } 

    private void switchUI() { 
     Log.v("Main Activity", "In SwitchUI Method"); 

     Log.v("Main Activity", "Invoking sendMessage Method "); 
     sendMessage(socket, text); 
     Log.v("Main Activity", "Message Sent"); 

     BluetoothSocketListener bsl = new BluetoothSocketListener(socket, 
       handler); 
     Thread messageListener = new Thread(bsl); 
     messageListener.start(); 
    } 

    private void sendMessage(BluetoothSocket socket, String msg) { 
     msg = "UP"; 
     OutputStream outStream; 
     try { 
      Log.v("Main Activity", "Inside sendMessage Method "); 

      outStream = socket.getOutputStream(); 
      Log.v("Main Activity", "Outstream:" + outStream); 
      byte[] byteString = (msg + " ").getBytes(); 
      Log.v("Main Activity", "byteString:" + byteString); 

      outStream.write(byteString); 
      Log.v("Main Activity", "outstream written:"); 
     } catch (IOException e) { 
      Log.d("BLUETOOTH_COMMS", e.getMessage()); 
     } 
    } 

    private class MessagePoster implements Runnable { 
     private TextView textView; 
     private String message; 

     public MessagePoster(String message) { 
      // this.textView = textView; 
      this.message = message; 
     } 

     public void run() { 
      // textView.setText(message); 
     } 
    } 

    private class BluetoothSocketListener implements Runnable { 
     private BluetoothSocket socket; 
     private TextView textView; 
     private Handler handler; 

     public BluetoothSocketListener(BluetoothSocket socket, Handler handler) { 
      this.socket = socket; 
      // this.textView = textView; 
      this.handler = handler; 
     } 

     public void run() { 
      int bufferSize = 2048; 
      byte[] buffer = new byte[bufferSize]; 
      try { 
       InputStream instream = socket.getInputStream(); 
       int bytesRead = -1; 
       String message = ""; 
       while (true) { 
        message = ""; 
        bytesRead = instream.read(buffer); 
        if (bytesRead != -1) { 
         while ((bytesRead == bufferSize) 
           && (buffer[bufferSize - 1] != 0)) { 
          message = message 
            + new String(buffer, 0, bytesRead); 
          bytesRead = instream.read(buffer); 
         } 
         message = message 
           + new String(buffer, 0, bytesRead - 1); 
         handler.post(new MessagePoster(message)); 
         socket.getInputStream(); 
        } 
       } 
      } catch (IOException e) { 
       Log.d("BLUETOOTH_COMMS", e.getMessage()); 
      } 
     } 
    } 

    BroadcastReceiver discoveryResult = new BroadcastReceiver() { 

     @Override 
     public void onReceive(Context context, Intent intent) { 
      // TODO Auto-generated method stub 
      BluetoothDevice remoteDevice; 
      remoteDevice = intent 
        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 
      if (btadapter.getBondedDevices().contains(remoteDevice)) { 
       foundDevices.add(remoteDevice); 
       aa.notifyDataSetChanged(); 
      } 
     } 
    }; 

    protected void onDestroy() { 
     super.onDestroy(); 
     unregisterReceiver(discoveryResult); 
    } 

} 

的logcat:

E/AndroidRuntime(10360): FATAL EXCEPTION: Thread-1585 

E/AndroidRuntime(10360): java.lang.StringIndexOutOfBoundsException: length=2048; regionStart=0; regionLength=65534 

E/AndroidRuntime(10360): at java.lang.String.failedBoundsCheck(String.java:587) 

E/AndroidRuntime(10360): at java.lang.String.<init>(String.java:247) 

E/AndroidRuntime(10360): at java.lang.String.<init>(String.java:171) 

E/AndroidRuntime(10360): at com.example.blueremote.MainActivity$BluetoothSocketListener.run(MainActivity.java:177) 
+0

哪一行是MainActivity.java:177? – immibis

+0

@immibis:while(true){ \t \t \t \t \t message =“hello”; \t \t \t \t \t bytesRead = instream.read(buffer); \t \t \t \t \t如果(bytesRead = -1!){ \t \t \t \t \t \t而((bytesRead == BUFFERSIZE) \t \t \t \t \t \t \t \t &&(缓冲![BUFFERSIZE - 1] = 0 )){ \t \t \t \t \t \t \t message = message \t \t \t \t \t \t \t \t \t +新字符串(缓冲液,0,bytesRead); \t \t \t \t \t \t \t bytesRead = instream.read(buffer); \t \t \t \t \t \t} \t \t \t \t \t \t消息=消息 \t \t \t \t \t \t \t \t +新字符串(缓冲液,0,bytesRead - 1); \t \t \t \t \t \t handler.post(new MessagePoster(message)); \t \t \t \t \t \t socket.getInputStream(); \t \t \t \t \t} \t \t \t \t} –

+0

尝试使用字符串缓冲区 –

回答

0

在参考String类,我们看到调用String (byte[] data, int offset, int byteCount)将抛出一个IndexOutOfBoundsException当发生下列三种情形之一:

  1. offset > 0 - 如果偏移传递给该方法是小于0,一个Exception将被抛出。由于您通过0,而不是一个变量到您的方法调用,这不会导致Exception

  2. offset + byteCount > data.length - 在这种情况下一个Exception将当offsetbyteCount大于缓冲器的长度长抛出。在您的代码中,offset始终为0byteCount,在您的示例中为bytesRead - 1,永远不会超过2048,因为instream.read(buffer)无法读取比buffer本身可容纳的更多字节。这意味着offset(0)+ byteCount(-1≤byteCount≤2047)永远不会大于data.length(2048),因此这不是Exception的原因。

  3. byteCount < 0 - 这将引发提到Exception第三种情况是,当你传递一个byte计数小于0。在你的例子中,你通过bytesRead - 1作为byte计数。当您检查以确保bytesRead != -1,这将发生,如果已达到流的末尾,您不检查,以确保至少有1 byte被读取。这是最有可能的罪魁祸首......

按照您的例子,让我们考虑当bytesRead = instream.read(buffer);回报0,这意味着没有byte小号被读取时会发生什么......

  1. 首先检查你执行if (bytesRead != -1)将通过,因为bytesRead等于0

  2. 里面的if语句是while ((bytesRead == bufferSize) && (buffer[bufferSize - 1] != 0)),这当然也会因为bytesRead,这是0失败,不等于bufferSize,这是2048

  3. 最后的电话是message = message + new String(buffer, 0, bytesRead - 1);,我们可以将其翻译为message = message + String(buffer, 0, -1)。如您所见,由于bytesRead为0,上述呼叫将生成IndexOutOfBoundsException

要解决这个问题,只需确保你不叫String(buffer, 0, bytesRead - 1)如果bytesRead小于1