Android基于蓝牙的聊天demo

来源:互联网 发布:windows ad域搭建 编辑:程序博客网 时间:2024/05/16 06:36

本文介绍了一个基于蓝牙的聊天demo:在服务端,通过打开蓝牙、设置可见状态、不断监听客户端的访问、建立连接、交换数据等步骤,实现服务端的蓝牙功能创建;在客户端,通过打开蓝牙、搜索蓝牙设备(服务端)、绑定蓝牙设备、建立连接、交换数据等步骤,实现客户端的蓝牙功能创建。有关上述蓝牙基础部分的内容,请参见我的博文《Android蓝牙开发介绍》。


模块构成及依赖关系


在软件设计之初,为了降低各功能之间的耦合,提高软件的复用性,提出了分层的概念:
demo分为3层,分别是UI层、业务逻辑层、网络层(蓝牙传输),每层包含的类如下所示:
这里写图片描述


其中UI层包含MainActivity、DeviceAdapter类;
业务逻辑层包含ChatControl、BlueToothControl类;
网络层包含ConnectedThread、AcceptThread、ConnectThread类。


各个类的依赖关系如下所示:
这里写图片描述

由图可知,模块之间是自顶至下的顺序依赖关系,这样做的好处是,当有某一个功能所对应的模块需要改变时,只需修改其内部逻辑即可,而向上提供的接口无需改变,这样也就无需修改上层的结构。


layout布局

首先是layout布局,初始时,默认显示聊天面板,隐藏蓝牙列表:

<!-- activity_main.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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity">    <!-- 蓝牙设备列表 -->    <ListView        android:id="@+id/device_list"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="gone"></ListView>    <!--聊天面板 -->    <RelativeLayout        android:id="@+id/chat_panel"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="visible">        <!-- 聊天按钮 -->        <Button            android:id="@+id/bt_send"            android:layout_width="100dp"            android:layout_height="50dp"            android:layout_alignParentBottom="true"            android:layout_alignParentRight="true"            android:text="@string/send" />        <!-- 聊天输入框 -->        <EditText            android:id="@+id/chat_edit"            android:layout_width="match_parent"            android:layout_height="50dp"            android:layout_alignParentBottom="true"            android:layout_toLeftOf="@+id/bt_send"            />        <!-- 聊天对话框 -->        <TextView            android:id="@+id/chat_content"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:layout_above="@+id/bt_send" />    </RelativeLayout></RelativeLayout>

UI层


UI层主要负责初始化并更新用户界面、设置广播接收器、展示蓝牙搜索列表、通知用户蓝牙状态等。下面是MainActivity的代码:

