android 蓝牙客户端与服务端通信


首先介绍基本类及方法
一,BlueboothAdapter这个就是表示本机,里面几个常用的方法如下。
1,getDefaultAdapter 这个是静态的方法,通过它可以获取BlueboothAdapter对象
2,enable()  这个方法会弹出一个对话框(包含“确定”,“取消”按钮)提示用户打开蓝牙,用户选择确定则这个方法会返回true,取消返回false.
3,getNmae() 返回本机蓝牙的名称
4,getRemoteDevice(String address)根据给定一个地址参数获取远程蓝牙。
5,getAddress 获取本机的地址
6,startDiscovery() 扫描周围蓝牙,若找到蓝牙会发送 BluetoothDevice. ACTION_FOUND广播
7 cancelDiscovery() 取消扫描
8,isEnabled() 判断蓝牙是否打开若打开则返回true,没有打开返回false
9,getBondedDevices() 返回绑定的蓝牙,
10,listenUsingRfcommWithServiceReord(String name,UUID uuid) 其中name通常是你的包名,也可以是任意字符串,UUID你可以通过浏览器在线获取
     返回的是一个BlueboothServerSocket对象

BlueboothAdapter中常用的方法就是这么多,接下来是BlueboothDevice
二,BlueboothDevice 这个表示远程的设备,常用方法如下
1,getName 获取远程蓝牙的名字
2,getAddress获取远程蓝牙的地址
3,getBondState()获取远程蓝牙的绑定状态,Bond_none 为绑定,bond_bonding正在绑定,bond_bonded已经绑定
3,createBond() 调用这个方法可以进行绑定蓝牙,这个方法要求的最低版本是19,当然你还可以通过反射进行绑定如下
Method method=(Method)BluetoothDevice.class.getMethod("createBond");
method.invoke(device);//device为你想要绑定的远程蓝牙
4,createRfcommSocketToServiceRecord(UUID uuid)//根据uuid获取BlueboothSocket对象,其中uuid一定要跟listenUsingRfcommWithServiceReord中给定的uuid一致

