2013-08-19 53 views
0

我是新來的android +藍牙。我正在嘗試編寫一個簡單的rfcomm客戶端應用程序,它與在嵌入式平臺上運行的rfcomm服務器通信。當我的應用程序啓動時,它會顯示配對設備的列表視圖,並在點擊其中一個設備時跳轉到第二個活動。在這個活動中,我打開一個藍牙套接字並連接到它。只要我跳到一個新的活動,我的UI排序掛起。這項新活動有兩個按鈕。點擊這些按鈕我發送數據到藍牙服務器。但是,我的UI類型在這個活動中掛起,一旦我點擊一個需要很長時間才能響應的按鈕,它會生成一條錯誤消息。android ui掛起時,從一個活動寫入藍牙設備

我的代碼看起來是這樣的:

package com.example.bluetoothapp2; 

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

import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothSocket; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.EditText; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.Toast; 

public class MainActivity extends Activity { 

// Return Intent extra 
public static String EXTRA_DEVICE_ADDRESS = "device_address"; 

public int REQUEST_ENABLE_BT = 1;// Just defining a flag 
//Define a local bluetooth adapter variable to get id of default Adapter 
public BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 

//Adapter for LIST ITEMS FOR PAIRED DEVICES 
public ArrayAdapter<String> mPairedDevicesArrayAdapter; 
//Array to store list data for paired device 
ArrayList<String> itemPairedArray = new ArrayList<String>(); 

//Adapter for LIST ITEMS FOR NEW DEVICES  
public ArrayAdapter<String> mNewDevicesArrayAdapter; 
//Array to store list data for paired device 
ArrayList<String> itemNewDvcArray = new ArrayList<String>(); 

//RECORDING HOW MUCH TIMES BUTTON WAS CLICKED 
int clickCounter=0; 

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

private void init() 
{ 
    //GetListId from Layout 
    ListView pairedListView = (ListView) findViewById(R.id.listPairedDvc); 
    ListView newListView = (ListView) findViewById(R.id.listAvailableDvc); 

    //Bind the list with listview in layout 
    mPairedDevicesArrayAdapter= new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,itemPairedArray);  
    mNewDevicesArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,itemNewDvcArray); 

    //Set the adapter to list view (bind a adapter to listview in layout) 
    pairedListView.setAdapter(mPairedDevicesArrayAdapter); 
    newListView.setAdapter(mNewDevicesArrayAdapter); 

    pairedListView.setOnItemClickListener(mDeviceClickListener); 

    // Register the BroadcastReceiver 
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 
    registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy 

    // Register for broadcasts when discovery has finished 
    filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 
    this.registerReceiver(mReceiver, filter); 

    // Register for broadcasts when discovery has finished 
    filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 
    this.registerReceiver(mReceiver, filter); 

    // Get a set of currently paired devices 
    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); 

     // If there are paired devices, add each one to the ArrayAdapter 
     if (pairedDevices.size() > 0) 
     { 
      /*findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);*/ 
      for (BluetoothDevice device : pairedDevices) 
      { 
      itemPairedArray.add(device.getName() + " => "+ device.getAddress()); 
      }   
     } 
     else 
     { 
     itemPairedArray.add("noDevices"); 
     } 

    //Check if device has bluetooth 
    if(mBluetoothAdapter == null) 
    { 
     Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); 
     finish(); 
     return; 
    } 
    //Check if it is enabled or not 
    if(!mBluetoothAdapter.isEnabled()) 
    { 
     Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
     startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); 
    } 
} 

//METHOD WHICH WILL HANDLE DYNAMIC INSERTION 
public void addItems(View v) 
{ 
    //itemPairedArray.add("Clicked : "+clickCounter++); //Just for debugging 
    //itemNewDvcArray.add("Clicked : "+clickCounter++); //Just for debugging 
    //itemNewDvcArray.add("NoDevice"); 
    startDiscovery() ; 

    //mPairedDevicesArrayAdapter.notifyDataSetChanged(); 
    mNewDevicesArrayAdapter.notifyDataSetChanged();  
} 

//method to start discovery 
private void startDiscovery() 
{ 
    // TODO Auto-generated method stub 
    // If we're already discovering, stop it 
    if (mBluetoothAdapter.isDiscovering()) 
    { 
     mBluetoothAdapter.cancelDiscovery(); 
    } 

    // Request discover from BluetoothAdapter 
    mBluetoothAdapter.startDiscovery(); 
} 

