移动开发作业6——蓝牙通信的简要设计与开发

安卓实现蓝牙控制
1.在AndroidManifest.xml中添加权限申请


   <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

2…编写客户端代码

public class ConnectThread extends Thread{
    private static final UUID MY_UUID= UUID.fromString(Constant.CONNECTTION_UUID);
    /** 客户端socket*/
    private final BluetoothSocket mmSoket;
    /** 要连接的设备*/
    private final BluetoothDevice mmDevice;
    private BluetoothAdapter mBluetoothAdapter;
    /** 主线程通信的Handler*/
    private final Handler mHandler;
    /** 发送和接收数据的处理类*/
    private ConnectedThread mConnectedThread;
 
    public ConnectThread(BluetoothDevice device, BluetoothAdapter bluetoothAdapter, Handler mUIhandler) {
        mmDevice = device;
        mBluetoothAdapter = bluetoothAdapter;
        mHandler = mUIhandler;
 
        BluetoothSocket tmp = null;
        try {
            // 创建客户端Socket
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        mmSoket = tmp;
    }
 
    @Override
    public void run() {
        super.run();
        // 关闭正在发现设备.(如果此时又在查找设备,又在发送数据,会有冲突,影响传输效率)
        mBluetoothAdapter.cancelDiscovery();
 
        try {
            // 连接服务器
            mmSoket.connect();
        } catch (IOException e) {
            // 连接异常就关闭
            try {
                mmSoket.close();
            } catch (IOException e1) {
            }
            return;
        }
 
        manageConnectedSocket(mmSoket);
    }
 
    private void manageConnectedSocket(BluetoothSocket mmSoket) {
        // 通知主线程连接上了服务端socket,更新UI
        mHandler.sendEmptyMessage(Constant.MSG_CONNECTED_TO_SERVER);
        // 新建一个线程进行通讯,不然会发现线程堵塞
        mConnectedThread = new ConnectedThread(mmSoket,mHandler);
        mConnectedThread.start();
    }
 
    /**
     * 关闭当前客户端
     */
    public void cancle() {
        try {
            mmSoket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 发送数据
     * @param data
     */
    public void sendData(byte[] data) {
        if(mConnectedThread != null) {
            mConnectedThread.write(data);
        }
    }
}

3.编写服务端的代码


public class AcceptThread extends Thread {
 
    /** 连接的名称*/
    private static final String NAME = "BluetoothClass";
    /** UUID*/
    private static final UUID MY_UUID = UUID.fromString(Constant.CONNECTTION_UUID);
    /** 服务端蓝牙Sokcet*/
    private final BluetoothServerSocket mmServerSocket;
    private final BluetoothAdapter mBluetoothAdapter;
    /** 线程中通信的更新UI的Handler*/
    private final Handler mHandler;
    /** 监听到有客户端连接,新建一个线程单独处理,不然在此线程中会堵塞*/
    private ConnectedThread mConnectedThread;
 
    public AcceptThread(BluetoothAdapter adapter, Handler handler) throws IOException {
        mBluetoothAdapter = adapter;
        this.mHandler = handler;
 
        // 获取服务端蓝牙socket
        mmServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
    }
 
    @Override
    public void run() {
        super.run();
        // 连接的客户端soacket
        BluetoothSocket socket = null;
 
        // 服务端是不退出的,要一直监听连接进来的客户端,所以是死循环
        while (true){
            // 通知主线程更新UI,客户端开始监听
            mHandler.sendEmptyMessage(Constant.MSG_START_LISTENING);
            try {
                // 获取连接的客户端socket
                socket =  mmServerSocket.accept();
            } catch (IOException e) {
                // 通知主线程更新UI, 获取异常
                mHandler.sendEmptyMessage(Constant.MSG_ERROR);
                e.printStackTrace();
                // 服务端退出一直监听线程
                break;
            }
 
            if(socket != null) {
                // 管理连接的客户端socket
                manageConnectSocket(socket);
 
                // 这里应该是手动断开,案例应该是只保证连接一个客户端,所以连接完以后,关闭了服务端socket
//                try {
//                    mmServerSocket.close();
//                    mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
            }
        }
    }
 
    /**
     * 管理连接的客户端socket
     * @param socket
     */
    private void manageConnectSocket(BluetoothSocket socket) {
        // 只支持同时处理一个连接
        // mConnectedThread不为空,踢掉之前的客户端
        if(mConnectedThread != null) {
            mConnectedThread.cancle();
        }
 
        // 主线程更新UI,连接到了一个客户端
        mHandler.sendEmptyMessage(Constant.MSG_GOT_A_CLINET);
        // 新建一个线程,处理客户端发来的数据
        mConnectedThread = new ConnectedThread(socket, mHandler);
        mConnectedThread.start();
    }
 
    /**
     * 断开服务端,结束监听
     */
    public void cancle() {
        try {
            mmServerSocket.close();
            mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 发送数据
     * @param data
     */
    public void sendData(byte[] data){
        if(mConnectedThread != null) {
            mConnectedThread.write(data);
        }
    }
}

4.Constant常量类

public class Constant {
    public static final String CONNECTTION_UUID = "00001101-0000-1000-8000-00805F9B34FB";
    /**
     * 开始监听
     */
    public static final int MSG_START_LISTENING = 1;
    /**
     * 结束监听
     */
    public static final int MSG_FINISH_LISTENING = 2;
    /**
     * 有客户端连接
     */
    public static final int MSG_GOT_A_CLINET = 3;
    /**
     * 连接到服务器
     */
    public static final int MSG_CONNECTED_TO_SERVER = 4;
    /**
     * 获取到数据
     */
    public static final int MSG_GOT_DATA = 5;
    /**
     * 出错
     */
    public static final int MSG_ERROR = -1;
}

5.编写蓝牙接受广播


private BroadcastReceiver mReceiverBluetoothStatus = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context,Intent intent) {
            String action = intent.getAction();
            if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
                // 开始搜索        ——接收广播
                Log.d(TAG,"开始搜索");
                mList.clear();
                mAdapter.refresh(mList);
 
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                // 查找到设备完成   —— 接收广播
                Log.d(TAG,"查找到设备完成");
 
            } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // 搜索到设备       —— 接收广播
                Log.d(TAG,"搜索到设备");
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                mList.add(device);
                mAdapter.refresh(mList);
 
 
            } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
                // 当自己设备设置蓝牙可见时或者不可见时 —— 接收广播
                int scanMode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,0);
                // 可见时
                if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                    Log.d(TAG,"设备可见监听");
                } else {
                    Log.d(TAG,"设备不可见监听");
                }
 
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                // 绑定状态改变回调
                BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (remoteDevice == null) {
                    Log.d(TAG,"没有绑定设备");
                    return;
                }
 
