2015-01-17 2 views
0

Я работаю над Android-приложением, где мне нужно отправить текст по Bluetooth. Я придумал кусок кода для достижения этого. Моя проблема в том, что он разбился после отправки сообщения на устройство, бросая StringIndexOutOfBoundsException. Как я могу исправить this.My полный код:Получение StringIndexOutOfBoundsException при отправке текстового сообщения на другое устройство Bluetooth

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 сообщение = сообщение \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 (новый MessagePoster (сообщение)); \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 будет сгенерирован, когда offset плюс byteCount больше, чем длина буфера. В вашем коде offset всегда 0 и byteCount, который в вашем примере равен 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.

Смежные вопросы