如何在Android蓝牙连接中继续传输数据?

时间:2014-06-18 05:46:43

标签: android multithreading bluetooth

我正在开发一个Android应用程序,它将查询传输到蓝牙设备并从中检索数据。在应用程序中,通过点击屏幕上方的可用设备建立连接,然后在下半部分有一个按钮,触发发送查询,旁边的文本框显示数据。

我能够成功连接到设备并从中获取一次数据,但是当我第二次点击查询按钮时,应用程序崩溃了。

在代码中,我按下按钮后启动ConnectedThread线程,然后在线程代码的末尾调用一个处理程序,然后在屏幕上显示文本。我第二次按下按钮,我的代码再次尝试启动相同的线程 - 这会导致错误。 一旦接收到收到的数据,我一直试图阻止connectedThread 这样我可以为每次发送 - 接收启动和关闭connectedThread。

您能否建议解决问题的方法或即兴创作代码结构的方法。任何帮助将不胜感激。 感谢

    package com.test.bluetooth;

    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.Button;
    import android.widget.EditText;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.widget.Toast;

        public class Main_Activity extends Activity implements OnItemClickListener {

    public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    protected static final int SUCCESS_CONNECT = 0;
    protected static final int MESSAGE_READ = 1;

    BluetoothAdapter btAdapter;
    Set<BluetoothDevice> devicesArray;
    ArrayList<String> pairedDevices;
    ArrayList<BluetoothDevice> devices;

    ArrayAdapter<String> listAdapter;
    ListView listView;
    Button mConnect;
    TextView mResponse;
    IntentFilter filter;
    BroadcastReceiver receiver;
    String tag = "Debug";

    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            Log.i(tag, "Handler starts");
            super.handleMessage(msg);
            switch(msg.what){
            case SUCCESS_CONNECT:


                final ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
                Toast.makeText(getApplicationContext(), "Connected", 0).show();

                mConnect.setOnClickListener(
                        new View.OnClickListener()
                        {
                            public void onClick(View view)
                            {
                                //Log.v("EditText", mCommand.getText().toString());
                                //String Command = mCommand.getText().toString();

                                byte[] inputs = {0x30, 0x31, 0x30, 0x44, 0x0d, 0x0a};
                                connectedThread.write(inputs);

                                Log.i(tag, "sent ");
                                connectedThread.start();
                                Log.i(tag, "sent 2");

                            } 
                        });
                break;
            case MESSAGE_READ:
                byte[] TxBuf = (byte[])msg.obj;
                String string = new String(TxBuf);
                Log.d("ReceiverValue", string);

                mResponse.setText(string); 

                break;
            }
        }
    };


    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
            long arg3) {
        // TODO Auto-generated method stub

        if(btAdapter.isDiscovering()){
            btAdapter.cancelDiscovery();
        }
        if(listAdapter.getItem(arg2).contains("Paired")){

            BluetoothDevice selectedDevice = devices.get(arg2);
            ConnectThread connect = new ConnectThread(selectedDevice);
            connect.start();
            Log.i(tag, "in click listener");
        }
        else{
            Toast.makeText(getApplicationContext(), "device is not paired", 0).show();
        }
    }




    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        init();
        if(btAdapter==null){
            Toast.makeText(getApplicationContext(), "No bluetooth detected", 0).show();
            finish();
        }
        else{
            if(!btAdapter.isEnabled()){
                turnOn();
            }   
            getPairedDevices();
            startDiscovery();
        }
    }
    private void startDiscovery() {
        // TODO Auto-generated method stub
        btAdapter.cancelDiscovery();
        btAdapter.startDiscovery();
    }
    private void turnOn() {
        // TODO Auto-generated method stub
        Intent intent =new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(intent, 1);
    }
    private void getPairedDevices() {
        // TODO Auto-generated method stub
        devicesArray = btAdapter.getBondedDevices();
        if(devicesArray.size()>0){
            for(BluetoothDevice device:devicesArray){
                pairedDevices.add(device.getName());

            }
        }
    }
    private void init() {
        // TODO Auto-generated method stub
        listView=(ListView)findViewById(R.id.listView);
        mConnect=(Button)findViewById(R.id.bConnectNew);
        //mCommand=(EditText)findViewById(R.id.etCommand);
        mResponse=(TextView)findViewById(R.id.tvResponse);

        listView.setOnItemClickListener(this);
        listAdapter= new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,0);
        listView.setAdapter(listAdapter);

        btAdapter = BluetoothAdapter.getDefaultAdapter();
        pairedDevices = new ArrayList<String>();
        filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        devices = new ArrayList<BluetoothDevice>();
        receiver = new BroadcastReceiver(){
            @Override
            public void onReceive(Context context, Intent intent) {
                // TODO Auto-generated method stub
                String action = intent.getAction();

                if(BluetoothDevice.ACTION_FOUND.equals(action)){
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    devices.add(device);
                    String s = "";
                    for(int a = 0; a < pairedDevices.size(); a++){
                        if(device.getName().equals(pairedDevices.get(a))){
                            //append 
                            s = "(Paired)";
                            break;
                        }
                    }

                    listAdapter.add(device.getName()+" "+s+" "+"\n"+device.getAddress());
                }

                else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
                }
                else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
                }
                else if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){
                    if(btAdapter.getState() == btAdapter.STATE_OFF){
                        turnOn();
                    }
                }
            }
        };

        registerReceiver(receiver, filter);
         filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        registerReceiver(receiver, filter);
         filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(receiver, filter);
         filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(receiver, filter);
    }


    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        unregisterReceiver(receiver);
    }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            // TODO Auto-generated method stub
            super.onActivityResult(requestCode, resultCode, data);
            if(resultCode == RESULT_CANCELED){
                Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue", Toast.LENGTH_SHORT).show();
                finish();
            }
        }






        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;
                Log.i(tag, "construct");
                // 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);
                } catch (IOException e) { 
                    Log.i(tag, "get socket failed");

                }
                mmSocket = tmp;
            }

            public void run() {
                // Cancel discovery because it will slow down the connection
                btAdapter.cancelDiscovery();
                Log.i(tag, "connect - run");
                try {
                    // Connect the device through the socket. This will block
                    // until it succeeds or throws an exception
                    mmSocket.connect();
                    Log.i(tag, "connect - succeeded");
                } catch (IOException connectException) {    Log.i(tag, "connect failed");
                    // 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)

                mHandler.obtainMessage(Main_Activity.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 {
            private final BluetoothSocket mmSocket;
            private final InputStream mmInStream;
            private final OutputStream mmOutStream;

            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(Main_Activity.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 {
                    mmOutStream.write(bytes);
                } catch (IOException e) { }
            }

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

XML布局:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
<TextView 
            android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="Paired Devices"
        android:id="@+id/tvPD"
    />

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="100dip"
        android:layout_above="@+id/Border"
        android:layout_below="@+id/tvPD" >

    </ListView>

    <Button
        android:id="@+id/bConnectNew"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tvResponse"
        android:layout_alignBottom="@+id/tvResponse"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="45dp"
        android:text="Send" />

    <TextView
        android:id="@+id/tvResponse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="188dp"
        android:layout_marginRight="26dp"
        android:text="Response displayed here" />

    <View
        android:id="@+id/Border"
        android:layout_width="wrap_content"
        android:layout_height="3dip"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_weight="10"
        android:background="@android:color/black" />

</RelativeLayout>

    enter code here

0 个答案:

没有答案