欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Day6:蓝牙

程序员文章站 2022-07-13 22:30:53
...

一.蓝牙介绍:

是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换,我们主要掌握这几项技能:

  • 添加权限:
    <!-- 用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 用于访问GPS定位 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
  • 打开蓝牙并设置允许被搜索
 //调用系统开关蓝牙弹窗->用户手动允许
	Intent intent = new Intent();
	intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);//开启蓝
    intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//允许蓝牙被搜索
   intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,200);//设置允许被搜索时间200s内可以被搜索到
    startActivityForResult(intent,100);
  • 关闭蓝牙
 bluetoothAdapter.disable();//强制关闭蓝牙
  • 获得已经配对的蓝牙设备:
- adapter.getBondedDevices();
  • 搜索附近的蓝牙
bluetoothAdapter.startDiscovery();//搜索
  • 显示已经搜索到的蓝牙设备
//1.注册广播
//2.解除注册
//3.定义广播接受者
//TODO 1:广播接收者:接受系统发送的广播,扫描到设备
    class MyRecevier extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals(BluetoothDevice.ACTION_FOUND)){//扫描到一个
                //获得远程蓝牙设备
                BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                //放到listview中
                list.add(device);
                myAdapter.notifyDataSetChanged();
            }
        }
    }
  • 点击扫描到的设备进行配对蓝牙:
bluetoothDevice.createBond();//发起配对
  • 使用蓝牙传输数据:socket和ServerSocket传输数据
//1.获得客户端Socket
BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
//2.获得服务端Socket
BluetoothServerSocket serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(bluetoothAdapter.getName(),uuid);
serverSocket.accpet();

二.蓝牙的作用:

Day6:蓝牙Day6:蓝牙

三 .蓝牙工作原理以及涉及到的类:

Day6:蓝牙

  • BluetoothManager 蓝牙管理类,管理BluetoothAdapter。主要负责管理蓝牙的本地连接。
  • BluetoothAdapter 蓝牙适配器类:代表本蓝牙设备
  • BluetoothDevice 蓝牙设备,配对后的远程蓝牙设备.
  • BluetoothServiceSocket 服务端连接类
  • BluetoothSocket:客户端连接类
  • UUID(universal unique identifier , 全局唯一标识符)
    格式如下:UUID格式一般是”xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”,可到http://www.uuidgenerator.com 申请。UUID分为5段,是一个8-4-4-4-12的字符串,这个字符串要求永不重复。蓝牙建立连接时双方必须使用固定的UUID
    例如:文件传输服务
    OBEXFileTransferServiceClass_UUID = ‘{00001106-0000-1000-8000-00805F9B34FB}’

四.代码

