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 }
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 }
两个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 }
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 }
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 }
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 }
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 }
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 }
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 }
需在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>
<?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>
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>
测试时,需要两部带有蓝牙的android手机(我的开发环境是android4.3),一个作为Client,一个作为Server进行测试即可。
至此,功能基本实现。