public class MainActivity extends Activity {    //startActivityForResult()的请求码    public static final int REQUEST_CODE = 0;    //搜索到的蓝牙设备列表    private List<BluetoothDevice> mDeviceList = new ArrayList<>();    //已绑定的蓝牙设备列表    private List<BluetoothDevice> mBondedDeviceList = new ArrayList<>();    //管理蓝牙操作的类    private BlueToothController mController = new BlueToothController();    private ListView mListView;    //自定义ListView的Adapter适配器    private DeviceAdapter mAdapter;    private Toast mToast;    //聊天面板    private View mChatPanel;    //发送按钮    private Button mSendBt;    //输入框    private EditText mInputBox;    //显示聊天内容区域    private TextView mChatContent;    //输入内容    private StringBuilder mChatText = new StringBuilder();    //Handler,用于线程之间传递信息以更新UI    private Handler mUIHandler = new MyHandler();    //广播接收器,用于收听系统发出的广播以触发操作    private BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            //接收广播附带的intent中的action            String action = intent.getAction();            //接收到开始搜索设备的action            if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {//在标题栏显示转动的progressBar,表示开始搜索              setProgressBarIndeterminateVisibility(true);                //初始化数据列表                mDeviceList.clear();                //刷新ListView                mAdapter.notifyDataSetChanged();            }             //接收到搜索完毕的action            else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {            //关闭标题栏转动的progressBar,表示搜索结束                setProgressBarIndeterminateVisibility(false);            }             //接收到找到设备的action            else if (BluetoothDevice.ACTION_FOUND.equals(action)) {                //从extra数据中获得搜索到的蓝牙设备                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                //找到一个,添加一个                mDeviceList.add(device);                //刷新ListView列表                mAdapter.notifyDataSetChanged();            }             //扫描模式改变,即设备在可见性之间切换            else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {                //可见性的模式                int scanMode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, 0);                //本设备对其他设备可见                if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {                    setProgressBarIndeterminateVisibility(true);                }                 //本设备对其他设备隐藏                else {                    setProgressBarIndeterminateVisibility(false);                }            }             //绑定状态改变            else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {                //获得绑定设备                BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                //无绑定                if (remoteDevice == null) {                    showToast("no device");                    return;                }                int status = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 0);                //已绑定                if (status == BluetoothDevice.BOND_BONDED) {                    showToast("Bonded " + remoteDevice.getName());                }                 //正在绑定                else if (status == BluetoothDevice.BOND_BONDING) {                    showToast("Bonding " + remoteDevice.getName());                }                 //未绑定                else if (status == BluetoothDevice.BOND_NONE) {                    showToast("Not bond " + remoteDevice.getName());                }            }        }    };    //点击搜索到的设备,并点击某一项并与之绑定时回调的接口对象    private AdapterView.OnItemClickListener bindDeviceClick = new AdapterView.OnItemClickListener() {        //绑定设备需要设备版本不低于Android 4.4 (API 19)        @TargetApi(Build.VERSION_CODES.KITKAT)        @Override        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {            //从列表中获取该设备            BluetoothDevice device = mDeviceList.get(i);            //绑定设备需要设备版本不低于Android 4.4 (API 19),低于该版本的设备无法绑定蓝牙            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {                //绑定设备                device.createBond();            }        }    };    //点击已绑定设备列表中的某一项时回调的接口对象    private AdapterView.OnItemClickListener bindedDeviceClick = new AdapterView.OnItemClickListener() {        @Override        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {            //获得绑定的设备            BluetoothDevice device = mBondedDeviceList.get(i);//与选中的设备聊天            ChatController.getInstance().startChatWith(device, mController.getAdapter(), mUIHandler);        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //初始化ActionBar        initActionBar();        //绑定界面        setContentView(R.layout.activity_main);        //初始化UI控件        initUI();        //注册广播接收器以接收系统广播        registerBluetoothReceiver();        //打开蓝牙        mController.turnOnBlueTooth(this, REQUEST_CODE);    }    private void registerBluetoothReceiver() {        IntentFilter filter = new IntentFilter();        //开始查找        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);        //结束查找        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);        //查找到设备        filter.addAction(BluetoothDevice.ACTION_FOUND);        //设备扫描模式改变(可见性改变)        filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);        //绑定状态        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);        //动态注册广播接收器        registerReceiver(mReceiver, filter);    }    private void initUI() {        mListView = (ListView) findViewById(R.id.device_list);        mAdapter = new DeviceAdapter(mDeviceList, this);        mListView.setAdapter(mAdapter);        mListView.setOnItemClickListener(bindDeviceClick);        mChatPanel = findViewById(R.id.chat_panel);        mSendBt = (Button) findViewById(R.id.bt_send);        mSendBt.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                //点击发送按钮,获得输入框中的输入框                String ext = mInputBox.getText().toString();                             //发送信息             ChatController.getInstance().sendMessage(ext);                //保存会话内容                mChatText.append(ext).append("\n");                //将输入内容显示在对话区域                mChatContent.setText(mChatText.toString());                //清空输入框                mInputBox.setText("");            }        });        mInputBox = (EditText) findViewById(R.id.chat_edit);        mChatContent = (TextView) findViewById(R.id.chat_content);    }    @Override    protected void onDestroy() {        super.onDestroy();        ChatController.getInstance().stopChat();        unregisterReceiver(mReceiver);    }    public void enterChatMode() {        //进入聊天界面,蓝牙列表隐藏        mListView.setVisibility(View.GONE);        //聊天面板出现        mChatPanel.setVisibility(View.VISIBLE);    }    public void exitChatMode() {        //退出聊天界面,显示蓝牙列表        mListView.setVisibility(View.VISIBLE);        //隐藏聊天面板        mChatPanel.setVisibility(View.GONE);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (requestCode == REQUEST_CODE) {            //若用户不打算打开蓝牙功能,则activity直接被finish            if (resultCode != RESULT_OK) {                finish();            }        }    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.menu_main, menu);        return true;    }    private void showToast(String text) {        if (mToast == null) {            mToast = Toast.makeText(this, text, Toast.LENGTH_LONG);        } else {            mToast.setText(text);        }        mToast.show();    }    @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();        //noinspection SimplifiableIfStatement        if (id == R.id.enable_visiblity) {            mController.enableVisibly(this);        } else if (id == R.id.find_device) {            //查找设备            mAdapter.refresh(mDeviceList);            mController.findDevice();            mListView.setOnItemClickListener(bindDeviceClick);        } else if (id == R.id.bonded_device) {            //查看已绑定设备            mBondedDeviceList = mController.getBondedDeviceList();            mAdapter.refresh(mBondedDeviceList);            mListView.setOnItemClickListener(bindedDeviceClick);        } else if (id == R.id.listening) {            //等待对方设备进入聊天                        ChatController.getInstance().waitingForFriends(mController.getAdapter(), mUIHandler);        } else if (id == R.id.stop_listening) {            ChatController.getInstance().stopChat();            exitChatMode();        } else if (id == R.id.disconnect) {            exitChatMode();        }        return super.onOptionsItemSelected(item);    }    private void initActionBar() {        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);        getActionBar().setDisplayUseLogoEnabled(false);        setProgressBarIndeterminate(true);        try {            ViewConfiguration config = ViewConfiguration.get(this);            Field menuKeyField = ViewConfiguration.class                    .getDeclaredField("sHasPermanentMenuKey");            if (menuKeyField != null) {                menuKeyField.setAccessible(true);                menuKeyField.setBoolean(config, false);            }        } catch (Exception e) {            e.printStackTrace();        }    }    //处理从子线层发给UI线程的消息以更新UI    private class MyHandler extends Handler {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case Constant.MSG_START_LISTENING:                    setProgressBarIndeterminateVisibility(true);                    break;                case Constant.MSG_FINISH_LISTENING:                    setProgressBarIndeterminateVisibility(false);                    exitChatMode();                    break;                case Constant.MSG_GOT_DATA:                    byte[] data = (byte[]) msg.obj;                    mChatText.append(ChatController.getInstance().decodeMessage(data)).append("\n");                    mChatContent.setText(mChatText.toString());                    break;                case Constant.MSG_ERROR:                    exitChatMode();                    showToast("error: " + String.valueOf(msg.obj));                    break;                case Constant.MSG_CONNECTED_TO_SERVER:                    enterChatMode();                    showToast("Connected to Server");                    break;                case Constant.MSG_GOT_A_CLINET:                    enterChatMode();                    showToast("Got a Client");                    break;            }        }    }}

以下是自定义的蓝牙列表项布局及内容

//DeviceAdapter.java//蓝牙列表的布局public class DeviceAdapter extends BaseAdapter {    private List<BluetoothDevice> mData;    private Context mContext;    public DeviceAdapter(List<BluetoothDevice> data, Context context) {        mData = data;        mContext = context.getApplicationContext();    }    @Override    public int getCount() {        return mData.size();    }    @Override    public Object getItem(int i) {        return mData.get(i);    }    @Override    public long getItemId(int i) {        return i;    }    @Override    public View getView(int i, View view, ViewGroup viewGroup) {        View itemView = view;        //复用View,优化性能        if( itemView == null) {            itemView = LayoutInflater.from(mContext).inflate(android.R.layout.simple_list_item_2,viewGroup,false);        }        TextView line1 = (TextView) itemView.findViewById(android.R.id.text1);        TextView line2 = (TextView) itemView.findViewById(android.R.id.text2);        //获取对应的蓝牙设备        BluetoothDevice device = (BluetoothDevice) getItem(i);        //显示名称        line1.setText(device.getName());        //显示地址        line2.setText(device.getAddress());        return itemView;    }    public void refresh(List<BluetoothDevice> data) {        mData = data;        notifyDataSetChanged();    }}

业务逻辑层


业务逻辑层主要负责蓝牙功能的处理(如打开或关闭蓝牙、设置蓝牙设备的可见性、搜索蓝牙设备等)和聊天逻辑处理:


//BlueToothController.java//处理蓝牙逻辑public class BlueToothController {    private BluetoothAdapter mAapter;    public BlueToothController() {        //创建蓝牙对象BluetoothAdapter         mAapter = BluetoothAdapter.getDefaultAdapter();    }    public BluetoothAdapter getAdapter() {        return mAapter;    }    /**     * 打开蓝牙     * @param activity     * @param requestCode     */    public void turnOnBlueTooth(Activity activity, int requestCode) {        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);        activity.startActivityForResult(intent, requestCode);        //不推荐使用BluetoothAdapter.enable()方法打开蓝牙,该方法一般有系统调用//        mAdapter.enable();    }    /**     * 打开蓝牙可见性,系统会发出广播     * @param context     */    public void enableVisibly(Context context) {        Intent discoverableIntent = new                Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);        discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);        context.startActivity(discoverableIntent);    }    /**     * 查找设备,系统会发出广播     */    public void findDevice() {        assert (mAapter != null);        mAapter.startDiscovery();    }    /**     * 获取绑定设备     * @return     */    public List<BluetoothDevice> getBondedDeviceList() {        return new ArrayList<>(mAapter.getBondedDevices());    }}

//ChatController.java//聊天业务逻辑public class ChatController {    private ConnectThread mConnectThread;    private AcceptThread mAcceptThread;    /**     * 网络协议的处理函数     */    private  class ChatProtocol implements ProtocolHandler<String> {        private static final String CHARSET_NAME = "utf-8";        //封包,以发送至网络传递        @Override        public byte[] encodePackage(String data) {            if( data == null) {                return new byte[0];            }            else {                try {                    return data.getBytes(CHARSET_NAME);                } catch (UnsupportedEncodingException e) {                    e.printStackTrace();                    return new byte[0];                }            }        }        //解包,接收网络传递过来的数据        @Override        public String decodePackage(byte[] netData) {            if( netData == null) {                return "";            }            try {                return new String(netData, CHARSET_NAME);            } catch (UnsupportedEncodingException e) {                e.printStackTrace();                return "";            }        }    }    /**     * 协议处理     */    private ChatProtocol mProtocol = new ChatProtocol();    /**     * 与服务器连接进行聊天     * @param device     * @param adapter     * @param handler     */    public void startChatWith(BluetoothDevice device, BluetoothAdapter adapter, Handler handler) {        mConnectThread = new ConnectThread(device,adapter,handler);        mConnectThread.start();    }    /**     * 等待客户端来连接     * @param adapter     * @param handler     */    public void waitingForFriends(BluetoothAdapter adapter, Handler handler) {        mAcceptThread = new AcceptThread(adapter,handler);        mAcceptThread.start();    }    /**     * 发出消息     * @param msg     */    public void sendMessage(String msg) {        byte[] data = mProtocol.encodePackage(msg);        if(mConnectThread != null) {            mConnectThread.sendData(data);        }        else if( mAcceptThread != null) {            mAcceptThread.sendData(data);        }    }    /**     * 网络数据解码     * @param data     * @return     */    public String decodeMessage(byte[] data) {        return  mProtocol.decodePackage(data);    }    /**     * 停止聊天     */    public void stopChat() {        if(mConnectThread != null) {            mConnectThread.cancel();        }        else if( mAcceptThread != null) {            mAcceptThread.cancel();        }    }    /**     * 单例方式构造类对象     */    private static class ChatControlHolder {        private static ChatController mInstance = new ChatController();    }    public static ChatController getInstance() {        return ChatControlHolder.mInstance;    }}

网络层


网络层主要负责消息的传递。

//AcceptThread.java//当设备作为服务端时,不断监听来自其他设备的连接请求public class AcceptThread extends Thread {    private static final String NAME = "BlueToothClass";    private static final UUID MY_UUID = UUID.fromString(Constant.CONNECTTION_UUID);    private final BluetoothServerSocket mmServerSocket;    private final BluetoothAdapter mBluetoothAdapter;    private final Handler mHandler;    private ConnectedThread mConnectedThread;    public AcceptThread(BluetoothAdapter adapter, Handler handler) {        // Use a temporary object that is later assigned to mmServerSocket,        // because mmServerSocket is final        mBluetoothAdapter = adapter;        mHandler = handler;        BluetoothServerSocket tmp = null;        try {            // MY_UUID is the app's UUID string, also used by the client code            tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);        } catch (IOException e) { }        mmServerSocket = tmp;    }    public void run() {        BluetoothSocket socket = null;        // Keep listening until exception occurs or a socket is returned        while (true) {            try {                mHandler.sendEmptyMessage(Constant.MSG_START_LISTENING);                socket = mmServerSocket.accept();            } catch (IOException e) {                mHandler.sendMessage(mHandler.obtainMessage(Constant.MSG_ERROR, e));                break;            }            // If a connection was accepted            if (socket != null) {                // Do work to manage the connection (in a separate thread)                manageConnectedSocket(socket);                try {                    mmServerSocket.close();                    mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);                } catch (IOException e) {                    e.printStackTrace();                }                break;            }        }    }    private void manageConnectedSocket(BluetoothSocket socket) {        //只支持同时处理一个连接        if( mConnectedThread != null) {            mConnectedThread.cancel();        }        mHandler.sendEmptyMessage(Constant.MSG_GOT_A_CLINET);        mConnectedThread = new ConnectedThread(socket, mHandler);        mConnectedThread.start();    }    /** Will cancel the listening socket, and cause the thread to finish */    public void cancel() {        try {            mmServerSocket.close();            mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);        } catch (IOException e) { }    }    public void sendData(byte[] data) {        if( mConnectedThread!=null){            mConnectedThread.write(data);        }    }}

//ConnectThread.java//当设备作为客户端时,不断搜索可见设备public class ConnectThread extends Thread {    private static final UUID MY_UUID = UUID.fromString(Constant.CONNECTTION_UUID);    private final BluetoothSocket mmSocket;    private final BluetoothDevice mmDevice;    private BluetoothAdapter mBluetoothAdapter;    private final Handler mHandler;    private ConnectedThread mConnectedThread;    public ConnectThread(BluetoothDevice device, BluetoothAdapter adapter, Handler handler) {        // Use a temporary object that is later assigned to mmSocket,        // because mmSocket is final        BluetoothSocket tmp = null;        mmDevice = device;        mBluetoothAdapter = adapter;        mHandler = handler;        // 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) { }        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 (Exception connectException) {            mHandler.sendMessage(mHandler.obtainMessage(Constant.MSG_ERROR, 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);    }    private void manageConnectedSocket(BluetoothSocket mmSocket) {        mHandler.sendEmptyMessage(Constant.MSG_CONNECTED_TO_SERVER);        mConnectedThread = new ConnectedThread(mmSocket, mHandler);        mConnectedThread.start();    }    /** Will cancel an in-progress connection, and close the socket */    public void cancel() {        try {            mmSocket.close();        } catch (IOException e) { }    }    public void sendData(byte[] data) {        if( mConnectedThread!=null){            mConnectedThread.write(data);        }    }}

//ConnectedThread.java//用于支持蓝牙设备之间数据传输的类,每当建立一组新的聊天,就会通过该类创建一个新的线程public class ConnectedThread extends Thread {    private final BluetoothSocket mmSocket;    private final InputStream mmInStream;    private final OutputStream mmOutStream;    private final Handler mHandler;    public ConnectedThread(BluetoothSocket socket, Handler handler) {        mmSocket = socket;        InputStream tmpIn = null;        OutputStream tmpOut = null;        mHandler = handler;        // 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 = new byte[1024];  // 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                bytes = mmInStream.read(buffer);                // Send the obtained bytes to the UI activity                if( bytes >0) {                    Message message = mHandler.obtainMessage(Constant.MSG_GOT_DATA, buffer);                    mHandler.sendMessage(message);                }                Log.d("GOTMSG", "message size" + bytes);            } catch (IOException e) {                mHandler.sendMessage(mHandler.obtainMessage(Constant.MSG_ERROR, 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) { }    }}

存储常量的类:


//Constant.java//蓝牙设备相互匹配必须使用唯一的字符串,否则无法连接public class Constant {    public static final String CONNECTTION_UUID = "00001101-0000-1000-8000-00805F9B34FB";    /**     * 开始监听     */    public static final int MSG_START_LISTENING = 1;    /**     * 结束监听     */    public static final int MSG_FINISH_LISTENING = 2;    /**     * 有客户端连接     */    public static final int MSG_GOT_A_CLINET = 3;    /**     * 连接到服务器     */    public static final int MSG_CONNECTED_TO_SERVER = 4;    /**     * 获取到数据     */    public static final int MSG_GOT_DATA = 5;    /**     * 出错     */    public static final int MSG_ERROR = -1;}

** * 处理网络协议,对数据进行封包或解包 * */public interface ProtocolHandler<T> {    public byte[] encodePackage(T data);    public T decodePackage(byte[] netData);}

0 0
原创粉丝点击