我们知道,Android从2.0版本后的sdk开始才支持蓝牙开发,现在一般都不用蓝牙,而且模拟器不支持,测试至少需要两部手机,所以制约了很多技术人员的开发,Demo在国内更是少之又少。技术来源于网络,也要归属于网络,所以此次放置上来供大家共享学习。
由于我这里只有一台支持android的手机(google nexus s),但我的电脑是支持蓝牙的,所以就利用电脑和手机进行蓝牙通信,利用电脑测试借助于小工具:串口调试小助手。上网下载。
原理:android的蓝牙通信类似java的socket编程,一端发送,一端接收,发送点相当于服务器,接收端相当于客户端,也就是说,如果有类库可以帮我们产生服务器和客户端的API接口实例,接下来问题就简单很多,就可以通过JavaIO操作实现数据传输。
代码实现必备知识点:
1、要操作蓝牙,先要在AndroidManifest.xml里加入权限,否则不能操作蓝牙。
<uses-permissionandroid:name="android.permission.BLUETOOTH" />
2、认识几个重要的蓝牙操作类
a) BluetoothAdapter(借助此类可以获得本机上的蓝牙设备)
b) BluetoothServerSocket(由名字可以看出,是蓝牙的服务端的操作类)
OK,需要蓝牙通信的重要类就两个,其他的自己去查看相关文档。
3、各种状态通过Handler来动态显示。
4、布局就是一个非常简单的layout.xml文件,一个textedit和一个button。
代码演示:
1、布局文件main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:layout_height="wrap_content" android:id="@+id/edtMessage" android:layout_width="match_parent"> <requestFocus></requestFocus> </EditText> <Button android:text="send message" android:id="@+id/btnSend" android:layout_width="match_parent" android:layout_height="wrap_content"></Button> </LinearLayout>
2、蓝牙核心代码:
package cn.com.leon.bluetooth; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.Log; import android.widget.Toast; public class BusiessBlueToothChat { private static final String s_Tag = "BusniessBluetooth"; private BluetoothAdapter m_BluetoothAdapter; private Context m_Context; private InputStream m_InputStream; private OutputStream m_OutputStream; private int m_State; private int m_StateConnected = 0; private int m_StateDisConnect = 1; private boolean m_IsNormalClose = false; private Message m_Message = new Message(); private PortListenThread m_PortListenThread; private OnPortListener m_OnPortListener; private Handler m_Handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1: Toast.makeText(m_Context, "蓝牙设备不存在或被关闭,打开后重新启动服务", Toast.LENGTH_SHORT).show(); break; default: break; } } }; private static final String S_NAME = "BluetoothChat"; private static final UUID S_UUID = UUID .fromString("00001101-0000-1000-8000-00805F9B34FB"); public interface OnPortListener { public abstract void OnReceiverData(String p_Message); } public BusiessBlueToothChat(Context p_context) { m_Context = p_context; m_Message.what = 1; m_OnPortListener = (OnPortListener) p_context; } public void CreatePortListen() { try { // 获得一个本机蓝牙设备 m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 判断是否不存在蓝牙设备或没有打开 if (m_BluetoothAdapter != null || m_BluetoothAdapter.isEnabled()) { // 已开启蓝牙,创建一个无线射频通信(RFCOMM)蓝牙端口 BluetoothServerSocket _BluetoothServerSocket = m_BluetoothAdapter .listenUsingRfcommWithServiceRecord(S_NAME, S_UUID); if (m_PortListenThread == null) { // 启动端口监听线程 m_PortListenThread = new PortListenThread( _BluetoothServerSocket); m_PortListenThread.start(); } } else { m_Handler.sendMessage(m_Message); } } catch (Exception e) { Log.i(s_Tag, e.getMessage()); CreatePortListen(); } } public class PortListenThread extends Thread { private BluetoothServerSocket m_BluetoothServerSocket; BluetoothSocket _BluetoothSocket; public PortListenThread(BluetoothServerSocket p_BluetoothServerSocket) { // 初始化Socket m_BluetoothServerSocket = p_BluetoothServerSocket; } @Override public void run() { try { // 调用accept接收对方数据请求 BluetoothSocket _BluetoothSocket = m_BluetoothServerSocket .accept(); // 获得输出流 m_OutputStream = _BluetoothSocket.getOutputStream(); // 修改连接状态,表示已连接 m_State = m_StateConnected; // 建立一个长连接持续接收对方数据 while (m_State == m_StateConnected) { // 获得输入流 m_InputStream = _BluetoothSocket.getInputStream(); ReceiverData(); } } catch (Exception e) { Log.i(s_Tag, e.getMessage()); if (!m_BluetoothAdapter.isEnabled()) { m_Handler.sendMessage(m_Message); } } } public void Close() { try { m_BluetoothServerSocket.close(); if (_BluetoothSocket != null) { _BluetoothSocket.close(); } if (m_OutputStream != null) { m_OutputStream.close(); } if (m_InputStream != null) { m_InputStream.close(); } } catch (Exception e) { Log.i(s_Tag, e.getMessage()); } } } public void ReceiverData() { try { /* // 初始化字节数组 byte[] _Byte = new byte[8]; // 读取前8个字节获取数据长度 m_InputStream.read(_Byte); // 将字节转换为String字符 String _Msg = new String(_Byte); // 将String字符转换为int数字 int _Length = Integer.parseInt(_Msg); // 按得到的长度再初始化一个字节数组 _Byte = new byte[_Length]; // 继续读取剩余的数据 m_InputStream.read(_Byte); // 将两次数据合并为一个完整的数据 _Msg += new String(_Byte); */ byte[] _Byte = new byte[1024]; int len = 0; int t_temp = 0; while((t_temp=m_InputStream.read())!=-1){ _Byte[len++]=(byte)t_temp; } String _Msg = new String(_Byte,0,_Byte.length); // 调用回调函数,返回到界面处理 m_OnPortListener.OnReceiverData(_Msg); } catch (Exception e) { Log.i(s_Tag, e.getMessage()); if (!m_IsNormalClose) { Close(false); CreatePortListen(); } } } public void SendData(String p_Data) { try { // 调用输出流向对方发送数据 m_OutputStream.write(p_Data.getBytes()); } catch (Exception e) { Log.i(s_Tag, e.getMessage()); } } public void Close(boolean p_IsNormalClose) { m_IsNormalClose = p_IsNormalClose; m_State = m_StateDisConnect; if (m_PortListenThread != null) { m_PortListenThread.Close(); m_PortListenThread = null; } } }
3、MainActivity.java,入口代码:
package cn.com.leon.bluetooth; import cn.com.leon.bluetooth.BusiessBlueToothChat.OnPortListener; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity implements OnClickListener, OnPortListener { private BusiessBlueToothChat m_BusiessBlueToothChat; EditText _edtMessage; Button _btnSend; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); InitView(); InitListener(); m_BusiessBlueToothChat = new BusiessBlueToothChat(this); m_BusiessBlueToothChat.CreatePortListen(); } private void InitView(){ _edtMessage = (EditText) this.findViewById(R.id.edtMessage); _btnSend = (Button) this.findViewById(R.id.btnSend); } private void InitListener(){ _btnSend.setOnClickListener(this); } @Override public void onClick(View v){ switch (v.getId()) { case R.id.btnSend: m_BusiessBlueToothChat.SendData(_edtMessage.getText().toString()); break; default: break; } } @Override public void OnReceiverData(String p_Message) { Log.i("BusinessBluetooth", "接收到的数据:"+p_Message); } }
4、注册mianfest.xml文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.com.leon.bluetooth" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.BLUETOOTH"/> </manifest>