Android之蓝牙编程开发详解

时间:2024-04-16 16:13:25

 我们知道,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>

 

http://blog.****.net/xiang_j2ee/article/details/7041615