android手机之间蓝牙通信的实现
从开始学习到实现用了差不多一个星期的时间,从网上找了很多资料,基本出处都是一个,将大牛们的资料整合,存在很多问题,经过自己几天反复修改和调试,终于搞通,自己Make一下;也供刚开始学习这部分的同学们借鉴一下,如果大家有什么好的建议和意见也可以反馈给我。
我仅在两个android手机上进行了测试,大家可以借助串口调试助手,测试蓝牙芯片和android之间的通信。
测试如图:
实现的关键代码:两个Activity,一个对话,一个搜索设备
1 package com.houwen.btchatactivity;
2
3
4
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import android.app.Activity;
9 import android.content.Intent;
10 import android.os.Bundle;
11 import android.os.Handler;
12 import android.os.Message;
13 import android.text.TextUtils;
14 import android.view.Menu;
15 import android.view.View;
16 import android.view.View.OnClickListener;
17 import android.widget.ArrayAdapter;
18 import android.widget.Button;
19 import android.widget.EditText;
20 import android.widget.ListView;
21 import android.widget.RadioGroup;
22 import android.widget.RadioGroup.OnCheckedChangeListener;
23 import android.widget.Toast;
24
25
26 public class BTChatActivity extends Activity {
27
28 private ListView mListView;
29 private Button sendButton;
30 private Button disconnectButton;
31 private EditText editMsgView;
32 private ArrayAdapter<String> mAdapter;
33 private List<String> msgList=new ArrayList<String>();
34 private BTClient client;
35 private BTServer server;
36 private Button finddevice;
37
38 @Override
39 protected void onCreate(Bundle savedInstanceState) {
40 super.onCreate(savedInstanceState);
41 setContentView(R.layout.bt_chat);
42 initView();
43 }
44
45
46
47 private Handler detectedHandler = new Handler(){
48 public void handleMessage(android.os.Message msg) {
49 msgList.add(msg.obj.toString());
50 mAdapter.notifyDataSetChanged();
51 mListView.setSelection(msgList.size() - 1);
52 };
53 };
54
55 private void initView() {
56
57 mAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, msgList);
58 mListView = (ListView) findViewById(R.id.list);
59 mListView.setAdapter(mAdapter);
60 mListView.setFastScrollEnabled(true);
61 editMsgView= (EditText)findViewById(R.id.MessageText);
62 editMsgView.clearFocus();
63
64 RadioGroup group = (RadioGroup)this.findViewById(R.id.radioGroup);
65 group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
66
67 @Override
68 public void onCheckedChanged(RadioGroup group, int checkedId) {
69 switch(checkedId){
70 case R.id.radioNone:
71 BluetoothMsg.serviceOrCilent = BluetoothMsg.ServerOrCilent.NONE;
72 if(null!=client){
73 client.closeBTClient();
74 client=null;
75 }
76 if(null!=server){
77 server.closeBTServer();
78 server=null;
79 }
80 break;
81 case R.id.radioClient:
82 BluetoothMsg.serviceOrCilent = BluetoothMsg.ServerOrCilent.CILENT;
83 Intent it=new Intent(getApplicationContext(),BTDeviceActivity.class);
84 startActivityForResult(it, 100);
85 break;
86 case R.id.radioServer:
87 BluetoothMsg.serviceOrCilent = BluetoothMsg.ServerOrCilent.SERVICE;
88 initConnecter();
89 break;
90 }
91 }
92 });
93 finddevice=(Button)findViewById(R.id.finddevice);
94 finddevice.setOnClickListener(new OnClickListener()
95 {
96 @Override
97 public void onClick(View arg0)
98 {
99 Intent intent=new Intent(BTChatActivity.this,BTDeviceActivity.class);
100 startActivity(intent);
101 }
102 });
103 sendButton= (Button)findViewById(R.id.btn_msg_send);
104 sendButton.setOnClickListener(new OnClickListener() {
105 @Override
106 public void onClick(View arg0) {
107
108 String msgText =editMsgView.getText().toString();
109 if (msgText.length()>0) {
110 if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT){
111 if(null==client)
112 return;
113 if(client.sendmsg(msgText)){
114 Message msg = new Message();
115 msg.obj = "send: "+msgText;
116 msg.what = 1;
117 detectedHandler.sendMessage(msg);
118 }else{
119 Message msg = new Message();
120 msg.obj = "send fail!! ";
121 msg.what = 1;
122 detectedHandler.sendMessage(msg);
123 }
124 }
125 else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE) {
126 if(null==server)
127 return;
128 if(server.sendmsg(msgText)){
129 Message msg = new Message();
130 msg.obj = "send: "+msgText;
131 msg.what = 1;
132 detectedHandler.sendMessage(msg);
133 }else{
134 Message msg = new Message();
135 msg.obj = "send fail!! ";
136 msg.what = 1;
137 detectedHandler.sendMessage(msg);
138 }
139 }
140 editMsgView.setText("");
141 }else{
142 Toast.makeText(getApplicationContext(), "发送内容不能为空!", Toast.LENGTH_SHORT).show();
143 }
144 }
145 });
146 disconnectButton= (Button)findViewById(R.id.btn_disconnect);
147 disconnectButton.setOnClickListener(new OnClickListener() {
148 @Override
149 public void onClick(View arg0) {
150 if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT){
151 if(null==client)
152 return;
153 client.closeBTClient();
154 }
155 else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE) {
156 if(null==server)
157 return;
158 server.closeBTServer();
159 }
160 BluetoothMsg.isOpen = false;
161 BluetoothMsg.serviceOrCilent=BluetoothMsg.ServerOrCilent.NONE;
162 Toast.makeText(getApplicationContext(), "已断开连接!", Toast.LENGTH_SHORT).show();
163 }
164 });
165 }
166 @Override
167 protected void onResume() {
168 super.onResume();
169
170 if (BluetoothMsg.isOpen) {
171 Toast.makeText(getApplicationContext(), "连接已经打开,可以通信。如果要再建立连接,请先断开!",
172 Toast.LENGTH_SHORT).show();
173 }
174 }
175 @Override
176 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
177 super.onActivityResult(requestCode, resultCode, data);
178 if(requestCode==100){
179 //从设备列表返回
180 initConnecter();
181 }
182 }
183 private void initConnecter(){
184 if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT) {
185 String address = BluetoothMsg.BlueToothAddress;
186 if (!TextUtils.isEmpty(address)) {
187 if(null==client)
188 client=new BTClient(BTManage.getInstance().getBtAdapter(), detectedHandler);
189 client.connectBTServer(address);
190 BluetoothMsg.isOpen = true;
191 } else {
192 Toast.makeText(getApplicationContext(), "address is empty please choose server address !",
193 Toast.LENGTH_SHORT).show();
194 }
195 } else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE) {
196 if(null==server)
197 server=new BTServer(BTManage.getInstance().getBtAdapter(), detectedHandler);
198 server.startBTServer();
199 BluetoothMsg.isOpen = true;
200 }
201 }
202 @Override
203 public boolean onCreateOptionsMenu(Menu menu) {
204 // Inflate the menu; this adds items to the action bar if it is present.
205 getMenuInflater().inflate(R.menu.btchat, menu);
206 return true;
207 }
208
209 }
BTChatActivity.java
1 package com.houwen.btchatactivity;
2 import android.app.Activity;
3 import android.app.AlertDialog;
4 import android.content.DialogInterface;
5 import android.os.Bundle;
6 import android.view.View;
7 import android.widget.AdapterView;
8 import android.widget.AdapterView.OnItemClickListener;
9 import android.widget.Button;
10 import android.widget.ListView;
11 public class BTDeviceActivity extends Activity implements OnItemClickListener
12 ,View.OnClickListener ,StatusBlueTooth{
13
14 // private List<BTItem> mListDeviceBT=new ArrayList<BTItem>();
15 private ListView deviceListview;
16 private Button btserch;
17 private BTDeviceAdapter adapter;
18 private boolean hasregister=false;
19
20 @Override
21 protected void onCreate(Bundle savedInstanceState) {
22 super.onCreate(savedInstanceState);
23 setContentView(R.layout.finddevice);
24
25 setView();
26
27 BTManage.getInstance().setBlueListner(this);
28 }
29
30 private void setView(){
31 deviceListview=(ListView)findViewById(R.id.devicelist);
32 deviceListview.setOnItemClickListener(this);
33 adapter=new BTDeviceAdapter(getApplicationContext());
34 deviceListview.setAdapter(adapter);
35 deviceListview.setOnItemClickListener(this);
36 btserch=(Button)findViewById(R.id.start_seach);
37 btserch.setOnClickListener(this);
38 }
39
40 @Override
41 protected void onStart() {
42 super.onStart();
43 //注册蓝牙接收广播
44 if(!hasregister){
45 hasregister=true;
46 BTManage.getInstance().registerBluetoothReceiver(getApplicationContext());
47 }
48 }
49
50 @Override
51 protected void onResume() {
52 // TODO Auto-generated method stub
53 super.onResume();
54 }
55
56 @Override
57 protected void onPause() {
58 // TODO Auto-generated method stub
59 super.onPause();
60 }
61
62 @Override
63 protected void onStop() {
64 super.onStop();
65 if(hasregister){
66 hasregister=false;
67 BTManage.getInstance().unregisterBluetooth(getApplicationContext());
68 }
69 }
70
71 @Override
72 protected void onDestroy() {
73 super.onDestroy();
74
75 }
76
77 @Override
78 public void onItemClick(AdapterView<?> parent, View view, int position,
79 long id) {
80
81 final BTItem item=(BTItem)adapter.getItem(position);
82
83
84 AlertDialog.Builder dialog = new AlertDialog.Builder(this);// 定义一个弹出框对象
85 dialog.setTitle("Confirmed connecting device");
86 dialog.setMessage(item.getBuletoothName());
87 dialog.setPositiveButton("connect",
88 new DialogInterface.OnClickListener() {
89 @Override
90 public void onClick(DialogInterface dialog, int which) {
91 // btserch.setText("repeat search");
92 BTManage.getInstance().cancelScanDevice();
93 BluetoothMsg.BlueToothAddress=item.getBluetoothAddress();
94
95 if(BluetoothMsg.lastblueToothAddress!=BluetoothMsg.BlueToothAddress){
96 BluetoothMsg.lastblueToothAddress=BluetoothMsg.BlueToothAddress;
97 }
98 setResult(100);
99 finish();
100 }
101 });
102 dialog.setNegativeButton("cancel",
103 new DialogInterface.OnClickListener() {
104 @Override
105 public void onClick(DialogInterface dialog, int which) {
106 BluetoothMsg.BlueToothAddress = null;
107 }
108 });
109 dialog.show();
110 }
111
112 @Override
113 public void onClick(View v) {
114 BTManage.getInstance().openBluetooth(this);
115
116 if(BTManage.getInstance().isDiscovering()){
117 BTManage.getInstance().cancelScanDevice();
118 btserch.setText("start search");
119 }else{
120 BTManage.getInstance().scanDevice();
121 btserch.setText("stop search");
122 }
123 }
124
125 @Override
126 public void BTDeviceSearchStatus(int resultCode) {
127 switch(resultCode){
128 case StatusBlueTooth.SEARCH_START:
129 adapter.clearData();
130 adapter.addDataModel(BTManage.getInstance().getPairBluetoothItem());
131 break;
132 case StatusBlueTooth.SEARCH_END:
133 break;
134 }
135 }
136
137 @Override
138 public void BTSearchFindItem(BTItem item) {
139 adapter.addDataModel(item);
140 }
141
142 @Override
143 public void BTConnectStatus(int result) {
144
145 }
146
147 }
BTDeviceActivity.java
两个Acivity中用到的方法主要有:
1 package com.houwen.btchatactivity;
2
3
4 import java.io.BufferedInputStream;
5 import java.io.BufferedOutputStream;
6 import java.io.EOFException;
7 import java.io.IOException;
8 import java.util.UUID;
9
10 import android.bluetooth.BluetoothAdapter;
11 import android.bluetooth.BluetoothDevice;
12 import android.bluetooth.BluetoothSocket;
13 import android.os.Handler;
14 import android.os.Message;
15 import android.util.Log;
16
17
18 public class BTClient {
19
20 final String Tag=getClass().getSimpleName();
21 private BluetoothSocket btsocket = null;
22 private BluetoothDevice btdevice = null;
23 private BufferedInputStream bis=null;
24 private BufferedOutputStream bos=null;
25 private BluetoothAdapter mBtAdapter =null;
26
27 private Handler detectedHandler=null;
28
29 public BTClient(BluetoothAdapter mBtAdapter,Handler detectedHandler){
30 this.mBtAdapter=mBtAdapter;
31 this.detectedHandler=detectedHandler;
32 }
33
34 public void connectBTServer(String address){
35 //check address is correct
36 if(BluetoothAdapter.checkBluetoothAddress(address)){
37 btdevice = mBtAdapter.getRemoteDevice(address);
38 ThreadPool.getInstance().excuteTask(new Runnable() {
39 public void run() {
40 try {
41 btsocket = btdevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
42
43 Message msg2 = new Message();
44 msg2.obj = "请稍候,正在连接服务器:"+BluetoothMsg.BlueToothAddress;
45 msg2.what = 0;
46 detectedHandler.sendMessage(msg2);
47
48 btsocket.connect();
49 Message msg = new Message();
50 msg.obj = "已经连接上服务端!可以发送信息。";
51 msg.what = 0;
52 detectedHandler.sendMessage(msg);
53 receiverMessageTask();
54 } catch (IOException e) {
55 e.printStackTrace();
56 Log.e(Tag, e.getMessage());
57
58 Message msg = new Message();
59 msg.obj = "连接服务端异常!请检查服务器是否正常,断开连接重新试一试。";
60 msg.what = 0;
61 detectedHandler.sendMessage(msg);
62 }
63
64 }
65 });
66 }
67 }
68
69 private void receiverMessageTask(){
70 ThreadPool.getInstance().excuteTask(new Runnable() {
71 public void run() {
72 byte[] buffer = new byte[2048];
73 int totalRead;
74 /*InputStream input = null;
75 OutputStream output=null;*/
76 try {
77 bis=new BufferedInputStream(btsocket.getInputStream());
78 bos=new BufferedOutputStream(btsocket.getOutputStream());
79 } catch (IOException e) {
80 e.printStackTrace();
81 }
82
83 try {
84 // ByteArrayOutputStream arrayOutput=null;
85 while((totalRead = bis.read(buffer)) > 0 ){
86 // arrayOutput=new ByteArrayOutputStream();
87 String txt = new String(buffer, 0, totalRead, "UTF-8");
88 Message msg = new Message();
89 msg.obj = "Receiver: "+txt;
90 msg.what = 1;
91 detectedHandler.sendMessage(msg);
92 }
93 } catch(EOFException e){
94 Message msg = new Message();
95 msg.obj = "server has close!";
96 msg.what = 1;
97 detectedHandler.sendMessage(msg);
98 }catch (IOException e) {
99 e.printStackTrace();
100 Message msg = new Message();
101 msg.obj = "receiver message error! make sure server is ok,and try again connect!";
102 msg.what = 1;
103 detectedHandler.sendMessage(msg);
104 }
105 }
106 });
107 }
108
109 public boolean sendmsg(String msg){
110 boolean result=false;
111 if(null==btsocket||bos==null)
112 return false;
113 try {
114 bos.write(msg.getBytes());
115 bos.flush();
116 result=true;
117 } catch (IOException e) {
118 e.printStackTrace();
119 }
120 return result;
121 }
122
123 public void closeBTClient(){
124 try{
125 if(bis!=null)
126 bis.close();
127 if(bos!=null)
128 bos.close();
129 if(btsocket!=null)
130 btsocket.close();
131 }catch(IOException e){
132 e.printStackTrace();
133 }
134 }
135
136 }
BTClient.java
1 package com.houwen.btchatactivity;
2
3
4 public class BTItem {
5
6 private String buletoothName=null;
7 private String bluetoothAddress=null;
8 private int bluetoothType=-1;
9
10 public String getBuletoothName() {
11 return buletoothName;
12 }
13 public void setBuletoothName(String buletoothName) {
14 this.buletoothName = buletoothName;
15 }
16 public String getBluetoothAddress() {
17 return bluetoothAddress;
18 }
19 public void setBluetoothAddress(String bluetoothAddress) {
20 this.bluetoothAddress = bluetoothAddress;
21 }
22 public int getBluetoothType() {
23 return bluetoothType;
24 }
25 public void setBluetoothType(int bluetoothType) {
26 this.bluetoothType = bluetoothType;
27 }
28
29
30 }
BTItem.java
1 package com.houwen.btchatactivity;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.Set;
7 import android.app.Activity;
8 import android.app.AlertDialog;
9 import android.bluetooth.BluetoothAdapter;
10 import android.bluetooth.BluetoothDevice;
11 import android.content.BroadcastReceiver;
12 import android.content.Context;
13 import android.content.DialogInterface;
14 import android.content.Intent;
15 import android.content.IntentFilter;
16
17 public class BTManage {
18
19 // private List<BTItem> mListDeviceBT=null;
20 private BluetoothAdapter mBtAdapter =null;
21 private static BTManage mag=null;
22
23 private BTManage(){
24 // mListDeviceBT=new ArrayList<BTItem>();
25 mBtAdapter=BluetoothAdapter.getDefaultAdapter();
26 }
27
28 public static BTManage getInstance(){
29 if(null==mag)
30 mag=new BTManage();
31 return mag;
32 }
33
34 private StatusBlueTooth blueStatusLis=null;
35 public void setBlueListner(StatusBlueTooth blueLis){
36 this.blueStatusLis=blueLis;
37 }
38
39 public BluetoothAdapter getBtAdapter(){
40 return this.mBtAdapter;
41 }
42
43 public void openBluetooth(Activity activity){
44 if(null==mBtAdapter){ ////Device does not support Bluetooth
45 AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
46 dialog.setTitle("No bluetooth devices");
47 dialog.setMessage("Your equipment does not support bluetooth, please change device");
48
49 dialog.setNegativeButton("cancel",
50 new DialogInterface.OnClickListener() {
51 @Override
52 public void onClick(DialogInterface dialog, int which) {
53
54 }
55 });
56 dialog.show();
57 return;
58 }
59 // If BT is not on, request that it be enabled.
60 if (!mBtAdapter.isEnabled()) {
61 /*Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
62 activity.startActivityForResult(enableIntent, 3);*/
63 mBtAdapter.enable();
64 }
65 }
66
67 public void closeBluetooth(){
68 if(mBtAdapter.isEnabled())
69 mBtAdapter.disable();
70 }
71
72 public boolean isDiscovering(){
73 return mBtAdapter.isDiscovering();
74 }
75
76 public void scanDevice(){
77 // mListDeviceBT.clear();
78 if(!mBtAdapter.isDiscovering())
79 mBtAdapter.startDiscovery();
80 }
81
82 public void cancelScanDevice(){
83 if(mBtAdapter.isDiscovering())
84 mBtAdapter.cancelDiscovery();
85 }
86
87 public void registerBluetoothReceiver(Context mcontext){
88 // Register for broadcasts when start bluetooth search
89 IntentFilter startSearchFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
90 mcontext.registerReceiver(mBlueToothReceiver, startSearchFilter);
91 // Register for broadcasts when a device is discovered
92 IntentFilter discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
93 mcontext.registerReceiver(mBlueToothReceiver, discoveryFilter);
94 // Register for broadcasts when discovery has finished
95 IntentFilter foundFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
96 mcontext.registerReceiver(mBlueToothReceiver, foundFilter);
97 }
98
99 public void unregisterBluetooth(Context mcontext){
100 cancelScanDevice();
101 mcontext.unregisterReceiver(mBlueToothReceiver);
102 }
103
104 public List<BTItem> getPairBluetoothItem(){
105 List<BTItem> mBTitemList=null;
106 // Get a set of currently paired devices
107 Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
108 Iterator<BluetoothDevice> it=pairedDevices.iterator();
109 while(it.hasNext()){
110 if(mBTitemList==null)
111 mBTitemList=new ArrayList<BTItem>();
112
113 BluetoothDevice device=it.next();
114 BTItem item=new BTItem();
115 item.setBuletoothName(device.getName());
116 item.setBluetoothAddress(device.getAddress());
117 item.setBluetoothType(BluetoothDevice.BOND_BONDED);
118 mBTitemList.add(item);
119 }
120 return mBTitemList;
121 }
122
123
124 private final BroadcastReceiver mBlueToothReceiver = new BroadcastReceiver() {
125 @Override
126 public void onReceive(Context context, Intent intent) {
127 String action = intent.getAction();
128 if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
129 if(blueStatusLis!=null)
130 blueStatusLis.BTDeviceSearchStatus(StatusBlueTooth.SEARCH_START);
131 }
132 else if (BluetoothDevice.ACTION_FOUND.equals(action)){
133 // When discovery finds a device
134 // Get the BluetoothDevice object from the Intent
135 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
136 // If it's already paired, skip it, because it's been listed already
137 if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
138 BTItem item=new BTItem();
139 item.setBuletoothName(device.getName());
140 item.setBluetoothAddress(device.getAddress());
141 item.setBluetoothType(device.getBondState());
142
143 if(blueStatusLis!=null)
144 blueStatusLis.BTSearchFindItem(item);
145 // mListDeviceBT.add(item);
146 }
147 }
148 else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
149 // When discovery is finished, change the Activity title
150 if(blueStatusLis!=null)
151 blueStatusLis.BTDeviceSearchStatus(StatusBlueTooth.SEARCH_END);
152 }
153 }
154 };
155
156
157 }
BTManage.java
1 package com.houwen.btchatactivity;
2
3 import java.io.BufferedInputStream;
4 import java.io.BufferedOutputStream;
5 import java.io.EOFException;
6 import java.io.IOException;
7 import java.util.UUID;
8 import android.bluetooth.BluetoothAdapter;
9 import android.bluetooth.BluetoothServerSocket;
10 import android.bluetooth.BluetoothSocket;
11 import android.os.Handler;
12 import android.os.Message;
13
14 public class BTServer {
15
16 /* 一些常量,代表服务器的名称 */
17 public static final String PROTOCOL_SCHEME_L2CAP = "btl2cap";
18 public static final String PROTOCOL_SCHEME_RFCOMM = "btspp";
19 public static final String PROTOCOL_SCHEME_BT_OBEX = "btgoep";
20 public static final String PROTOCOL_SCHEME_TCP_OBEX = "tcpobex";
21
22 private BluetoothServerSocket btServerSocket = null;
23 private BluetoothSocket btsocket = null;
24 private BluetoothAdapter mBtAdapter =null;
25 private BufferedInputStream bis=null;
26 private BufferedOutputStream bos=null;
27
28 private Handler detectedHandler=null;
29
30 public BTServer(BluetoothAdapter mBtAdapter,Handler detectedHandler){
31 this.mBtAdapter=mBtAdapter;
32 this.detectedHandler=detectedHandler;
33 }
34
35 public void startBTServer() {
36 ThreadPool.getInstance().excuteTask(new Runnable() {
37 public void run() {
38 try {
39 btServerSocket = mBtAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM,
40 UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
41
42 Message msg = new Message();
43 msg.obj = "请稍候,正在等待客户端的连接...";
44 msg.what = 0;
45 detectedHandler.sendMessage(msg);
46
47 btsocket=btServerSocket.accept();
48 Message msg2 = new Message();
49 String info = "客户端已经连接上!可以发送信息。";
50 msg2.obj = info;
51 msg.what = 0;
52 detectedHandler.sendMessage(msg2);
53
54 receiverMessageTask();
55 } catch(EOFException e){
56 Message msg = new Message();
57 msg.obj = "client has close!";
58 msg.what = 1;
59 detectedHandler.sendMessage(msg);
60 }catch (IOException e) {
61 e.printStackTrace();
62 Message msg = new Message();
63 msg.obj = "receiver message error! please make client try again connect!";
64 msg.what = 1;
65 detectedHandler.sendMessage(msg);
66 }
67 }
68 });
69 }
70
71 private void receiverMessageTask(){
72 ThreadPool.getInstance().excuteTask(new Runnable() {
73 public void run() {
74 byte[] buffer = new byte[2048];
75 int totalRead;
76 /*InputStream input = null;
77 OutputStream output=null;*/
78 try {
79 bis=new BufferedInputStream(btsocket.getInputStream());
80 bos=new BufferedOutputStream(btsocket.getOutputStream());
81 } catch (IOException e) {
82 e.printStackTrace();
83 }
84
85 try {
86 // ByteArrayOutputStream arrayOutput=null;
87 while((totalRead = bis.read(buffer)) > 0 ){
88 // arrayOutput=new ByteArrayOutputStream();
89 String txt = new String(buffer, 0, totalRead, "UTF-8");
90 Message msg = new Message();
91 msg.obj = txt;
92 msg.what = 1;
93 detectedHandler.sendMessage(msg);
94 }
95 } catch (IOException e) {
96 e.printStackTrace();
97 }
98 }
99 });
100 }
101
102 public boolean sendmsg(String msg){
103 boolean result=false;
104 if(null==btsocket||bos==null)
105 return false;
106 try {
107 bos.write(msg.getBytes());
108 bos.flush();
109 result=true;
110 } catch (IOException e) {
111 e.printStackTrace();
112 }
113 return result;
114 }
115
116 public void closeBTServer(){
117 try{
118 if(bis!=null)
119 bis.close();
120 if(bos!=null)
121 bos.close();
122 if(btServerSocket!=null)
123 btServerSocket.close();
124 if(btsocket!=null)
125 btsocket.close();
126 }catch(IOException e){
127 e.printStackTrace();
128 }
129 }
130
131 }
BTServer.java
1 package com.houwen.btchatactivity;
2
3 import java.util.concurrent.LinkedBlockingQueue;
4 import java.util.concurrent.ThreadFactory;
5 import java.util.concurrent.ThreadPoolExecutor;
6 import java.util.concurrent.TimeUnit;
7 import java.util.concurrent.atomic.AtomicBoolean;
8 import java.util.concurrent.atomic.AtomicInteger;
9
10 public class ThreadPool {
11
12 private AtomicBoolean mStopped = new AtomicBoolean(Boolean.FALSE);
13 private ThreadPoolExecutor mQueue;
14 private final int coreSize=2;
15 private final int maxSize=10;
16 private final int timeOut=2;
17 private static ThreadPool pool=null;
18
19 private ThreadPool() {
20 mQueue = new ThreadPoolExecutor(coreSize, maxSize, timeOut, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), sThreadFactory);
21 // mQueue.allowCoreThreadTimeOut(true);
22 }
23
24 public static ThreadPool getInstance(){
25 if(null==pool)
26 pool=new ThreadPool();
27 return pool;
28 }
29
30 public void excuteTask(Runnable run) {
31 mQueue.execute(run);
32 }
33
34 public void closeThreadPool() {
35 if (!mStopped.get()) {
36 mQueue.shutdownNow();
37 mStopped.set(Boolean.TRUE);
38 }
39 }
40
41 private static final ThreadFactory sThreadFactory = new ThreadFactory() {
42 private final AtomicInteger mCount = new AtomicInteger(1);
43
44 @Override
45 public Thread newThread(Runnable r) {
46 return new Thread(r, "ThreadPool #" + mCount.getAndIncrement());
47 }
48 };
49
50 }
ThreadPool.java
1 package com.houwen.btchatactivity;
2
3
4 import java.util.ArrayList;
5 import java.util.List;
6 import android.content.Context;
7 import android.view.LayoutInflater;
8 import android.view.View;
9 import android.view.ViewGroup;
10 import android.widget.BaseAdapter;
11 import android.widget.TextView;
12
13
14 public class BTDeviceAdapter extends BaseAdapter{
15
16
17 private List<BTItem> mListItem=new ArrayList<BTItem>();;
18 private Context mcontext=null;
19 private LayoutInflater mInflater=null;
20
21 public BTDeviceAdapter(Context context){
22 this.mcontext=context;
23 // this.mListItem=mListItem;
24 this.mInflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
25
26 }
27
28 void clearData(){
29 mListItem.clear();
30 }
31
32 void addDataModel(List<BTItem> itemList){
33 if(itemList==null || itemList.size()==0)
34 return;
35 mListItem.addAll(itemList);
36 notifyDataSetChanged();
37 }
38 void addDataModel(BTItem item){
39 mListItem.add(item);
40 notifyDataSetChanged();
41 }
42
43 @Override
44 public int getCount() {
45
46 return mListItem.size();
47 }
48
49 @Override
50 public Object getItem(int position) {
51
52 return mListItem.get(position);
53 }
54
55 @Override
56 public long getItemId(int position) {
57
58 return position;
59 }
60
61 @Override
62 public View getView(int position, View convertView, ViewGroup parent) {
63 ViewHolder holder=null;
64
65 if(convertView==null){
66 holder=new ViewHolder();
67 convertView = mInflater.inflate(R.layout.device_item_row, null);
68 holder.tv=(TextView)convertView.findViewById(R.id.itemText);
69 convertView.setTag(holder);
70 }else{
71 holder=(ViewHolder)convertView.getTag();
72 }
73
74
75 holder.tv.setText(mListItem.get(position).getBuletoothName());
76 return convertView;
77 }
78
79
80 class ViewHolder{
81 TextView tv;
82 }
83
84 }
BTDeviceAdapter.java
1 package com.houwen.btchatactivity;
2
3
4 public interface StatusBlueTooth {
5
6 final static int SEARCH_START=110;
7 final static int SEARCH_END=112;
8 final static int serverCreateSuccess=211;
9 final static int serverCreateFail=212;
10 final static int clientCreateSuccess=221;
11 final static int clientCreateFail=222;
12 final static int connectLose=231;
13
14 void BTDeviceSearchStatus(int resultCode);
15 void BTSearchFindItem(BTItem item);
16 void BTConnectStatus(int result);
17
18 }
StatusBlueTooth.java
需在AndroidManifest.xml中添加许可:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
对于界面的设计主要代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android1="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout
android:id="@+id/edit_bottombar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<Button
android:id="@+id/btn_disconnect"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="断开" />
<Button
android:id="@+id/btn_msg_send"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="发送" />
<EditText
android:id="@+id/MessageText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/btn_msg_send"
android:layout_toRightOf="@+id/btn_disconnect"
android:hint="说点什么呢?"
android:textSize="15sp" />
</RelativeLayout>
<RadioGroup
android1:id="@+id/radioGroup"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:layout_alignParentLeft="true"
android1:layout_alignParentTop="true" >
<RadioButton
android1:id="@+id/radioNone"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:checked="true"
android1:text="AS none" />
<RadioButton
android1:id="@+id/radioClient"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:text="AS Client" />
<RadioButton
android1:id="@+id/radioServer"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:text="AS server" />
</RadioGroup>
<ListView
android1:id="@+id/list"
android1:layout_width="match_parent"
android1:layout_height="wrap_content"
android1:layout_above="@+id/edit_bottombar"
android1:layout_below="@+id/radioGroup"
android1:layout_centerHorizontal="true"
android1:layout_marginBottom="21dp" >
</ListView>
<Button
android1:id="@+id/finddevice"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:layout_alignParentRight="true"
android1:layout_alignParentTop="true"
android1:text="搜索设备" />
</RelativeLayout>
bt_chat.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id = "@+id/devices"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom = "true"
android:id= "@+id/bt_bottombar">
<Button android:id="@+id/start_seach"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Began to search"/>
</RelativeLayout>
<ListView
android:id="@+id/devicelist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollingCache="false"
android:divider="#ffc6c6c6"
android:layout_above = "@id/bt_bottombar"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
finddevice.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7 <TextView
8 android:id="@+id/itemText"
9 android:layout_width="wrap_content"
10 android:layout_height="wrap_content"
11 android:text="00000000" />
12
13 </LinearLayout>
device_item_row
测试时,需要两部带有蓝牙的android手机(我的开发环境是android4.3),一个作为Client,一个作为Server进行测试即可。
至此,功能基本实现。