2013-03-14 3 views
3

Это мой первый вопрос в SO. Я новичок (и взволнован) в Android-программировании, и вот моя ПРОБЛЕМА: Я строю проект, используя мой Android-телефон и микроконтроллер. Микроконтроллер имеет датчик расстояния и передает его значение. Мне удалось подключиться к микроконтроллеру и отправить правильные сигналы, но я не могу получить дистанционное смешение или что-то еще. Приложение не сбой или что-либо, что он просто не получит данные от микроконтроллера (мой компьютер получает данные от микроконтроллера (данные являются строкой)). Мой код из Android App это:Как получить InputStream через bluetooth и поместить в Textview?

общественного класса акселерометр расширяет активность {

// Intent request codes 
private static final int REQUEST_CONNECT_DEVICE = 1; 
private static final int REQUEST_ENABLE_BT = 2; 
private static final int RECIEVE_MESSAGE = 3; 

// Program variables 
private byte microcOut; 
private boolean ledStat; 
private boolean connectStat = false; 
private Button btnled; 
private Button connect_button; 
private TextView yAccel, xAccel, incoming; 
protected static final int MOVE_TIME = 80; 
private long lastWrite = 0; 
OnClickListener myClickListener; 
ProgressDialog myProgressDialog; 
private Toast failToast; 
private Handler mHandler,h; 
private StringBuilder sb = new StringBuilder(); 

// Sensor object used to handle accelerometer 
private SensorManager mySensorManager; 
private List<Sensor> sensors; 
private Sensor accSensor; 

// Bluetooth Stuff 
private BluetoothAdapter btAdapter = null; 
private BluetoothSocket btSocket = null; 
private OutputStream outStream = null; 
private InputStream inStream = null; 
private ConnectThread mConnectThread = null; 
private ConnectedThread mConnectedThread; 

private String deviceAddress = null; 
// Well known SPP UUID (will *probably* map to RFCOMM channel 1 (default) if not in use); 
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 

//Sound Clip to make app prettier 
MediaPlayer myclip; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
    setContentView(R.layout.activity_accelerometer); 
    myclip = MediaPlayer.create(this, R.raw.cartcar); 
    myclip.start(); 
    // Finds buttons in .xml layout file 
    btnled = (Button) findViewById(R.id.led_button1); 
    connect_button = (Button) findViewById(R.id.connect_button1); 
    yAccel = (TextView) findViewById(R.id.accText1); 
    xAccel = (TextView) findViewById(R.id.accText2); 
    incoming = (TextView) findViewById(R.id.incoming); 
    // Set Sensor 
    mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); 
    sensors = mySensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); 
    if(sensors.size() > 0) accSensor = sensors.get(0); 

    myProgressDialog = new ProgressDialog(this); 
    failToast = Toast.makeText(this, R.string.failedToConnect, Toast.LENGTH_SHORT); 
    mHandler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
     if (myProgressDialog.isShowing()) { 
       myProgressDialog.dismiss(); 
      } 

     // Check if bluetooth connection was made to selected device 
      if (msg.what == 1) { 
       // Set button to display current status 
       connectStat = true; 
       connect_button.setText(R.string.connected); 

       // Reset the BluCar 
       microcOut = 0; 
       ledStat = false; 
       write(microcOut); 
      }else { 
       // Connection failed 
      failToast.show(); 
      } 
     } 
    }; 


    h = new Handler() { 
     public void handleMessage(android.os.Message msg) { 
      switch (msg.what) { 
      case RECIEVE_MESSAGE:             // if receive massage 
       byte[] readBuf = (byte[]) msg.obj; 
       String strIncom = new String(readBuf, 0, msg.arg1);     // create string from bytes array 
       sb.append(strIncom);            // append string 
       int endOfLineIndex = sb.indexOf("\r\n");       // determine the end-of-line 
       if (endOfLineIndex > 0) {           // if end-of-line, 
        String sbprint = sb.substring(0, endOfLineIndex);    // extract string 
        sb.delete(0, sb.length());          // and clear 
        incoming.setText("Data from Arduino: " + sbprint);   // update TextView 
       } 
       //Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "..."); 
       break; 
      } 
     }; 
    }; 