                int status = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,0);
                if (status == BluetoothDevice.BOND_BONDED) {
                    Log.d(TAG,"绑定设备完成: " + remoteDevice.getName());
                } else if (status == BluetoothDevice.BOND_BONDING) {
                    Log.d(TAG,"绑定设备中: " + remoteDevice.getName());
                } else if (status == BluetoothDevice.BOND_NONE) {
                    Log.d(TAG,"取消绑定: ");
                }
            }
        }
    };

6.蓝牙设备DeviceAdapter

public class DeviceAdapter extends BaseAdapter {
    private Context mContext;
    private List<BluetoothDevice> mDate;

    public DeviceAdapter(List<BluetoothDevice> Date, Context context){
        mDate = Date;
        mContext = context;
    }
    @Override
    public int getCount() {
        return mDate.size();
    }
    @Override
    public Object getItem(int position) {
        return mDate.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        if(convertView==null){
            viewHolder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.deviceadapter_layout,null);
            viewHolder.textView1 = (TextView)convertView.findViewById(R.id.textview1);
            viewHolder.textView2 = (TextView)convertView.findViewById(R.id.textview2);
            convertView.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder) convertView.getTag();
        }
        //获取蓝牙设备
        BluetoothDevice bluetoothDevice = (BluetoothDevice) getItem(position);
        viewHolder.textView1.setText("Name="+bluetoothDevice.getName());
        viewHolder.textView2.setText("Address"+bluetoothDevice.getAddress());
        return convertView;
    }
    public class ViewHolder{
        public TextView textView1;
        public  TextView textView2;
    }
    public void refresh(List<BluetoothDevice> data){
        mDate = data;
        notifyDataSetChanged();
    }
}

实验截图:

在这里插入图片描述
代码地址:https://gitee.com/shijia0526/Bluetooth

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值