我是android +蓝牙的新手。我正在尝试编写一个简单的 rfcomm 客户端应用程序,它与在嵌入式平台上运行的 rfcomm 服务器通信。当我的应用程序启动时,它会显示配对设备的列表视图,并在单击其中一个设备时跳转到第二个活动。在这个活动中,我打开一个蓝牙插座并连接到它。一旦我跳到一个新的活动,我的 UI 就会挂起。这个新活动有两个按钮。Onclick 这些按钮我将数据发送到蓝牙服务器。但是我的 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
抱歉发了这么长的帖子。知道为什么 UI 挂起以及可能导致错误的原因。
谢谢多摩