Day6:蓝牙

一.蓝牙介绍:

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

  • 添加权限:
    <!-- 用于进行网络定位 -->
    <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();

二.蓝牙的作用:

在这里插入图片描述在这里插入图片描述

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

在这里插入图片描述

  • 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.客户端:

/**
 * 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();
                    //发文字
               
                    //发图片
                    //发文件
                } 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();
            }
        }
    }

2.服务端线程

/**
 * 蓝牙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();
        }
    }
}

五.Android 蓝牙4.0低功耗(BLE)

Android 4.3(API level 18)引入了蓝牙低功耗(BLE)核心功能,并提供了API可供app来搜索设备,查询服务以及传输信息。

蓝牙低功耗通常用于以下几个方面:

  • 在两个相近的设备之间传输少量数据。
  • 与距离传感器进行交互,比如Google Beacons。这样可以基于当前位置来定制用户个性化体验。

相比经典蓝牙,蓝牙低功耗(BLE)可以显著减少电量消耗。这使得Android应用可以与对电量有着更严格限制的设备通信,比如位置传感器,心率监视器,以及健身设备。

大致流程:

  1. 扫描并与指定的BLE设备进行连接。
  2. 连接成功就能拿到设备的GATT、Service、Characteristic、Descriptor这几个关键的东西(其实能拿到很多东西),并且每个Service、Characteristic都有自己唯一的UUID。
  3. 开启数据通道,这里的一条数据通道就相当于一个Characteristic,而具体开启哪一个或哪几个,需要根据BLE设备的工程师给的协议文档,如果工程师给的文档很坑的话,就要自己调试,判断等。
  4. 手机就可以向BLE设备发送数据或接受BLE向手机发送的数据。
  5. 一般BLE设备向手机发送的数据都16进制的数据报,类似于IP数据报,需要自己解析,具体的解析规则BLE设备的工程师都会给一份协议文档的,看着解析就行了,到这里就完成了与BLE设备的通信了

查看网址 :https://blog.csdn.net/fu908323236/article/details/76208997

1.描BLE设备并对指定设备进行连接

https://blog.csdn.net/fu908323236/article/details/76208997

2.扫描服务

3.开启数据通道(Characteristic)

4.接受数据

5.发送数据

练习手册

技能一:

1.打开蓝牙
2.关闭蓝牙
3.扫描蓝牙
4.配对蓝牙
5.显示已配对蓝牙
6.能够发送数据
7.能够接受数据

技能二:

1.使用蓝牙能够发送文件
2.使用蓝牙能够接受文件
3.发送文件的过程中显示发送进度
4.接受文件的过程中显示接受进度
5.当接受完毕土司接受完毕
6.当发送完毕土司发送完毕

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值