首页 > 系统 > Android > 正文

Android实现一对一蓝牙聊天APP

2019-10-22 18:10:14
字体:
来源:转载
供稿:网友

学习了,三天的Android 蓝牙开发,开始是一头雾水,看着别人讲的Google官方的demo感觉很容易,所有自己也尝试写一个很简单的聊天demo.可是想的很简单,自己做起来也花了,将近一天的时间才搞定这个基本的流程设计.下面是几点心得后面再贴代码 

1)写一个简单的demo也好,记得一定需要有总体的流程,才开始抠代码 
2)既然是demo毕竟就是新的知识,代码中间的log点一定/不能少,这是你快速调试的利器 
3)还是thinking in java 里面的那句话,思考什么是可变的,什么是不可变的,然后分开,这样来实现代码的封装,感觉很不错了.只是现在感觉还是很难想明白 
4)开始思考以面向对象的流程处理问题,需要怎么弄,也是封装代码的一种思想

蓝牙聊天的基本功能: 

1.实现一对一蓝牙连接 
2.实现一对一聊天

很简单的功能,思路看着也很清晰,可是深入去写,才知道,水还是深度的,java不熟的话. 
此处基本的如何打开蓝牙不在复述,请自行百度.

思路:

1)初始化,打开手机的蓝牙,开始蓝牙服务器线程,等待连接 
2)配对,获取某台手机的蓝牙address地址. 
3)开启连接线程连接手机蓝牙 
4)连接成功后,开启,蓝牙聊天的线程,进行聊天的通讯.

上面四步是主要思路,其中存在着几个细节的地方,就是在开发中某些逻辑问题,线程间的安全问题,也是需要好好处理的. 让我感受比较深的地方是,一对一聊天,相当于,首相每台机器都可能作为服务器在进行通讯,所以一开始开启了两个服务监听,一旦有一个接入进来,这里需要弄清楚哪个是接入对象,哪个是被接入对象, 没有作为服务端的,可以把服务端线程关闭掉。

下面贴点代码

/** * 客户端启动连接线程 * 通过蓝牙的mac地址获取连接 * @author Administrator * */ private class ConnectThread extends Thread { private BluetoothDevice mDevice; private BluetoothSocket btSocket = null; public ConnectThread(String address) {  // TODO Auto-generated constructor stub  mDevice = mBluetoothAdapter.getRemoteDevice(address); } @Override public void run() {  // TODO Auto-generated method stub  connect(mDevice); } private void connect(BluetoothDevice btDev) {  Method creMethod;  try {  creMethod = BluetoothDevice.class.getMethod("createBond");  creMethod.invoke(btDev);  } catch (Exception e) {  // TODO Auto-generated catch block  e.printStackTrace();  }  try {  btSocket = btDev.createRfcommSocketToServiceRecord(MYUUID);  System.out.println("========" + "start connect");  Log.d("BlueToothTestActivity", "开始连接...");  btSocket.connect();  mClientSocket = btSocket;  isConnected=true;  mHandler.sendEmptyMessage(SUCCESS_SERVICE_BEGIN_TALKING);  // 作为客户端 关闭 服务端 等待的链接  if (acceptThread != null) {   acceptThread.close();  }  startTalk();  } catch (IOException e) {  // TODO Auto-generated catch block  System.out.println("???????????????? close socket");  close();  System.out.println(e.toString());  e.printStackTrace();  } } private void close() {  if (btSocket != null) {  try {   btSocket.close();   mHandler.sendEmptyMessage(FAILED_SERVICE_SOCRCKET);  } catch (IOException e1) {   // TODO Auto-generated catch block   e1.printStackTrace();  }  } }}
/** * 服务端的设计 * 每个蓝牙的客户端先要开启服务端等待接入 * @author Administrator **/ private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; public AcceptThread() {  // Use a temporary object that is later assigned to mmServerSocket,  // because mmServerSocket is final  BluetoothServerSocket tmp = null;  try {  // MY_UUID is the app's UUID string, also used by the client  // code  tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("Fisrt", MYUUID);  } catch (IOException e) {  mHandler.sendEmptyMessage(FAILED_SERVICE_SOCRCKET);  }  mmServerSocket = tmp; } public void run() {  BluetoothSocket socket = null;  // Keep listening until exception occurs or a socket is returned  while (isRun) {  try {   socket = mmServerSocket.accept();   mHandler.sendEmptyMessage(SUCCESS_SERVICE_SOCRCKET);   Log.e("TAG", "========== server start ====");  } catch (IOException e) {   mHandler.sendEmptyMessage(FAILED_SERVICE_SOCRCKET);   close();  }  // If a connection was accepted  if (socket != null) {   // 服务端连接成功,启动聊天线程,通过 同一个 socket 防止多线程赋值出现空值的问题   isConnected=true;   mClientSocket = socket;   mTalkThread = new TalkThread();   mTalkThread.start();   // Do work to manage the connection (in a separate thread)   // 多线程操作小心不安全性   synchronized (BlueConnectService.this) {   //close();   }  }  } } public void close() {  isRun = false;  try {  mmServerSocket.close();  } catch (IOException e) {  // TODO Auto-generated catch block  e.printStackTrace();  } }}
/** *设计连接成功后的聊天线程 1.建立流,打通连接 2.发送和接收数据 3.显示数据 *需要注意的是聊天的时候,需要同一个socket建立连接才能获取对应的输入输出流 */ private class TalkThread extends Thread { private final BluetoothSocket talkSocket; private final InputStream mIs; private final OutputStream mOs; private boolean isRunning = true; public TalkThread() {  // TODO Auto-generated constructor stub  talkSocket = mClientSocket;  if (talkSocket == null) {  System.out.println("================= talkThread erro ");  // return;  }  InputStream is = null;  OutputStream os = null;  try {  is = talkSocket.getInputStream();  os = talkSocket.getOutputStream();  } catch (IOException e) {  // TODO Auto-generated catch block  try {   System.out.println("???????????????? close socket");   talkSocket.close();   CloseUtil.closeStream(is, os);  } catch (IOException e1) {   // TODO Auto-generated catch block   e1.printStackTrace();  }  e.printStackTrace();  }  mIs = is;  mOs = os; } @Override public void run() {  // TODO Auto-generated method stub  super.run();  byte[] buffer = new byte[1024];  int len;  while (isRunning) {  try {   len = mIs.read(buffer);   mHandler.obtainMessage(READ_MESSAGE, len, -1, buffer).sendToTarget();  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();   try {   isRunning = false;   isConnected=false;   System.out.println("???????????????? close socket");   talkSocket.close();   // 需要重启服务器   // 启动服务器   } catch (IOException e1) {   // TODO Auto-generated catch block   e1.printStackTrace();   }   CloseUtil.closeStream(mIs, mOs);  }  } } public void write(byte[] bytes) {  try {  mOs.write(bytes);  mHandler.obtainMessage(WRITE_MESSAGE, bytes.length, -1, bytes).sendToTarget();  } catch (IOException e) {  // TODO Auto-generated catch block  e.printStackTrace();  } }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表