// Check whether bluetooth adapter exists 
    btAdapter = BluetoothAdapter.getDefaultAdapter(); 
    if (btAdapter == null) { 
     Toast.makeText(this, R.string.no_bt_device, Toast.LENGTH_LONG).show(); 
     finish(); 
     return; 
    } 

    // If BT is not on, request that it be enabled. 
    if (!btAdapter.isEnabled()) { 
     Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
     startActivityForResult(enableIntent, REQUEST_ENABLE_BT); 
    } 
    /********************************************************************** 
    * Buttons for controlling BluCar 
    */ 
    connect_button.setOnClickListener(new View.OnClickListener() { 

     // Connect to Bluetooth Module 
     @Override 
     public void onClick(View v) { 
      if (connectStat) { 
       // Attempt to disconnect from the device 
       disconnect(); 
      }else{ 
       // Attempt to connect to the device 
       connect(); 
      } 
     } 
    }); 

    // Toggle Headlights 
    btnled.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      if (ledStat) { 
       microcOut = (byte) (microcOut & 124); 
       btnled.setText(R.string.ledbuttonON); 
       ledStat = false; 
      }else{ 
       microcOut = (byte) (microcOut | 128); 
       btnled.setText(R.string.ledbuttonOFF); 
       ledStat = true; 
      } 
      write(microcOut); 
     } 
    }); 

} 
/** Thread used to connect to a specified Bluetooth Device */ 
public class ConnectThread extends Thread { 
private String address; 
private boolean connectionStatus; 

    ConnectThread(String MACaddress) { 
     address = MACaddress; 
     connectionStatus = true; 
} 

    public void run() { 
    // When this returns, it will 'know' about the server, 
     // via it's MAC address. 
     try { 
      BluetoothDevice device = btAdapter.getRemoteDevice(address); 

      // We need two things before we can successfully connect 
      // (authentication issues aside): a MAC address, which we 
      // already have, and an RFCOMM channel. 
      // Because RFCOMM channels (aka ports) are limited in 
      // number, Android doesn't allow you to use them directly; 
      // instead you request a RFCOMM mapping based on a service 
      // ID. In our case, we will use the well-known SPP Service 
      // ID. This ID is in UUID (GUID to you Microsofties) 
      // format. Given the UUID, Android will handle the 
      // mapping for you. Generally, this will return RFCOMM 1, 
      // but not always; it depends what other BlueTooth services 
      // are in use on your Android device. 
      try { 
       btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); 
      } catch (IOException e) { 
       connectionStatus = false; 
      } 
     }catch (IllegalArgumentException e) { 
      connectionStatus = false; 
     } 

     // Discovery may be going on, e.g., if you're running a 
     // 'scan for devices' search from your handset's Bluetooth 
     // settings, so we call cancelDiscovery(). It doesn't hurt 
     // to call it, but it might hurt not to... discovery is a 
     // heavyweight process; you don't want it in progress when 
     // a connection attempt is made. 
     btAdapter.cancelDiscovery(); 

     // Blocking connect, for a simple client nothing else can 
     // happen until a successful connection is made, so we 
     // don't care if it blocks. 
     try { 
      btSocket.connect(); 
     } catch (IOException e1) { 
      try { 
       btSocket.close(); 
      } catch (IOException e2) { 
      } 
     } 

     // Create a data stream so we can talk to server. 
     try { 
     outStream = btSocket.getOutputStream(); 
     } catch (IOException e2) { 
     connectionStatus = false; 
     } 

     // Send final result 
     if (connectionStatus) { 
     mHandler.sendEmptyMessage(1); 
     }else { 
     mHandler.sendEmptyMessage(0); 
     } 
    } 
} 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    switch (requestCode) { 
     case REQUEST_CONNECT_DEVICE: 
     // When DeviceListActivity returns with a device to connect 
      if (resultCode == Activity.RESULT_OK) { 
      // Show please wait dialog 
      myProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.pleaseWait), getResources().getString(R.string.makingConnectionString), true); 

      // Get the device MAC address 
      deviceAddress = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS); 
      // Connect to device with specified MAC address 
       mConnectThread = new ConnectThread(deviceAddress); 
       mConnectThread.start(); 

      }else { 
      // Failure retrieving MAC address 
      Toast.makeText(this, R.string.macFailed, Toast.LENGTH_SHORT).show(); 
      } 
      break; 
     case REQUEST_ENABLE_BT: 
      // When the request to enable Bluetooth returns 
      if (resultCode == Activity.RESULT_OK) { 
       // Bluetooth is now enabled 
      } else { 
       // User did not enable Bluetooth or an error occured 
       Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); 
       finish(); 
      } 
     } 
    } 

