是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换,我们主要掌握这几项技能:
<!-- 用于进行网络定位 --> <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();//强制关闭蓝牙
bluetoothAdapter.startDiscovery();//搜索
bluetoothDevice.createBond();//发起配对
//1.获得客户端Socket BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid); socket.connect(); //2.获得服务端Socket BluetoothServerSocket serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(bluetoothAdapter.getName(),uuid); serverSocket.accpet();
如何区分客户端和服务端?如果设备A连接设备B 那么A就是客户端,B就是服务端。
客户端功能:打开蓝牙/关闭蓝牙/搜索附近蓝牙设备/点击其中一个建立连接
(0)添加权限:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH"/>
(1)MainActivity代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener,MainAdapter.OnItemClick{ private Button mStart,mStop,mSearch; private RecyclerView mRv; private BluetoothManager manager; private BluetoothAdapter bluetoothAdapter; private List<BluetoothDevice>list=new ArrayList<>(); private BluetoothReceiver receiver; private MainAdapter adapter; @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); initBluetooth(); } private void init(){ mStart = findViewById(R.id.startBtn); mStop = findViewById(R.id.stopBtn); mSearch = findViewById(R.id.searchBtn); mRv = findViewById(R.id.rv); mStart.setOnClickListener(this); mStop.setOnClickListener(this); mSearch.setOnClickListener(this); LinearLayoutManager manager = new LinearLayoutManager(this); manager.setOrientation(LinearLayoutManager.VERTICAL); mRv.setLayoutManager(manager); } @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) private void initBluetooth(){ manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); bluetoothAdapter = manager.getAdapter(); if (bluetoothAdapter == null){ Toast.makeText(this,"蓝牙设备故障",Toast.LENGTH_SHORT).show(); return; } receiver = new BluetoothReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_FOUND);// filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); registerReceiver(receiver,filter); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); } @Override public void onClick(View view) { if (R.id.startBtn == view.getId()){ Intent intent = new Intent(); intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE); intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,200); startActivityForResult(intent,100); }else if (R.id.stopBtn == view.getId()){ bluetoothAdapter.disable(); }else if (R.id.searchBtn == view.getId()){ bluetoothAdapter.startDiscovery();//搜索 } } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 100){ if (bluetoothAdapter.isEnabled()){ Toast.makeText(this,"蓝牙启动",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this,"蓝牙未启动",Toast.LENGTH_SHORT).show(); } } } @Override public void OnItem(int index) { //发起绑定->搜索到的蓝牙设备中的一台 BluetoothDevice device = list.get(index); device.createBond(); } private class BluetoothReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { //绑定状态改变;搜索完成;搜索到一台设备 if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)){ //搜索到一台设备广播 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); list.add(device); }else if (intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)){ //搜索完成 //绑定适配器 adapter = new MainAdapter(list); adapter.setClick(MainActivity.this); mRv.setAdapter(adapter); }else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){ //绑定状态改变 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int state = device.getBondState(); if (state == BluetoothDevice.BOND_BONDED){ //发起蓝牙连接线程 new BluetoothThread(device).start(); } } } } }
(2)客户端线程代码
public class BluetoothThread extends Thread { private UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB"); private String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/xxyy.txt"; private BluetoothDevice device; public BluetoothThread(BluetoothDevice device){ this.device = device; } @Override public void run() { super.run(); try { BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid); socket.connect();//建立连接 Log.e("ZXY","客户端建立连接"); FileInputStream inputStream = new FileInputStream(path); OutputStream out = socket.getOutputStream(); byte[]buff = new byte[1024]; int leng = 0; while ((leng=inputStream.read(buff))!=-1){ out.write(buff,0,leng); } out.flush(); out.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
服务端是被连接者,只有打开蓝牙和关闭蓝牙的功能
(0)添加权限:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH"/>
(1)MainActivity代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button mStart,mStop; private BluetoothManager manager;//蓝牙管理器 private BluetoothAdapter bluetoothAdapter;//蓝牙适配器->开关搜索等本机蓝牙操作 private BluetoothReceiver receiver;//蓝牙绑定广播接收器 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); initBluetooth(); } private void init(){ mStart = findViewById(R.id.startBtn); mStop = findViewById(R.id.stopBtn); mStart.setOnClickListener(this); mStop.setOnClickListener(this); } @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) private void initBluetooth(){ manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); bluetoothAdapter = manager.getAdapter();//获取本机蓝牙适配器 if (bluetoothAdapter==null){ //本机无蓝牙硬件模块 Toast.makeText(this,"本机蓝牙设备故障",Toast.LENGTH_SHORT).show(); return; } //蓝牙设备可用 receiver = new BluetoothReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); registerReceiver(receiver,filter); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); } @Override public void onClick(View view) { if (bluetoothAdapter==null) return; if (R.id.startBtn == view.getId()){ // bluetoothAdapter.enable();强制开启->基本无效->手机系统是否允许 //用户手动允许开启蓝牙 //调用系统开关蓝牙弹窗->用户手动允许 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); }else if (R.id.stopBtn == view.getId()){ bluetoothAdapter.disable();//强制关闭蓝牙 } } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode==100){ String msg; //蓝牙是否开启 if (bluetoothAdapter.isEnabled()){ msg = "开启成功"; }else msg = "开启失败"; Toast.makeText(this,msg,Toast.LENGTH_SHORT).show(); } } //注册蓝牙配对广播->通过广播侦听配对状态 private class BluetoothReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { //接收蓝牙配对广播 if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){ //配对过来的蓝牙设备 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int state = device.getBondState();//获取绑定状态 new BluetoothThread(bluetoothAdapter).start(); if (state == BluetoothDevice.BOND_NONE){ //未绑定 Log.e("ZXY","未绑定"); }else if (state == BluetoothDevice.BOND_BONDING){ //绑定中 Log.e("ZXY","绑定中"); }else if (state == BluetoothDevice.BOND_BONDED){ //绑定完成 Log.i("lq","绑定完成"); } } } } }
(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(); } } }