2015-04-23 80 views
0

我是Android的新手。我的應用程序使用語音識別,TextToSpeech並通過藍牙從Android手機(SAMSUNG Galaxy Note | OS:Android 4.1.2)發送數據到Arduino。它每次只能發送一次數據,並且無法發送(通過IOException),所以應用程序finish()。以下是我的代碼。Android語音識別和通過藍牙向Arduino發送數據。我怎樣才能多次發送數據?

的Android代碼

package com.itcdroid.smarthome; 

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

import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothSocket; 
import android.content.ActivityNotFoundException; 
import android.content.Intent; 
import android.os.Bundle; 
import android.speech.RecognizerIntent; 
import android.speech.tts.TextToSpeech; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.ImageButton; 
import android.widget.TextView; 
import android.widget.Toast; 

public class MainActivity extends Activity implements 
    TextToSpeech.OnInitListener { 

    //Tag for logging 
    private static final String TAG = "ITCDroid"; 

    private static final int REQUEST_ENABLE_BT = 1; 
    private BluetoothAdapter mBluetoothAdapter = null; 
    private BluetoothSocket mBluetoothSocket = null; 
    private OutputStream outStream = null; 

    //MAC address of remote Bluetooth device 
    private final String address = "98:D3:31:B4:34:EE"; 

    // UUID that specifies a protocol for generic bluetooth serial communication 
    //Well known SPP UUID 
    private static final UUID MY_UUID = 
      UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 

    private TextToSpeech tts; 
    private String ttsText; 
    private TextView txtSpeechInput; 
    private ImageButton btnSpeak; 
    private final int REQ_CODE_SPEECH_INPUT = 100; 

    // Available commands 
    private static final String[] commands = {"on", "off", "turn on the light", "turn off the light"}; 
    boolean foundCommand; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     checkBtState(); 

     tts = new TextToSpeech(this, this); 
     txtSpeechInput = (TextView) findViewById(R.id.txtSpeechInput); 
     btnSpeak = (ImageButton) findViewById(R.id.btnSpeak); 

     // hide the action bar 
     //getActionBar().hide(); 

     //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     //checkBtState(); 

     btnSpeak.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       promptSpeechInput(); 
      } 
     }); 

    } 

    @Override 
    public void onResume() { 
     super.onResume(); 

     Log.d(TAG, "...In onResume - Attempting client connect..."); 

     //Set up a pointer to the remote node using it's address. 
     BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); 

     // Two things are needed to make a connection: 
     // A MAC address, which we got above. 
     // A Service ID or UUID. in this case we are using the UUID for SPP 
     try { 
      mBluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID); 
     } catch (IOException e) { 
      errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + "."); 
     } 

     // Discovery is resource intensive. Make sure it isn't going on 
     // when you attempt to connect and pass your message. 
     mBluetoothAdapter.cancelDiscovery(); 

     // Establish the connection. This will block until is connects. 
     Log.d(TAG, "...Connecting to Remote..."); 
     try { 
      mBluetoothSocket.connect(); 
      Log.d(TAG, "...Connection established and data link opened..."); 
     } catch(IOException e) { 
      try { 
       mBluetoothSocket.close(); 
      } catch (IOException e2) { 
       errorExit("Fatal Error", "In onResume() and unable to close socket during connection failture" + e2.getMessage() + "."); 
      } 
     } 

     //Create a data stream so we can talk to server. 
     Log.d(TAG, "...Creating Socket..."); 

     try { 
      outStream = mBluetoothSocket.getOutputStream(); 
     } catch (IOException e) { 
      errorExit("Fatal Error", "In onResume() and output stream creation failture: " + e.getMessage() + "."); 
     } 
    } 

    @Override 
    public void onPause(){ 
     super.onPause(); 
     Log.d(TAG, "...In onPause()..."); 

     if (outStream != null) { 
      try { 
       outStream.flush(); 
      } catch (IOException e) { 
       errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + "."); 
      } 
     } 
    } 

    /** Will cancel an in-progress connection, and close the socket */ 
    public void cancel() { 
     try { 
      mBluetoothSocket.close(); 
     } catch (IOException e) { } 
    } 

    private void checkBtState() { 
     // TODO Auto-generated method stub 
     //Check for Bluetooth support and then check to make sure it is turned on 
     if (mBluetoothAdapter == null) { 
      errorExit("Fatal Error", "Bluetooth Not supported. Aborting."); 
     } else { 
      if (mBluetoothAdapter.isEnabled()) { 
       Log.d(TAG, "...Bluetooth is enabled..."); 
      } else { 
       //Prompt user to turn on Bluetooth 
       Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
       startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); 
      } 
     } 

    } 

    /** 
    * Showing google speech input dialog 
    * */ 
    private void promptSpeechInput() { 
     Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 
     intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
       RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); 
     intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); 
     intent.putExtra(RecognizerIntent.EXTRA_PROMPT, 
       getString(R.string.speech_prompt)); 
     try { 
      startActivityForResult(intent, REQ_CODE_SPEECH_INPUT); 
     } catch (ActivityNotFoundException a) { 
      Toast.makeText(getApplicationContext(), 
        getString(R.string.speech_not_supported), 
        Toast.LENGTH_SHORT).show(); 
     } 
    } 

    /** 
    * Receiving speech input 
    * */ 
    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

     switch (requestCode) { 
     case REQ_CODE_SPEECH_INPUT: { 
      if (resultCode == RESULT_OK && null != data) { 

       ArrayList<String> result = data 
         .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); 

       foundCommand = false; 
       for(String command : commands) { 
        if(result.contains(command)) { 
         foundCommand = true; 
         if(command == "on") { 
          txtSpeechInput.setText("You say -on-"); 
          ttsText = "The light is turn on now."; 
          speakOut(); 
          sentData("1"); 
         } 
         else if(command == "off") { 
          txtSpeechInput.setText("You say -off-"); 
          ttsText = "The light is turn off now."; 
          speakOut(); 
          sentData("2"); 
         } 
         else if(command == "turn on the light") { 
          txtSpeechInput.setText("You say -turn on the light-"); 
          ttsText = "The light is turn on now."; 
          speakOut(); 
          sentData("1"); 
         } 
         else if(command == "turn off the light") { 
          txtSpeechInput.setText("You say -turn off the light-"); 
          ttsText = "The light is turn off now."; 
          speakOut(); 
          sentData("2"); 
         } 
        } 
       } 

       if (!foundCommand) { 
        txtSpeechInput.setText("Unknown what you say"); 
        ttsText = "I don't know what you want!"; 
        speakOut(); 
       } 
       //txtSpeechInput.setText(result.get(0)); 
      } 
      break; 
     } 

     } 
    } 

    @Override 
    public void onDestroy() { 
     // Don't forget to shutdown! 
     if (tts != null) { 
      tts.stop(); 
      tts.shutdown(); 
     } 
     super.onDestroy(); 
    } 

    @Override 
    public void onInit(int status) { 
     // TODO Auto-generated method stub 

     if (status == TextToSpeech.SUCCESS) { 

      int result = tts.setLanguage(Locale.US); 

      // tts.setPitch(5); // set pitch level 

      // tts.setSpeechRate(2); // set speech speed rate 

      if (result == TextToSpeech.LANG_MISSING_DATA 
        || result == TextToSpeech.LANG_NOT_SUPPORTED) { 
       Log.e("TTS", "Language is not supported"); 
      } else { 
       //btnSpeak.setEnabled(true); 
       speakOut(); 
      } 

     } else { 
      Log.e("TTS", "Initilization Failed"); 
     } 

    } 

    //@SuppressWarnings("deprecation") 
    private void speakOut() { 

     String text = ttsText; 

     tts.speak(text, TextToSpeech.QUEUE_FLUSH, null); 
    } 

    private void sentData(String message) { 
     // TODO Auto-generated method stub 
     byte[] msgBuffer = message.getBytes(); 

     Log.d(TAG, "...Sending data: " + message + "..."); 
     try { 
      outStream.write(msgBuffer); 
      outStream.close(); 
      reConnectBT(); 
     } catch (IOException e) { 
      String msg = "In onResume() and an exception occurred during write:" + e.getMessage(); 
      msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + "exists on server.\n\n"; 

      errorExit("sentData IOException", msg); 
     } 

    } 

    private void reConnectBT() { 
     // TODO Auto-generated method stub 
     Log.d(TAG, "...In reConnectBT - Attempting client connect..."); 

     //Set up a pointer to the remote node using it's address. 
     BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); 

     // Two things are needed to make a connection: 
     // A MAC address, which we got above. 
     // A Service ID or UUID. in this case we are using the UUID for SPP 
     try { 
      mBluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID); 
     } catch (IOException e) { 
      errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + "."); 
     } 

     // Discovery is resource intensive. Make sure it isn't going on 
     // when you attempt to connect and pass your message. 
     mBluetoothAdapter.cancelDiscovery(); 

     // Establish the connection. This will block until is connects. 
     Log.d(TAG, "...Connecting to Remote..."); 
     try { 
      mBluetoothSocket.connect(); 
      Log.d(TAG, "...Connection established and data link opened..."); 
     } catch(IOException e) { 
      try { 
       mBluetoothSocket.close(); 
      } catch (IOException e2) { 
       errorExit("Fatal Error", "In onResume() and unable to close socket during connection failture" + e2.getMessage() + "."); 
      } 
     } 

     //Create a data stream so we can talk to server. 
     Log.d(TAG, "...Creating Socket..."); 

     try { 
      outStream = mBluetoothSocket.getOutputStream(); 
     } catch (IOException e) { 
      errorExit("Fatal Error", "In onResume() and output stream creation failture: " + e.getMessage() + "."); 
     } 

    } 

    private void errorExit(String title, String message) { 
     // TODO Auto-generated method stub 
     Toast msg= Toast.makeText(getBaseContext(), 
       title, Toast.LENGTH_SHORT); 
     msg.show(); 
     finish(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 
     if (id == R.id.action_settings) { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
} 
+0

歡迎來到Stack Overflow!我已經從問題中刪除了您的電子郵件地址。然而,這個問題仍然太長,請考慮如何減少代碼大小,以便我們可以幫助解決您的問題。此外,請包括與您所得例外相關的LogCat輸出。 –

+0

對不起肯Y-N,因爲**模擬器**沒有藍牙,所以我無法得到有關異常的所有信息。 –

回答

0

看來,你做了很多雜耍的連接並從您的藍牙設備,這可能會損害你的表現斷開。您正在做的另一件事是直接在UI線程中管理所有繁重的藍牙進程,這將使您的應用程序鎖定,直到連接完成。

Here's一個鏈接到我的項目的存儲庫,我在它做簡單的藍牙連接,並作爲一個包裝管理連接狀態的包裝。隨意使用源代碼,但要小心,我一直在積極改變它。如果您選擇使用它的代碼,執行會去是這樣的:

InputStream mInputStream; 
OutputStream mOutputStream; 

BluetoothConnection mConnection = new BluetoothConnection("Connection Name", "98:D3:31:B4:34:EE"); 
mConnection.setOnConnectStatusChangedListener(this, new onConnectStatusChangedListener() { 
    @Override 
    public void onConnect() { 
    /* 
    * Connecting to bluetooth takes some time, it won't be ready immediately. 
    * Set some actions here that let your program know that the connection 
    * finished successfully. For example, 
    */ 
    mInputStream = mConnection.getInputStream(); 
    mOutputStream = mConnection.getOutputStream(); 

    //Use some method of your own to write data 
    sendDataToBluetoothDevice(mOutputStream); 
    } 

    @Override 
    public void onDisconnect() { 
    /* 
    * Same thing applies to disconnecting, set some actions to occur 
    * when the disconnect is confirmed. 
    */ 
    } 
} 

/* 
* Internally, this launches an AsyncTask to handle connecting, 
* which is why we need the onConnectStatusChangedListener 
* callbacks. 
*/ 
mConnection.connect(); 

//To disconnect: 
mConnection.disconnect(); 

這應該處理所有繁重的任務在後臺進程簡化你的東西。至於讀寫不止一次,只要正確使用InputStream和OutputStream,您就應該是金手指。

+0

謝謝CodeWhisperer的回覆。我會盡量按照你的建議。 –

+0

最近我一直在進行大量的檢修,正如我提到的那樣,這是我的活躍項目,它還很年輕。一定要跟蹤其他文件以及它們如何將數據傳輸到另一個文件。需要注意的重要類有:Connection,BluetoothConnection,BluetoothConnectionService,TECIntent和TerminalActivity。目前,BluetoothConnectionService負責處理所有的連接,而不是當我發佈的時候,所有連接都由'BluetoothConnection'自己管理。我會盡力保持我的代碼充分記錄,因爲我去:) – nicholastmosher