protected void onDestroy() 
{ 
    super.onDestroy(); 

    // Make sure we're not doing discovery anymore 
    if (mBluetoothAdapter != null) 
    { 
     mBluetoothAdapter.cancelDiscovery(); 
    } 

    // Unregister broadcast listeners 
    this.unregisterReceiver(mReceiver); 
}  

// The BroadcastReceiver that listens for discovered devices and 
// changes the title when discovery is finished 
private final BroadcastReceiver mReceiver = new BroadcastReceiver() 
{ 
public void onReceive(Context context, Intent intent) 
{ 
     String action = intent.getAction(); 
     // When discovery finds a device 
     if (BluetoothDevice.ACTION_FOUND.equals(action)) 
     { 
      // Get the BluetoothDevice object from the Intent 
      BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 

      // If it's already paired, skip it, because it's been listed already 
      if (device.getBondState() != BluetoothDevice.BOND_BONDED) 
      { 
        // Add the name and address to an array adapter to show in a ListView 
        itemNewDvcArray.add(device.getName() +" => "+ device.getAddress());    
      }     
     }   
    } 
    };  

    // The on-click listener for all devices in the ListViews 
    private OnItemClickListener mDeviceClickListener = new OnItemClickListener() 
    { 
    public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) 
    { 
     // Get the device MAC address, which is the last 17 chars in the View 
     String info = ((TextView) v).getText().toString(); 
     String address = info.substring(info.length() - 17); 

     //Toast.makeText(getApplicationContext(), address, 0).show(); 
     // Create the result Intent and include the MAC address 
     Intent intent = new Intent(MainActivity.this,ConnectActivity.class); 
     intent.putExtra(EXTRA_DEVICE_ADDRESS, address); 

     startActivity(intent); 
     } 
    }; 
} 


    package com.example.bluetoothapp2; 

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

import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothSocket; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.Toast; 

public class ConnectActivity extends Activity { 

// Unique UUID for this application 
public static final UUID MY_UUID_INSECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 

String address; 
protected static final int SUCCESS_CONNECT = 0; 
protected static final int MESSAGE_READ = 1; 
public BluetoothSocket mmSocket; 
public InputStream mmInStream; 
public OutputStream mmOutStream;  
String tag = "debugging"; 

private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
Handler mHandler = new Handler(){ 
    @Override 
    public void handleMessage(Message msg) 
    { 
     // TODO Auto-generated method stub 
     Log.i(tag, "in handler"); 
     super.handleMessage(msg); 
     switch(msg.what){ 
     case SUCCESS_CONNECT: 
      // DO something 
      ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket)msg.obj); 
      //Toast.makeText(getApplicationContext(), "CONNECT", 0).show(); 
      String s = "successfully connected"; 
      connectedThread.write(s.getBytes()); 
      Log.i(tag, "connected"); 
      break; 
     case MESSAGE_READ: 
      byte[] readBuf = (byte[])msg.obj; 
      String string = new String(readBuf); 
      //Toast.makeText(getApplicationContext(), string, 0).show(); 
      break; 
     } 
    } 
}; 

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

    // Get the message from the intent 
    Intent intent = getIntent(); 
    address = intent.getStringExtra(MainActivity.EXTRA_DEVICE_ADDRESS); 

    // Create the text view 
    TextView textView = (TextView)findViewById(R.id.addrs); 
    //textView.setTextSize(40); 
    textView.setText(address); 

    connect(); 
} 

//method to start discovery 
public void connect() 
{ 
    // Get the BluetoothDevice object 
    BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); 

    //Toast.makeText(getApplicationContext(),"connecting", 0).show(); 
    ConnectThread connect = new ConnectThread(device) ; 
    connect.start(); 
} 

//Thread for establising a connection 
private class ConnectThread extends Thread 
{ 
    private final BluetoothSocket mmSocket; 
    private final BluetoothDevice mmDevice; 

    public ConnectThread(BluetoothDevice device) 
    { 
     // Use a temporary object that is later assigned to mmSocket, 
     // because mmSocket is final 
     BluetoothSocket tmp = null; 
     mmDevice = device; 

     // Get a BluetoothSocket to connect with the given BluetoothDevice 
     try { 
      // MY_UUID is the app's UUID string, also used by the server code 
      tmp = device.createRfcommSocketToServiceRecord(MY_UUID_INSECURE); 
     } catch (IOException e) { } 
     mmSocket = tmp; 
    } 

