学习了,三天的Android 蓝牙开发,开始是一头雾水,看着别人讲的Google官方的demo感觉很容易,所有自己也尝试写一个很简单的聊天demo.可是想的很简单,自己做起来也花了,将近一天的时间才搞定这个基本的流程设计.下面是几点心得后面再贴代码
1)写一个简单的demo也好,记得一定需要有总体的流程,才开始抠代码
2)既然是demo毕竟就是新的知识,代码中间的log点一定\不能少,这是你快速调试的利器
3)还是thinking in java 里面的那句话,思考什么是可变的,什么是不可变的,然后分开,这样来实现代码的封装,感觉很不错了.只是现在感觉还是很难想明白
4)开始思考以面向对象的流程处理问题,需要怎么弄,也是封装代码的一种思想
蓝牙聊天的基本功能:
1.实现一对一蓝牙连接
2.实现一对一聊天
很简单的功能,思路看着也很清晰,可是深入去写,才知道,水还是深度的,java不熟的话.
此处基本的如何打开蓝牙不在复述,请自行百度.
思路:
1)初始化,打开手机的蓝牙,开始蓝牙服务器线程,等待连接
2)配对,获取某台手机的蓝牙address地址.
3)开启连接线程连接手机蓝牙
4)连接成功后,开启,蓝牙聊天的线程,进行聊天的通讯.
上面四步是主要思路,其中存在着几个细节的地方,就是在开发中某些逻辑问题,线程间的安全问题,也是需要好好处理的. 让我感受比较深的地方是,一对一聊天,相当于,首相每台机器都可能作为服务器在进行通讯,所以一开始开启了两个服务监听,一旦有一个接入进来,这里需要弄清楚哪个是接入对象,哪个是被接入对象, 没有作为服务端的,可以把服务端线程关闭掉。
下面贴点代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/**
* 客户端启动连接线程
* 通过蓝牙的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();
}
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/**
* 服务端的设计
* 每个蓝牙的客户端先要开启服务端等待接入
* @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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
/**
*设计连接成功后的聊天线程 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();
}
}
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/yangxlAndroid/article/details/51614112