蓝牙就像应用不通信一样

时间:2013-07-23 09:15:17

标签: android multithreading chat communication

在开发基于BluetoothChat示例的应用时遇到问题,但分为2个活动。

  1. 主要有蓝牙动作()BTActivity
  2. 聊天(BTCommunication)
  3. 我将BluetoothChatService分成以下文件,但它们不是活动:

    1. 传输:所有处理程序操作
    2. ConnectThread
    3. ConnectedThread
    4. AccpetThread
    5. 应用程序找到de device,开始连接它然后崩溃。我试图找出与BluetoothChat App相比我做错了什么,但我没有发现问题。

      07-23 10:58:43.076: D/AbsListView(17279): unregisterIRListener() is called 
      07-23 10:58:43.076: D/AbsListView(17279): unregisterIRListener() is called 
      07-23 10:58:43.086: D/BluetoothUtils(17279): isSocketAllowedBySecurityPolicy start : device null
      07-23 10:58:43.086: W/BluetoothAdapter(17279): getBluetoothService() called with no BluetoothManagerCallback
      07-23 10:58:43.106: E/SpannableStringBuilder(17279): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
      07-23 10:58:43.106: E/SpannableStringBuilder(17279): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
      07-23 10:58:43.116: D/AbsListView(17279): onDetachedFromWindow
      07-23 10:58:43.116: D/AbsListView(17279): unregisterIRListener() is called 
      07-23 10:58:43.116: D/AbsListView(17279): onDetachedFromWindow
      07-23 10:58:43.116: D/AbsListView(17279): unregisterIRListener() is called 
      07-23 10:58:44.527: D/AndroidRuntime(17279): Shutting down VM
      07-23 10:58:44.527: W/dalvikvm(17279): threadid=1: thread exiting with uncaught exception (group=0x41d58ac8)
      07-23 10:58:44.537: E/AndroidRuntime(17279): FATAL EXCEPTION: main
      07-23 10:58:44.537: E/AndroidRuntime(17279): java.lang.NullPointerException
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.example.btaplication.BTActivity$1.handleMessage(BTActivity.java:288)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at android.os.Handler.dispatchMessage(Handler.java:99)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at android.os.Looper.loop(Looper.java:137)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at android.app.ActivityThread.main(ActivityThread.java:5328)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at java.lang.reflect.Method.invokeNative(Native Method)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at java.lang.reflect.Method.invoke(Method.java:511)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
      07-23 10:58:44.537: E/AndroidRuntime(17279):    at dalvik.system.NativeStart.main(Native Method)
      07-23 10:58:55.428: I/Process(17279): Sending signal. PID: 17279 SIG: 9
      

      /这是主要活动

      public class BTActivity extends Activity {
      
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
      
          setContentView(R.layout.main);
      
          final Button button1 = (Button) findViewById(R.id.boton1);
          final Button button2 = (Button) findViewById(R.id.boton2);
          final Button button4 = (Button) findViewById(R.id.boton4);
          final Button button5 = (Button) findViewById(R.id.boton5);
      
          button5.setOnClickListener(new OnClickListener() {
              @Override
              public void onClick(View view) {
                  lanzarComunicacion (null);
              }
          });
      
      
          GlobalVar.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
      
          if (GlobalVar.mBluetoothAdapter == null) {
              Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
              finish();
              return;
          }
      
          button2.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  LanzarBusqueda(null);
      
              }
          });
      
          button1.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  if (!GlobalVar.mBluetoothAdapter.isDiscovering()) {
      
                      Context context = getApplicationContext();
                      CharSequence text = "MAKING YOUR DEVICE DISCOVERABLE";
                      int duration = Toast.LENGTH_SHORT;
      
                      Toast toast = Toast.makeText(context, text, duration);
                      toast.show();
      
                      Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                      discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
      
                      startActivity(discoverableIntent);
                  }
              }
          });
      
          button4.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  GlobalVar.mBluetoothAdapter.disable();
      
                  Context context = getApplicationContext();
                  CharSequence text = "TURNING OFF BLUETOOTH";
                  int duration = Toast.LENGTH_LONG;
      
                  Toast toast = Toast.makeText(context, text, 15);
                  toast.show();
      
              }
          });
      }
      
      
      @Override
      public void onStart() {
          super.onStart();
      
          if (!GlobalVar.mBluetoothAdapter.isEnabled()) {
      
              Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
              startActivityForResult(enableBtIntent, GlobalVar.REQUEST_ENABLE_BT);
          }
          else {
              if (GlobalVar.mTransmission == null) setupCaller();
          }
      }
      
      
      @Override
      public void onResume() {
          super.onResume();
      
          if (GlobalVar.mTransmission != null) {
              /**Only if the state is STATE_NONE, do we know that we haven't started already*/
              if (GlobalVar.mTransmission.getState() == GlobalVar.STATE_NONE) {
      
              }
          }
      }
      
      
      @Override
      public void onActivityResult(int requestCode, int resultCode, Intent data) {
          switch (requestCode) {
              case GlobalVar.REQUEST_CONNECT_DEVICE:
                  /**When DeviceListActivity returns with a device to connect*/
                  if (resultCode == Activity.RESULT_OK) {
                      connectDevice(data);
                  }
              case GlobalVar.REQUEST_ENABLE_BT:
                  /**When the request to enable Bluetooth returns*/
                  if (resultCode == Activity.RESULT_OK) {
                      /**Bluetooth is now enabled, so set up a chat session*/
                      setupCaller();
                  } else {
                      /**User did not enable Bluetooth or an error occurred*/
                      Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                      finish();
                  }
                  break;
          }
      
      }
      
      
      private void connectDevice(Intent data) {
          /**Get the device MAC address*/
          String address = data.getExtras().getString(DeviceListDialog.EXTRA_DEVICE_ADDRESS);
          /**Get the BluetoothDevice object*/
          BluetoothDevice device = GlobalVar.mBluetoothAdapter.getRemoteDevice(address);
          /**Attempt to connect to the device*/
          try{
              GlobalVar.mTransmission.connect(device);
          }catch(Exception ex) {
          }
      }
      
      
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          /**Inflate the menu; this adds items to the action bar if it is present.*/
          getMenuInflater().inflate(R.menu.bt, menu);
          return true;
      }
      
      public void lanzarComunicacion (View view) {
          Intent i = new Intent(this, BTCommunication.class);
          startActivity(i);
      }
      
      public void LanzarBusqueda (View view) {
          Intent serverintent = new Intent(this, DeviceListDialog.class);
          startActivityForResult(serverintent, GlobalVar.REQUEST_CONNECT_DEVICE);
      }
      
      
      private final void setStatus(int resId) {
          final ActionBar actionBar = getActionBar();
          actionBar.setSubtitle(resId);
      }
      
      private final void setStatus(CharSequence subTitle) {
          final ActionBar actionBar = getActionBar();
          actionBar.setSubtitle(subTitle);
      }
      
      
      /**
       * The Handler that gets information back from the Transmission
       */
      private final Handler mHandler = new Handler() {
          @Override
          public void handleMessage(Message msg) {
              switch (msg.what) {
                  case GlobalVar.MESSAGE_STATE_CHANGE:
                      switch (msg.arg1) {
                          case GlobalVar.STATE_CONNECTED:
                              setStatus(getString(R.string.title_connected_to, GlobalVar.mConnectedDeviceName));
                              GlobalVar.mConversationArrayAdapter.clear();
                              break;
                          case GlobalVar.STATE_CONNECTING:
                              setStatus(R.string.title_connecting);
                              break;
                          case GlobalVar.STATE_LISTEN:
                          case GlobalVar.STATE_NONE:
                              setStatus(R.string.title_not_connected);
                              break;
                      }
                      break;
                  case  GlobalVar.MESSAGE_WRITE:
                      byte[] writeBuf = (byte[]) msg.obj;
                      /**construct a string from the buffer*/
                      String writeMessage = new String(writeBuf);
                      GlobalVar.mConversationArrayAdapter.add("Me:  " + writeMessage);
                      break;
                  case  GlobalVar.MESSAGE_READ:
                      byte[] readBuf = (byte[]) msg.obj;
                      /**construct a string from the valid bytes in the buffer*/
                      String readMessage = new String(readBuf, 0, msg.arg1);
                      GlobalVar.mConversationArrayAdapter.add(GlobalVar.mConnectedDeviceName+":  " + readMessage);
                      break;
                  case  GlobalVar.MESSAGE_DEVICE_NAME:
                      /**save the connected device's name*/
                      GlobalVar.mConnectedDeviceName = msg.getData().getString(GlobalVar.DEVICE_NAME);
                      Toast.makeText(getApplicationContext(), "Connected to " + GlobalVar.mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                      break;
                  case  GlobalVar.MESSAGE_TOAST:
                      Toast.makeText(getApplicationContext(), msg.getData().getString(GlobalVar.TOAST), Toast.LENGTH_SHORT).show();
                      break;
              }
          }
      };
      
      public void setupCaller() {
          /**Initialize the Transmission to perform bluetooth connections*/
          GlobalVar.mTransmission = new Transmission(this, mHandler);
      }
      

      }

      /聊天活动

      public class BTCommunication extends Activity {
      
      
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
      
          /**Set up the window layout*/
          setContentView(R.layout.chat);
      
          /**Start the Bluetooth chat services*/
          GlobalVar.mTransmission.start();
          setupChat(); //PROBAMOS A LLAMAR AQUI\\
      }
      
      
      
      public void setupChat() {
          /**Initialize the array adapter for the conversation thread*/
          GlobalVar.mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
          GlobalVar.mConversationView = (ListView) findViewById(R.id.in);
          GlobalVar.mConversationView.setAdapter(GlobalVar.mConversationArrayAdapter);
      
          /**Initialize the compose field with a listener for the return key*/
          GlobalVar.mOutEditText = (EditText) findViewById(R.id.edit_text_out);
          GlobalVar.mOutEditText.setOnEditorActionListener(mWriteListener);
      
          /**Initialize the send button with a listener that for click events*/
          GlobalVar.mSendButton = (Button) findViewById(R.id.button_send);
          GlobalVar.mSendButton.setOnClickListener(new OnClickListener() {
              @Override
              public void onClick(View v) {
                  /**Send a message using content of the edit text widget*/
                  TextView view = (TextView) findViewById(R.id.edit_text_out);
                  String message = view.getText().toString();
                  sendMessage(message);
              }
          });
      
          /**Initialize the Transmission to perform bluetooth connections*/
          //Done it in BTActivity in the function "setupCaller()"\\
      
      
          /**Initialize the buffer for outgoing messages*/
          GlobalVar.mOutStringBuffer = new StringBuffer("");
      }
      
      
      
      @Override
      public void onDestroy() {
          super.onDestroy();
          /**Stop the Bluetooth chat services*/
          if (GlobalVar.mTransmission != null) GlobalVar.mTransmission.stop();
      }
      
      
      /**
       * Sends a message.
       * @param message  A string of text to send.
       */
      public void sendMessage(String message) {
          /**Check that we're actually connected before trying anything*/
          if (GlobalVar.mTransmission.getState() != GlobalVar.STATE_CONNECTED) {
              Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
              return;
          }
      
          /**Check that there's actually something to send*/
          if (message.length() > 0) {
              /**Get the message bytes and tell the BluetoothChatService to write*/
              byte[] send = message.getBytes();
              GlobalVar.mTransmission.write(send);
      
              /**Reset out string buffer to zero and clear the edit text field*/
              GlobalVar.mOutStringBuffer.setLength(0);
              GlobalVar. mOutEditText.setText(GlobalVar.mOutStringBuffer);
          }
      }
      
      /**The action listener for the EditText widget, to listen for the return key*/
      private final TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() {
          @Override
          public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
              /**If the action is a key-up event on the return key, send the message*/
              if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
                  String message = view.getText().toString();
                  sendMessage(message);
              }
              return true;
          }
      };
      

      }

      /传输文件:

      public class Transmission {
      
      /**
       * Constructor. Prepares a new session.
       * @param context  The UI Activity Context
       * @param handler  A Handler to send messages back to the UI Activity
       */
      public Transmission(Context context, Handler handler) {
          GlobalVar.mAdapter = BluetoothAdapter.getDefaultAdapter();
          GlobalVar.mState = GlobalVar.STATE_NONE;
          GlobalVar.mHandler = handler;
      }
      
      /**
       * Set the current state of the connection
       * @param state  An integer defining the current connection state
       */
      public synchronized void setState(int state) {
          GlobalVar.mState = state;
      
          /**Give the new state to the Handler so the UI Activity can update*/
          GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
      }
      
      /**
       * Return the current connection state.
       */
      public synchronized int getState() {
          return GlobalVar.mState;
      }
      
      /**
       * Start the chat service. Specifically start AcceptThread to begin a
       * session in listening (server) mode. Called by the Activity onResume()
       */
      public synchronized void start() {
          /**Cancel any thread attempting to make a connection*/
          if (GlobalVar.mConnectThread != null) {GlobalVar.mConnectThread.cancel(); GlobalVar.mConnectThread = null;}
      
          /**Cancel any thread currently running a connection*/
          if (GlobalVar.mConnectedThread != null) {GlobalVar.mConnectedThread.cancel(); GlobalVar.mConnectedThread = null;}
      
          setState(GlobalVar.STATE_LISTEN);
      
          /**Start the thread to listen on a BluetoothServerSocket*/
          if (GlobalVar.mAcceptThread == null) {
              GlobalVar.mAcceptThread = new AcceptThread();
              GlobalVar.mAcceptThread.start();
          }
      }
      
      /**
       * Start the ConnectThread to initiate a connection to a remote device.
       * @param device  The BluetoothDevice to connect
       */
      public synchronized void connect(BluetoothDevice device) {
          /**Cancel any thread attempting to make a connection*/
          if (GlobalVar.mState == GlobalVar.STATE_CONNECTING) {
              if (GlobalVar.mConnectThread != null) {GlobalVar.mConnectThread.cancel(); GlobalVar.mConnectThread = null;}
          }
      
          /**Cancel any thread currently running a connection*/
          if (GlobalVar.mConnectedThread != null) {GlobalVar.mConnectedThread.cancel(); GlobalVar.mConnectedThread = null;}
      
          /**Start the thread to connect with the given device*/
          GlobalVar.mConnectThread = new ConnectThread(device);
          GlobalVar.mConnectThread.start();
          setState(GlobalVar.STATE_CONNECTING);
      }
      
      /**
       * Start the ConnectedThread to begin managing a Bluetooth connection
       * @param socket  The BluetoothSocket on which the connection was made
       * @param device  The BluetoothDevice that has been connected
       */
      public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
          /**Cancel the thread that completed the connection*/
          if (GlobalVar.mConnectThread != null) {GlobalVar.mConnectThread.cancel(); GlobalVar.mConnectThread = null;}
      
          /**Cancel any thread currently running a connection*/
          if (GlobalVar.mConnectedThread != null) {GlobalVar.mConnectedThread.cancel(); GlobalVar.mConnectedThread = null;}
      
          /**Cancel the accept thread because we only want to connect to one device*/
          if (GlobalVar.mAcceptThread != null) {
              GlobalVar.mAcceptThread.cancel();
              GlobalVar.mAcceptThread = null;
          }
      
          /**Start the thread to manage the connection and perform transmissions*/
          GlobalVar.mConnectedThread = new ConnectedThread(socket);
          GlobalVar.mConnectedThread.start();
      
          /**Send the name of the connected device back to the UI Activity*/
          Message msg = GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_DEVICE_NAME);
          Bundle bundle = new Bundle();
          bundle.putString(GlobalVar.DEVICE_NAME, device.getName());
          msg.setData(bundle);
          GlobalVar.mHandler.sendMessage(msg);
      
          setState(GlobalVar.STATE_CONNECTED);
      }
      
      /**
       * Stop all threads
       */
      public synchronized void stop() {
      
          if (GlobalVar.mConnectThread != null) {
              GlobalVar.mConnectThread.cancel();
              GlobalVar.mConnectThread = null;
          }
      
          if (GlobalVar.mConnectedThread != null) {
              GlobalVar.mConnectedThread.cancel();
              GlobalVar.mConnectedThread = null;
          }
      
          if (GlobalVar.mAcceptThread != null) {
              GlobalVar.mAcceptThread.cancel();
              GlobalVar.mAcceptThread = null;
          }
      
          setState(GlobalVar.STATE_NONE);
      }
      
      /**
       * Write to the ConnectedThread in an unsynchronized manner
       * @param out The bytes to write
       * @see ConnectedThread#write(byte[])
       */
      public void write(byte[] out) {
          /**Create temporary object*/
          ConnectedThread r;
          /**Synchronize a copy of the ConnectedThread*/
          synchronized (this) {
              if (GlobalVar.mState != GlobalVar.STATE_CONNECTED) return;
              r = GlobalVar.mConnectedThread;
          }
          /**Perform the write unsynchronized*/
          r.write(out);
      }
      
      /**
       * Indicate that the connection attempt failed and notify the UI Activity.
       */
      public void connectionFailed() {
          /**Send a failure message back to the Activity*/
          Message msg = GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_TOAST);
          Bundle bundle = new Bundle();
          bundle.putString(GlobalVar.TOAST, "Unable to connect device");
          msg.setData(bundle);
          GlobalVar.mHandler.sendMessage(msg);
      
          /**tart the service over to restart listening mode*/
          Transmission.this.start();
      }
      
      /**
       * Indicate that the connection was lost and notify the UI Activity.
       */
      public void connectionLost() {
          /**Send a failure message back to the Activity*/
          Message msg = GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_TOAST);
          Bundle bundle = new Bundle();
          bundle.putString(GlobalVar.TOAST, "Device connection was lost");
          msg.setData(bundle);
          GlobalVar.mHandler.sendMessage(msg);
      
          /**Start the service over to restart listening mode*/
          Transmission.this.start();
      }
      

      }

      / Accept,connect和connected线程与BleutoothChat应用程序相同,但每个都有自己的文件。

1 个答案:

答案 0 :(得分:1)

07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.example.btaplication.BTActivity$1.handleMessage(BTActivity.java:288)

您的处理程序需要更多条件。它崩溃了,因为你的BTActivity中有一个空指针。

2周前我确实遇到过这个问题(我试图在Handler中更改textview的文本)。所以,在我的处理程序中,我只是说:

if(mTextView == null) {mTextView = (TextView) findViewById(R.id.tv)}

即使之前定义了mTextView。在这种情况下,您将确保您的属性已定义,并且您将避免使用NPE

希望有所帮助