    public void run() 
    { 
     // Cancel discovery because it will slow down the connection 
     mBluetoothAdapter.cancelDiscovery(); 

     try { 
      // Connect the device through the socket. This will block 
      // until it succeeds or throws an exception 
      mmSocket.connect(); 
     } catch (IOException connectException) { 
      // Unable to connect; close the socket and get out 
      try { 
       mmSocket.close(); 
      } catch (IOException closeException) { } 
      return; 
     } 

     // Do work to manage the connection (in a separate thread) 
     //manageConnectedSocket(mmSocket); 
     mHandler.obtainMessage(SUCCESS_CONNECT, mmSocket).sendToTarget(); 
    } 

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

private class ConnectedThread extends Thread 
{ 
    public ConnectedThread(BluetoothSocket socket) { 
     mmSocket = 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 ; // 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 
       buffer = new byte[1024]; 
       bytes = mmInStream.read(buffer); 
       // Send the obtained bytes to the UI activity 
       mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget(); 
      } catch (IOException e) { 
       break; 
      } 
     } 
    } 

    /* Call this from the main activity to send data to the remote device */ 
    public void write(byte[] bytes) { 
     try { 
      //a delay of 20ms occurs after each flush... 
      mmOutStream.write(bytes); 
      mmOutStream.flush(); 
     } catch (IOException e) { } 
    } 

    /* Call this from the main activity to shutdown the connection */ 
    public void cancel() { 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { } 
    } 
}  

//method to start discovery 
public void ledOn(View v) throws IOException 
{ 
    //Toast.makeText(getApplicationContext(),"LED ON", 0).show(); 
    mmOutStream.write('o'); 
} 

//method to start discovery 
public void ledOff(View v) throws IOException 
{ 
    //Toast.makeText(getApplicationContext(),"LED OFF", 0).show(); 
    mmOutStream.write('f'); 
} 

public void disconnectCntn(View v) throws IOException 
{ 
    String msg = "Disconnect"; 
    mmOutStream.write(msg.getBytes()); 
    // close the connection 
    mmOutStream.close(); 
    mmInStream.close(); 
    // close the connection 
    if (mmSocket != null) 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    return; 
} 

}

我得到以下錯誤消息

08-19 13:09:55.833: D/AndroidRuntime(5221): Shutting down VM 
08-19 13:09:55.834: W/dalvikvm(5221): threadid=1: thread exiting with uncaught exception (group=0x41cc29a8) 
08-19 13:09:55.847: E/AndroidRuntime(5221): FATAL EXCEPTION: main 
08-19 13:09:55.847: E/AndroidRuntime(5221): java.lang.IllegalStateException: Could not execute method of the activity 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.view.View$1.onClick(View.java:3606) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.view.View.performClick(View.java:4211) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.view.View$PerformClick.run(View.java:17446) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.os.Handler.handleCallback(Handler.java:725) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.os.Handler.dispatchMessage(Handler.java:92) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.os.Looper.loop(Looper.java:153) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.app.ActivityThread.main(ActivityThread.java:5299) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at java.lang.reflect.Method.invokeNative(Native Method) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at java.lang.reflect.Method.invoke(Method.java:511) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at dalvik.system.NativeStart.main(Native Method) 
08-19 13:09:55.847: E/AndroidRuntime(5221): Caused by: java.lang.reflect.InvocationTargetException 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at java.lang.reflect.Method.invokeNative(Native Method) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at java.lang.reflect.Method.invoke(Method.java:511) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.view.View$1.onClick(View.java:3601) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  ... 11 more 
08-19 13:09:55.847: E/AndroidRuntime(5221): Caused by: java.io.IOException: [JSR82] write: write() failed. 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:702) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at android.bluetooth.BluetoothOutputStream.write(BluetoothOutputStream.java:56) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  at com.example.bluetoothapp2.ConnectActivity.ledOn(ConnectActivity.java:213) 
08-19 13:09:55.847: E/AndroidRuntime(5221):  ... 14 more 

對不起,這麼長的帖子。任何想法爲什麼是用戶界面掛起,什麼可能導致錯誤。

感謝 摩

回答

0

ConnectedThread被實例化,但是我們跳過這在它啓動線程,花式調用start()的一部分嗎? connectedThread.start()將保持它在套接字上監聽寫入的任何數據。

ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket)msg.obj); 
//add this line 
connectedThread.start() 
//Toast.makeText(getApplicationContext(), "CONNECT", 0).show(); 
String s = "successfully connected"; 
connectedThread.write(s.getBytes());