这里再说明一定蓝牙客户端与服务端进行通信时用BlueboothSocket获取输入流,输出流来进行通信的。
下面是代码包含蓝牙的搜索及绑定
public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
    private Button search;
    private Button client;
    private ListView listBluebooth;
    private BluetoothAdapter bAdapter;
    private BluetoothDevice bDevice;
    private ListAdapter listAdapter;
    private List<String> deviceNames = new ArrayList<>();
    private List<String> deviceAddress = new ArrayList<>();
    private BluetoothDevice device;
    private IsSuccess isSuccess;
    private String isServer = "on";//判断是否为服务端
    
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            search.setText("搜索完成");
            client.setText("搜索完成");
        }
    };
    private boolean sureBlueboothIsOpen=true;//默认蓝牙是打开状态

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        client = (Button) findViewById(R.id.client);
        client.setOnClickListener(this);
        search = (Button) findViewById(R.id.search);
        search.setOnClickListener(this);
        listBluebooth = (ListView) findViewById(R.id.list_bluebooth);
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(receiver, filter);
        bAdapter = BluetoothAdapter.getDefaultAdapter();


    }

    //得到已绑定的设备
    private void addBoundDevice(BluetoothAdapter bAdapter) {
        Set<BluetoothDevice> set = bAdapter.getBondedDevices();
        Log.d("test", "set:" + set.size());
        for (BluetoothDevice device : set) {
            deviceNames.add(device.getName());
            deviceAddress.add(device.getAddress());
        }
        listAdapter = new ListAdapter(MainActivity.this, R.layout.bluebooth_item, deviceNames);
        /*listAdapter.notifyDataSetChanged();*/
        listBluebooth.setAdapter(listAdapter);
        listBluebooth.setOnItemClickListener(this);
    }

    //搜索到发现蓝牙广播
    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("test", "action:" + intent.getAction());
            if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
                bDevice = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (bDevice.getBondState() == BluetoothDevice.BOND_NONE) {
                    Log.d("test", "none");
                    deviceNames.add(bDevice.getName());
                    deviceAddress.add(bDevice.getAddress());

                }
                listAdapter.notifyDataSetChanged();
                listBluebooth.setAdapter(listAdapter);
            } else if (intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {

                handler.sendEmptyMessage(1);
            }
        }
    };
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            Log.d("test", "result ok");
        }else {
            Log.d("test", resultCode + " result");
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //服务端只需打开蓝牙,不需扫描,只要等待客户端接入即可
            case R.id.search:
                if (!bAdapter.isEnabled()) {
                    
                    sureBlueboothIsOpen=bAdapter.enable();
                }
                if (sureBlueboothIsOpen) {
                    isServer = "yes";

                    Intent intent1 = new Intent(MainActivity.this, ChatActivity.class);
                    intent1.putExtra("is_server", isServer);
                    startActivity(intent1);
                    client.setEnabled(false);
                }else {
                    Toast.makeText(getApplicationContext(),"蓝牙没有开启",Toast.LENGTH_SHORT).show();
                    return;
                }

                break;
            case R.id.client:
                addBoundDevice(bAdapter);
                //用户按下取消按钮返回false,确定返回true
                if (!bAdapter.isEnabled()) {
                    sureBlueboothIsOpen=bAdapter.enable();
                }
                if (sureBlueboothIsOpen) {
                    isServer = "no";
                    bAdapter.startDiscovery();
                    client.setText("搜索蓝牙中");
                    isSuccess = new IsSuccess();
                    isSuccess.start();
                    search.setEnabled(false);
                }else {
                    Toast.makeText(getApplicationContext(),"蓝牙没有开启",Toast.LENGTH_SHORT).show();
                    return;
                }

                break;

        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
        if (isSuccess != null)
            isSuccess.interrupt();
    }

    //deviceNmaes list子项的点击事件配对蓝牙
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //你要想绑定的蓝牙
        device = bAdapter.getRemoteDevice(deviceAddress.get(position));

            try {
                Method method = (Method) BluetoothDevice.class.getMethod("createBond");

                Log.d("test", (boolean) method.invoke(device) + ":" + device.getBondState());
            /*Log.d("test", device.createBond() + ":" + device.getBondState());*/

            } catch (Exception e) {
                e.printStackTrace();
            }

           /* address = deviceAddress.get(position);
            Intent intent1 = new Intent(MainActivity.this, ChatActivity.class);
            intent1.putExtra("device", address);
            intent1.putExtra("is_server", isServer);
            startActivity(intent1);*/




    }

    //根据bDevice绑定状态判断用户是否按下匹配按钮
    //这个线程会一直执行下去直到用户绑定蓝牙成功
    class IsSuccess extends Thread {
        private int i = 0;

        @Override
        public void run() {
            while (true) {

                i++;


                    /*Log.d("test", "device state:" + bDevice.getBondState());*/
                    if (device != null) {
                        break;
                    }
                   /* if (bDevice.getBondState() == 12 ) {
                        break;
                    }*/



                try {
                    sleep(1000);

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (device.getBondState() == 12) {
                        Intent intent1 = new Intent(MainActivity.this, ChatActivity.class);
                        intent1.putExtra("device", device.getAddress());
                        intent1.putExtra("is_server", isServer);
                        startActivity(intent1);
                    }
                }
            });
        }
    }
}
接着是客户端与服务端通信的代码
public class ChatActivity extends Activity implements View.OnClickListener {
    private ListView chat;
    private EditText content;
    private static String UUID_CODE="42385BC1-F486-5196-1956-9CBEF428212B";
    private Button send;
    private BluetoothSocket socket;
    private BluetoothServerSocket serverSocket;
    private BluetoothAdapter bAdapter;
    private BluetoothDevice device;
    private ReadThread readThread;//读线程
    private String isServer;
    private List<String> messageLists = new ArrayList<>();
    private ArrayAdapter arrayAdapter;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 3) {
                Log.d("test", "message ==3");
                readThread = new ReadThread(socket);
                readThread.start();
                messageLists.add("已连接到服务端:" + socket.getRemoteDevice().getName());
            }
            arrayAdapter = new ArrayAdapter(ChatActivity.this, android.R.layout.simple_list_item_1, messageLists);
            switch (msg.what) {
                case 1:

                    break;
                case 2:
                    String content = (String) msg.obj;
                    Log.d("test", "handler:" + content);
                    messageLists.add(content);

                    break;
            }
            Log.d("test", messageLists.size() + "");
            arrayAdapter.notifyDataSetChanged();
            chat.setAdapter(arrayAdapter);
            chat.setSelection(messageLists.size()-1);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.char_layout);
        init();
    }

    @Override
    protected void onStart() {
        super.onStart();
        String isServer = getIntent().getStringExtra("is_server");
        if (isServer.equals("yes")) {
            Log.d("test", "server");
            this.isServer = "server";
            ServerThread serverThread = new ServerThread(bAdapter);
            serverThread.start();
        } else if (isServer.equals("no")) {
            Log.d("test", "client");
            this.isServer = "client";
            ClientThread clientThread = new ClientThread(device);
            clientThread.start();
        }
    }

    private void init() {
        chat = (ListView) findViewById(R.id.chat);
        content = (EditText) findViewById(R.id.content);
        send = (Button) findViewById(R.id.send);
        send.setOnClickListener(this);
        bAdapter = BluetoothAdapter.getDefaultAdapter();
        String address = getIntent().getStringExtra("device");
        if (!TextUtils.isEmpty(address)) {
            Log.d("test", "chat adress:" + address);
            device = bAdapter.getRemoteDevice(address);
        }

    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.send:
                Log.d("test", "onclick");
                if (!TextUtils.isEmpty(content.getText())) {
                    /*sendMessage();*/

                        Log.d("test", "sendmessage");
                        sendMessage(content.getEditableText().toString());
                    //若读线程为空则再次创建读线程
                    if (readThread == null) {
                        readThread = new ReadThread(socket);
                        readThread.start();
                        Log.d("test", "readThread==nulll");

                    }else {
                        Log.d("test", "readThread!=null");
                    }
                }
                break;
        }
    }

    //发送信息


    //客户端
    private class ClientThread extends Thread {
        private BluetoothDevice device;

        public ClientThread(BluetoothDevice device) {
            this.device = device;
        }

        @Override
        public void run() {
            try {

                Log.d("test", "client");
                bAdapter.cancelDiscovery();
                socket = device.createRfcommSocketToServiceRecord(UUID.fromString(UUID_CODE));
                Log.d("test", device.getUuids().toString());
                socket.connect();
		//通过BlueboothSocket的getRemoteDevice()来确认连接的远程蓝牙是否是自己想要连接的
                Log.d("test", "client connet success:"+socket.getClass().toString() + socket.getRemoteDevice().getName() + ":" + socket.getRemoteDevice().getAddress());
               /*if (socket != null) {
                    readThread = new ReadThread(socket);
                    readThread.start();
                }*/
                Log.d("test", "start client read");
                //这里创建的readThread为空
                        /*readThread = new ReadThread(socket);
                        readThread.start();*/
                Message message=new Message();
                message.what=3;
                handler.sendMessage(message);
            } catch (Exception e) {
                e.printStackTrace();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (socket != null) {

                       
                }
            });}
        }
    }

    //服务端
    private class ServerThread extends Thread {
        private BluetoothAdapter adapter;

        public ServerThread(BluetoothAdapter adapter) {
            this.adapter = adapter;
        }

        @Override
        public void run() {
            try {
                Log.d("test", "serverThread");
                /*bAdapter.cancelDiscovery();*/
                serverSocket = adapter.listenUsingInsecureRfcommWithServiceRecord("bluetoothdemo", UUID.fromString(UUID_CODE));

                socket = serverSocket.accept();
                Log.d("test", "server connect success");


            } catch (Exception e) {

            }

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.d("test", "start server read");
                    if (socket != null) {
                        //
                        readThread = new ReadThread(socket);
                        readThread.start();
                        messageLists.add("客户端:" + socket.getRemoteDevice().getName() + "已连接");
                        Message message=new Message();
                        message.what=1;
                        handler.sendMessage(message);
                       /* sendMessage("client:"+socket.getRemoteDevice().getName()+"已经连接");*///自己会读取自己这边放入的字符
                   /* socket.close();*/
                    }
                }
            });
        }
    }

    //从输入流中读取,因为read(byte [])这个方法会阻塞,所以要放到子线程中
    private class ReadThread extends Thread {
        private BluetoothSocket socket;
        private InputStream stream;


        public ReadThread(BluetoothSocket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            super.run();
            while (true) {
                try {

                    stream = socket.getInputStream();
                    /*if (stream != null)
                        *//*Log.d("test", "stram not null");*//*
                    else
                        Log.d("test", "stram null");*/
                    byte[] buff = new byte[1024];
                    stream.read(buff);
                    String content=new String(buff);
                    //判断是是服务端还是客户端
                    if (isServer.equals("server")) {
                        content="客户端:"+content;
                    }else {
                        content="服务端:"+content;
                    }

                    Message message = new Message();
                    message.obj = content;
                    message.what = 2;
                    handler.sendMessage(message);


                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

        }


    }
    //发送信息
    private void sendMessage(String content) {
        if (socket != null) {
            Log.d("test", "socket class:" + socket.getRemoteDevice().getName() + ":" + socket.getRemoteDevice().getAddress());
            Log.d("test", "socket class:" + socket.toString());
            try {
                Log.d("test", "sock not null");
                OutputStream outputStream = socket.getOutputStream();

                ;

                if (outputStream != null) {
                    Log.d("test", "output not null");
                }else {
                    Log.d("test", "output null");
                }
                outputStream.write(content.getBytes());
                messageLists.add(content);
               /* InputStream stream = socket.getInputStream();
                byte[] buff = new byte[1024];
                stream.read(buff);
                String s = new String(buff);
                Log.d("test", "read:" + s);*/
                Log.d("test", "tttt");
                Message message1 = new Message();
                message1.what = 1;
                handler.sendMessage(message1);
            } catch (Exception e) {
                e.printStackTrace();
            }

        } else {
            Log.d("test", "socket null");
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (readThread != null) {
            readThread.interrupt();
        }
    }
}
这里有几个坑想说一下,当你从输入流中读取信息的时候一定要保证读线程是不为空的,不然一定读取不到信息,所以我在按下发送按钮的时候再重新检查下读线程是否为空
要是为空则重新创建一个读线程

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值