您的位置:首页 > 移动开发 > Android开发

Android基于蓝牙的聊天demo

2016-03-02 10:04 519 查看
本文介绍了一个基于蓝牙的聊天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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  蓝牙 聊天 android socket