public void write(byte data) { 
    if (outStream != null) { 
      try { 
      outStream.write(data); 
      } catch (IOException e) { 
      } 
     } 
    } 

    public void emptyOutStream() { 
    if (outStream != null) { 
      try { 
      outStream.flush(); 
      } catch (IOException e) { 
      } 
     } 
    } 

    public void connect() { 
    // Launch the DeviceListActivity to see devices and do scan 
     Intent serverIntent = new Intent(this, DeviceList.class); 
     startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); 
    } 

    public void disconnect() { 
    if (outStream != null) { 
     try { 
       outStream.close(); 
       connectStat = false; 
       connect_button.setText(R.string.disconnected); 
      } catch (IOException e) { 
      } 
    } 
    } 
    private final SensorEventListener mSensorListener = new SensorEventListener() { 

     @Override 
     public void onAccuracyChanged(Sensor sensor, int accuracy) {} 

     @Override 
     public void onSensorChanged(SensorEvent event) { 
      // Checks whether to send steering command or not 
      long date = System.currentTimeMillis(); 
      if (date - lastWrite > MOVE_TIME) { 
       yAccel.setText(" " + event.values[1]); 
       xAccel.setText(" " + event.values[0]); 
       if (event.values[1] > 2.5) { 
        // Turn right 
        microcOut = (byte) (microcOut & 248); 
        microcOut = (byte) (microcOut | 4); 
       }else if (event.values[1] < -2.5) { 
        // Turn left 
        microcOut = (byte) (microcOut & 244); 
        microcOut = (byte) (microcOut | 8); 
       }else { 
        // Center the steering servo 
        microcOut = (byte) (microcOut & 240); 
       } 
       write(microcOut); 
       lastWrite = date; 
      } 
     } 
     }; 

@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_accelerometer, menu); 
    return true; 
} 
public void onResume() { 
    super.onResume(); 
    mySensorManager.registerListener(mSensorListener, accSensor, SensorManager.SENSOR_DELAY_GAME); 
} 
@Override 
public void onDestroy() { 
    emptyOutStream(); 
    disconnect(); 
    if (mSensorListener != null) { 
     mySensorManager.unregisterListener(mSensorListener); 
    } 
    super.onDestroy(); 
    myclip.release(); 
} 
private class ConnectedThread extends Thread { 
    private final InputStream mmInStream; 
    private final OutputStream mmOutStream; 

    public ConnectedThread(BluetoothSocket socket) { 
     InputStream tmpIn = null; 
     OutputStream tmpOut = null; 

     // Get the input and output streams, using temp objects because 
     // member streams are final 
     try { 
      tmpIn = socket.getInputStream(); 
      tmpOut = socket.getOutputStream(); 
     } catch (IOException e) { } 

     mmInStream = tmpIn; 
     mmOutStream = tmpOut; 
    } 

    public void run() { 
     byte[] buffer = new byte[256]; // buffer store for the stream 
     int bytes; // bytes returned from read() 

     // Keep listening to the InputStream until an exception occurs 
     while (true) { 
      try { 
       // Read from the InputStream 
       bytes = mmInStream.read(buffer);  // Get number of bytes and message in "buffer" 
       h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();  // Send to message queue Handler 
      } catch (IOException e) { 
       break; 
      } 
     } 
    } 

    /* Call this from the main activity to send data to the remote device */ 
    public void write(String message) { 

     byte[] msgBuffer = message.getBytes(); 
     try { 
      mmOutStream.write(msgBuffer); 
     } catch (IOException e) { 

      } 
    } 
} 

}

Я прочитал все, что по этому вопросу (BluetoothChat, проекты людей в Интернете ...), и я очень устал. Буду признателен за любую оказанную помощь.

--EDIT--