/**
 * 1.蓝牙:BlueTooth  短距离数据传输
 * 2.应用:蓝牙耳机 蓝牙音箱
 * 3.功能:
 *   打开蓝牙:
 *   关闭蓝牙:
 *   扫描附近的蓝牙设备:
 *   配对蓝牙:
 *   传输文件:
 * 4.打开蓝牙:隐式意图打开蓝牙
 * 5.关闭蓝牙:adapter.disable()
 * 6.扫描:adpater.startDiscovery()
 * 7.配对:device.createBond()
 * 8.获取配对的设备:adpater.getBonedDevices()
 * 9.传输数据
 * (1)客户端
 * (2)服务端:
 * 一般保证蓝牙设备打开状态,不要点击关闭
 * **/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB");//蓝牙通讯规范
    Button bt_open,bt_close,bt_scan,bt_show;
    ListView listView,listView2;
    ArrayList<BluetoothDevice> list=new ArrayList<>();//附近的蓝牙设备
    ArrayList<BluetoothDevice> list2=new ArrayList<>();//已经配对的蓝牙设备
    MyAdapter myAdapter,myAdapter2;
    BluetoothAdapter adapter;
    //蓝牙权限和网络权限不需要动态获取,但是位置权限需要
    String[] strings=new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION};
    MyRecevier myRecevier;//广播
    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //TODO 1:动态获取权限 安卓6.0
        //TODO 2:功能
        initView();
        //TODO 3:获得本机蓝牙
        BluetoothManager manager= (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);//蓝牙管理者
        adapter = manager.getAdapter();
        //TODO 4:注册广播和解除注册
        myRecevier=new MyRecevier();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//扫描到远程设备
        registerReceiver(myRecevier,intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myRecevier);
    }

    private void initView() {
        bt_close=findViewById(R.id.bt_close);
        bt_open=findViewById(R.id.bt_open);
        bt_scan=findViewById(R.id.bt_scan);
        bt_show=findViewById(R.id.bt_show);
        listView=findViewById(R.id.lv);
        listView2=findViewById(R.id.lv2);
        bt_scan.setOnClickListener(this);
        bt_open.setOnClickListener(this);
        bt_close.setOnClickListener(this);
        bt_show.setOnClickListener(this);
        myAdapter=new MyAdapter(list,this);
        myAdapter2=new MyAdapter(list2,this);
        listView.setAdapter(myAdapter);
        listView2.setAdapter(myAdapter2);
        //点击发起配对
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.KITKAT)
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                list.get(position).createBond();//发起配对请求
            }
        });
        //点击发送数据
        listView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                try {
                    BluetoothSocket bluetoothSocket=list.get(position).createInsecureRfcommSocketToServiceRecord(uuid);
                    bluetoothSocket.connect();
                    //发文字
                    OutputStream outputStream = bluetoothSocket.getOutputStream();
                    String str="d.dgjkfdlkmkgdnhjngf";
                    outputStream.write((str.getBytes().length+" "+"text").getBytes());//长度+类型
                    Thread.sleep(200);
                    outputStream.write(str.getBytes());
                    //发图片
                    //发文件
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_open:
                open();
                break;
            case R.id.bt_close:
                close();
                break;
            case R.id.bt_scan:
                search();
                break;
            case R.id.bt_show:
                show();
                break;
        }
    }
    //获得已经配对的设备
    private void show() {
        list2.clear();
        Set<BluetoothDevice> bondedDevices = adapter.getBondedDevices();//获得已经配对的蓝牙设备
        list2.addAll(bondedDevices);
        myAdapter2.notifyDataSetChanged();

    }

    private void search() {
        list.clear();
        adapter.startDiscovery();//开始扫描
      //  adapter.cancelDiscovery();//停止扫描
    }

    //关闭蓝牙
    private void close() {
        adapter.disable();//关闭蓝牙
    }

    //使用隐士意图打开蓝牙
    public void open(){
        Intent intent = new Intent();
        intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);  //设置蓝牙可用
        intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//设置被扫描
        intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,200);//设置被扫描的时长
        startActivity(intent);
    }
    //TODO 1:广播接收者:接受系统发送的广播,扫描到设备
    class MyRecevier extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals(BluetoothDevice.ACTION_FOUND)){//扫描到一个
                //获得远程蓝牙设备
                BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                //放到listview中
                list.add(device);
                myAdapter.notifyDataSetChanged();
            }
        }
    }

服务端线程

/**
 * 蓝牙serversocket线程
 * */
public class BluetoothThread extends Thread{

    BluetoothAdapter adapter;//本机蓝牙适配器
    UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB");//系统随机产生string字符串35年内不重复->连接蓝牙时秘钥
    String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/xxyy.txt";
    //传递过来的txt文件本地保存路径

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

    @Override
    public void run() {
        super.run();
        try {
            BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord(adapter.getName(),uuid);
            //侦听连接过来的socket
            BluetoothSocket socket = serverSocket.accept();
            Log.e("ZXY","蓝牙连接成功");
            InputStream in = socket.getInputStream();
            //向本地sd卡保存文件的输出流
            FileOutputStream out = new FileOutputStream(path);
            byte[]buff = new byte[1024];
            int leng = 0;
            while ((leng=in.read(buff))!=-1){
                out.write(buff,0,leng);
                Log.e("ZXY","服务器边读边保存");
            }
            out.flush();
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}