Day6:蓝牙
程序员文章站
2022-07-13 22:30:53
...
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.蓝牙: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();
}
}
}
上一篇: 基于单目视觉的四旋翼定点降落——地标设计与识别算法(四)
下一篇: WPF MVVM模式下动画的实现