Android蓝牙应用开发

本文介绍从查找蓝牙到蓝牙间互相通信的几个基本开发步骤

(1)设置权限:在Android系统中使用蓝牙一般需要在AndroidManifest.xml中设置蓝牙权限

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

(2)启动蓝牙:启动蓝牙前需要检查设备是否支持蓝牙,然后获取蓝牙适配器对象

final int REQUEST_ENABLE_BT = 111;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if(adapter == null){
    //设备不支持蓝牙的相关动作
    return;
}
//蓝牙未开启
if(!adapter.isEnabled()){
    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(intent,REQUEST_ENABLE_BT);
}
...
public void onActivityResult(int requestCode, int resultCode,Intent data){
    if(resultCode == REQUEST_ENABLE_BT){
        if(requestCode == RESULT_OK){
            //蓝牙开启成功
        }
    }
}

(3)发现蓝牙设备

1、本机蓝牙调到可见模式,便于其他设备搜索发现

final int BLUETOOTH_DISCOVER_TIME = 300;//300s内对其他设备可见
private void ensureDiscoverable(){
    if(adapter.getScanMode() != BlueToothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION
                        ,BLUETOOTH_DISCOVER_TIME);
        startActivity(intent);
    }
}

2、查找已配对的蓝牙设备

Set<BluetoothDevice> devices = adapter.getBondedDevices();
if(devices.size > 0){
    //存在配对过的蓝牙设备,进行展示会处理
}
else{
    //没有配对过的设备
}

3、搜索设备,注册一个BroadcastReceiver获得搜索结果

//注册广播,发现设备
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this,registerReceiver(receiver,filter);
//搜索结束
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_DISCOVERY_FINISHED);
this,registerReceiver(receiver,filter);
...
private BroadcastReceiver receiver = new BroadcastReceiver(){
    @Override
    public void onReceive(Context context, Intent intent){
        String action = intent.getAction();
        if(BluetoothDevice.ACTION_FOUND.equals(action)){
            BluetoothDevice device =
            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            //跳过已配对设备
            if(device.getBondState() != BluetoothDevice.BOND_BONDED){
                //对未配对蓝牙的处理
            }    
        }
        else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
            //搜索结束处理
        }
    }
};

(4)建立连接:当查找到蓝牙设备后,需要建立本机与其他蓝牙设备之间的连接。一般在使用本机搜索其他蓝牙设备时,本机可以作为一个服务端来接收其他设备的连接。启动一个服务器端线程,死循环等待客户端的连接。

//UUID可以看成是一个随机生成的端口号
private static final UUID BT_UUID = 
        UUID.fromString("fa87c0d0-afac-l1de-8a39-0800200c9a66");
//创建一个新线程监听是否有连接建立
private class AcceptThread extends Thread{
    private BluetoothServerSocket serverSocket;
    public AcceptThread(boolean secure){
        BluetoothServerSocket socket = null;
        try{
            socket = adapter.listenUsingRfcommWithServerRecord(NAME_INSECURE,BT_UUID);
        }catch(IOException e){
            Log.e("app","listen failed",e);
        }
        serverSocket = socket;
    }

    public void run(){
        BluetoothSocket socket = null;
        while(true){
            try{
                socket = serverSocket.accept();
            }catch(IOException e){
                Log.e("app","accept failed",e);
                break;
            }
        }
        if(socket != null){
            //新建一个数据交换线程,将该socket传入
        }
    }

    //取消监听
    public void cancel(){
        try{
            serverSocket.close();
        }catch(IOException e){
            Log.e("app","cancel failed",e);
        }
    }
}

(5)交换数据:当搜索到蓝牙设备后,接下来可以获取设备的地址,通过此地址获取一个BluetoothDevice对象,可以将其看成是一个客户端,通过device.createRfcommSocketToServiceRecord(BT_UUID)相同的UUID,可与服务器建立连接获取另一个Socket对象。因为此服务器与客户端各有一个Socket对象,因此此时它们可以互相交换数据

//另一个设备(客户端)连接本机
private class ConnectThread extends Thread{
    private BluetoothSocket socket;
    private BluetoothDevice device;
    public ConnectThread(BluetoothDevice device,boolean secure){
        this.device = device;
        BluetoothSocket temp = null;
        try{
            temp = device.createRfcommSocketToServerRecord(BT_UUID);
        }catch(IOException e){
            Log.e("app","create failed",e);
        }
    }

    public void run(){
        adapter.cancelDiscovery();
        try{
            socket.connect();
        }catch(IOException e){
            try{
                socket.close()
            }catch(IOException e){
                Log.e("app","close failed",e);
            }
        connectionFailed();//连接失败
        return;
        }
        //此时可以新建一个数据交换线程,将该socket传进去
    }

    public void cancel(){
        try{
            socket.close();
        }catch(IOException e){
            Log.e("app","close failed",e);
        }
    }
}

(6)建立数据通信线程:此处的任务是进行数据读取

//建立连接后,进行数据通信的线程
private class ConnectedThread extends Thread{
    private BluetoothSocket socket;
    private InputStream inStream;
    private OutputStream outStream;

    public ConnectedThread(BluetoothSocket socket){
        this.socket = socket;
        try{
            //获得输入输出流
            inStream = socket.getInputStream();
            outStream = socket.getOutputStream();
        }catch(IOException e){
            Log.e("app","socket error",e);
        }
    }

    public void run(){
        byte[] buff = new byte[1024];
        int len = 0;
        //读取数据需要不断监听,写则不需要
        while(true){
            try{
                len = inStream.read(buff);
                //把读到的数据发送给UI进行显示
                Messsage msg = handler.obtainMessage(BluetoothChat.MESSAGE_READ,
                                len,-1,buff);
                msg.sendToTarget();
            }catch(IOException e){
                Log.e("app","disconnected",e);
                connectionLost();//失去连接
                start();//重启服务器
                break;
            }
        }
    }

    public void write(byte[] buffer){
        try{
            outStream.write(buffer);
            handler.obtainMessage(BluetoothChat.MESSAGE_WRITE,-1,-1,buffer)
                        .sendToTarget();
        }catch(IOException e){
            Log.e("app","write failed",e);
        }
    }

    public void cancel(){
        try{
            socket.close;
        }catch(IOException e){
            Log.e("app","close failed,e);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/gengkui9897/article/details/81901380