мне удалось получить InputStream в мою texteview. Моя проблема заключается в том, что мое приложение, когда оно пытается подключиться к моему устройству (микроконтроллер или мой компьютер), застревает в progressdialog (оно подключено к устройству, но progressdialog не исчезнет) и ждет чего-то. Через некоторое время (например, 5-6 секунд), даже если что-то приходит, оно остается застрявшим, и я должен заставить его закрыть. Я думаю, проблема в том, как обработчик обрабатывает поток. В отладчике нет проблем, все потоки работают нормально.

Изменение в моем коде: В моей ConnectThread: `/ ** Thread используется для подключения к указанному устройству Bluetooth */ общественного класса ConnectThread расширяет тему { частного адрес String; private boolean connectionStatus;

ConnectThread(String MACaddress) { 
     address = MACaddress; 
     connectionStatus = true; 
} 

    public void run() { 
    // When this returns, it will 'know' about the server, 
     // via it's MAC address. 
     try { 
      BluetoothDevice device = btAdapter.getRemoteDevice(address); 

      // We need two things before we can successfully connect 
      // (authentication issues aside): a MAC address, which we 
      // already have, and an RFCOMM channel. 
      // Because RFCOMM channels (aka ports) are limited in 
      // number, Android doesn't allow you to use them directly; 
      // instead you request a RFCOMM mapping based on a service 
      // ID. In our case, we will use the well-known SPP Service 
      // ID. This ID is in UUID (GUID to you Microsofties) 
      // format. Given the UUID, Android will handle the 
      // mapping for you. Generally, this will return RFCOMM 1, 
      // but not always; it depends what other BlueTooth services 
      // are in use on your Android device. 
      try { 
       btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); 
      } catch (IOException e) { 
       connectionStatus = false; 
      } 
     }catch (IllegalArgumentException e) { 
      connectionStatus = false; 
     } 

     // Discovery may be going on, e.g., if you're running a 
     // 'scan for devices' search from your handset's Bluetooth 
     // settings, so we call cancelDiscovery(). It doesn't hurt 
     // to call it, but it might hurt not to... discovery is a 
     // heavyweight process; you don't want it in progress when 
     // a connection attempt is made. 
     btAdapter.cancelDiscovery(); 

     // Blocking connect, for a simple client nothing else can 
     // happen until a successful connection is made, so we 
     // don't care if it blocks. 
     try { 
      btSocket.connect(); 
     } catch (IOException e1) { 
      try { 
       btSocket.close(); 
      } catch (IOException e2) { 
      } 
     } 

     // Create a data stream so we can talk to server. 
     try { 
      outStream = btSocket.getOutputStream(); 
      } catch (IOException e2) { 
      connectionStatus = false; 
      } 
     try{ 
     inStream = btSocket.getInputStream(); 
    }catch (IOException e2){ 
     connectionStatus = false; 
    } 
     int bytes; // bytes returned from read() 
     // Keep listening to the InputStream until an exception occurs 
     while (connectionStatus) { 
      try { 
       byte[] b = new byte[64]; // buffer store for the stream 
       // Read from the InputStream 
       bytes = inStream.read(b);  // Get number of bytes and message in "buffer" 
       mHandler.obtainMessage(RECIEVE_MESSAGE, bytes, -1, b).sendToTarget();  // Send to message queue Handler 
      } catch (IOException e) { 
       break; 
      } 
     } 
     // Send final result 
     if (connectionStatus) { 
     mHandler.obtainMessage(1); 
     }else { 
     mHandler.sendEmptyMessage(0); 
     } 
    } 
} 

` И в моем mHandler в моем OnCreate метод:

mHandler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
     if (myProgressDialog.isShowing()) { 
       myProgressDialog.dismiss(); 
      } 

     // Check if bluetooth connection was made to selected device 
      if (msg.what == 1) { 
       // Set button to display current status 
       connectStat = true; 
       connect_button.setText(R.string.connected); 
       // Reset the BluCar 
       microcOut = 0; 
       ledStat = false; 
       write(microcOut); 
      }else if (msg.what == 2){ 
       byte[] readBuf = (byte[]) msg.obj; 
       String strIncom = new String(readBuf, 0, msg.arg1);     // create string from bytes array 
       sb.append(strIncom);            // append string 
       int endOfLineIndex = sb.indexOf(".");       // determine the end-of-line 
       if (endOfLineIndex > 0) {           // if end-of-line, 
        String sbprint = sb.substring(0, endOfLineIndex);    // extract string 
        sb.delete(0, sb.length());          // and clear 
        incoming.setText(sbprint);   // update TextView 
        connectStat = true; 
        connect_button.setText(R.string.connected); 
       }else{ 
        incoming.setText("Problem!"); 
       } 
      }else { 
       // Connection failed 
      failToast.show(); 
      } 
     } 
    }; 

