本文介绍了一个基于蓝牙的聊天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);}

更多相关文章

  1. Android常用名令集锦(图文并茂)(转:来自网络)
  2. 飞利浦推出 Android(安卓)设备用 Fidelio 系列音箱底座
  3. Android(安卓)物联网socket通信采坑
  4. Android获取内置、外置以及OTG等方式挂载的存储设备路径
  5. Android移动view动画问题 关于view的位置移动了,但view里面绑定的
  6. 本人初学android,希望大神帮忙指点学习路线,现在好迷茫
  7. 为Android、iOS设备搭建模拟丢包、慢速网络模拟环境
  8. 友盟2013年上半年数据报告:与开发者相关的各种干货数据
  9. Android(安卓)11 功能和 API : 面向企业的 Android(安卓)新功能

随机推荐

  1. 图片走廊
  2. android camera系统3A模式及其状态转换(二
  3. 【Android】如何寻找出某个Intent是否可
  4. ch027 Android(安卓)Json
  5. android ContentResolver
  6. Android计算器布局
  7. android ToggleButton
  8. android slidemenu
  9. android 画线
  10. amlogic 编译 android