Другое дело, что мне нужно, как очистить буфер, когда она полна.

PS: Спасибо КАЖДЫЙ за его/ее помощь. Я очень благодарен.

+0

Вы прошли через код с прикрепленным отладчиком? Это будет способ пойти, чтобы увидеть, где все будет работать так, как должно и где все начинает идти не так. Я должен помочь вам определить проблему, которая поможет нам лучше помочь вам. Кроме того, просто рекомендация: не перехватывайте и не забывайте об исключениях - особенно на этапе разработки, вам нужно знать об этом. Прямо сейчас ваш код может провалиться в нескольких местах, если вы никогда не узнаете об этом, что вполне может быть причиной, по которой вы сейчас застряли. –

+0

Благодарим вас за ответ. Я знаю, что мой код работает так, как должен (когда дело доходит до отправки байта microcOut). Для отправки байта мне не нужен последний класс ConnectedThread и второй обработчик h. Это были дополнения к моему коду из того, что я нашел в Интернете. Вам нужен DeviceList также, чтобы помочь мне? Еще раз спасибо. – user2149122

+0

Опять же, вы захотите выполнить свой код с помощью отладчика; особенно метод 'run()' внутри вашего 'ConnectedThread'. Убедитесь, что 'bytes = mmInStream.read (buffer)' когда-либо возвращает разумное значение (и попадает ли он вообще!). Вряд ли исключено исключение, которое вы поймаете, а затем выходите из цикла. По крайней мере, напечатайте исключения, которые вы поймаете, а не игнорируете их, чтобы вы знали, что может быть не так. Как только у вас будет такая информация, мы сможем вам помочь. –

ответ

5

В качестве альтернативы использованию обработчика, просто получить информацию в пробеге нить ..

Я сделал это так, и это работает для меня.

public void run() { 
      byte[] buffer = new byte[128]; // buffer store for the stream 
      int bytes; // bytes returned from read() 

      // Keep listening to the InputStream until an exception occurs 
      while (true) { 
       try { 


        bytes = mmInStream.read(buffer); 
        byte[] readBuf = (byte[]) buffer; 
        String strIncom = new String(readBuf, 0, bytes);     // create string from bytes array 
        sb.append(strIncom);            // append string 
        int endOfLineIndex = sb.indexOf("\r\n");       // determine the end-of-line 
        if (endOfLineIndex > 0) { 
         // add the current string to eol to a local string 
         String sbprint = sb.substring(0, endOfLineIndex); 

         // get the start and end indexes of the heading 
         int startHeading = sb.indexOf("HE"); 
         int endHeading = sb.indexOf("/HE"); 

         // set the heading 
         Henry.this.setCurrentHeading(sb.substring((startHeading + 2), endHeading)); 

         // get the start and end indexes of the front range 
         int startFrontRange = sb.indexOf("FR"); 
         int endFrontRange = sb.indexOf("/FR"); 

         // get the front range 
         Henry.this.currentFrontRange = sb.substring((startFrontRange + 2), endFrontRange); 
      ... (grab all the information you need here) ... 

         // debugging output what we have 
         // System.out.println("recv: " + sbprint); 

         // clean out the sb to ready next run 
         sb.delete(0, sb.length()); 
        } 

Я сохранить всю информацию, получаемую от последовательного соединения в моем приложении (Henry), то любая деятельность, которая хочет использовать информацию получает его из приложения. Если представление должно иметь обновленную перспективу в отношении информации, я добавляю таймер в представление, чтобы использовать метод обновления так часто, как мне нравится. Это имеет дополнительное преимущество, заключающееся в возможности использовать информацию из любого места в вашем приложении для Android.

Я отправляю около 10 точек данных от ардуино до устройства и около 3 точек данных от устройства до ардуино таким образом. Я добавил свою собственную разметку вокруг datapoints, чтобы идентифицировать их.

Надеюсь, это поможет!

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