android pin码 经典蓝牙_Android蓝牙开发—经典蓝牙详细开发流程

本文详细介绍了Android经典蓝牙的开发流程,包括开启蓝牙、扫描蓝牙、配对蓝牙、连接蓝牙和通信等步骤,并提供了相关代码示例。文章还强调了经典蓝牙与BLE蓝牙的区别,并提到了权限管理和GPS开启的重要性。
摘要由CSDN通过智能技术生成

Android蓝牙开发—经典蓝牙详细开发流程

发布时间:2018-07-16 13:41,

浏览次数:637

, 标签:

Android

Android蓝牙开发前,首先要区分是经典蓝牙开发还是BLE(低功耗)蓝牙开发,它们的开发是有区别的,如果还分不清经典蓝牙和BLE(低功耗)蓝牙的小伙伴,可以先看

Android蓝牙开发—经典蓝牙和BLE(低功耗)蓝牙的区别

本文是针对经典蓝牙开发的,如果是BLE(低功耗)蓝牙开发,可以看Android蓝牙开发—BLE(低功耗)蓝牙详细开发流程

开发流程

* 开启蓝牙

* 扫描蓝牙

* 配对蓝牙

* 连接蓝牙

* 通信

开启蓝牙

1.获取BluetoothAdapter对象

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

2.判断设备是否支持蓝牙

/** * 设备是否支持蓝牙 true为支持 * @return */ public boolean isSupportBlue(){ return

mBluetoothAdapter != null; }

3.判断蓝牙是否开启

/** * 蓝牙是否打开 true为打开 * @return */ public boolean isBlueEnable(){ return

isSupportBlue() && mBluetoothAdapter.isEnabled(); }

4.开启蓝牙

* 异步自动开启蓝牙 /** * 自动打开蓝牙(异步:蓝牙不会立刻就处于开启状态) * 这个方法打开蓝牙不会弹出提示 */ public void

openBlueAsyn(){ if (isSupportBlue()) { mBluetoothAdapter.enable(); } }

* 同步提示开启蓝牙 /** * 自动打开蓝牙(同步) * 这个方法打开蓝牙会弹出提示 * 需要在onActivityResult

方法中判断resultCode == RESULT_OK true为成功 */ public void openBlueSync(Activity

activity, int requestCode){ Intent intent = new

Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

activity.startActivityForResult(intent, requestCode); }

5.权限处理

* 处理6.0以下版本的权限

在AndroidManifest里面添加权限

/>

android:name="android.permission.BLUETOOTH_ADMIN" />

* 处理6.0以上版本的权限

(1)在AndroidManifest里面添加权限

/>

android:name="android.permission.BLUETOOTH_ADMIN" />

android:name="android.permission.ACCESS_FINE_LOCATION" />

(2)动态检查权限

/** * 检查权限 */ private void checkPermissions() { String[] permissions =

{Manifest.permission.ACCESS_FINE_LOCATION}; List permissionDeniedList =

new ArrayList<>(); for (String permission : permissions) { int permissionCheck

= ContextCompat.checkSelfPermission(this, permission); if (permissionCheck ==

PackageManager.PERMISSION_GRANTED) { onPermissionGranted(permission); } else {

permissionDeniedList.add(permission); } } if (!permissionDeniedList.isEmpty())

{ String[] deniedPermissions = permissionDeniedList.toArray(new

String[permissionDeniedList.size()]); ActivityCompat.requestPermissions(this,

deniedPermissions, REQUEST_CODE_PERMISSION_LOCATION); } } /** * 权限回调 * @param

requestCode * @param permissions * @param grantResults */ @Override public

final void onRequestPermissionsResult(int requestCode, @NonNull String[]

permissions, @NonNull int[] grantResults) {

super.onRequestPermissionsResult(requestCode, permissions, grantResults);

switch (requestCode) { case REQUEST_CODE_PERMISSION_LOCATION: if

(grantResults.length > 0) { for (int i = 0; i < grantResults.length; i++) { if

(grantResults[i] == PackageManager.PERMISSION_GRANTED) {

onPermissionGranted(permissions[i]); } } } break; } }

(3)开启GPS

/** * 开启GPS * @param permission */ private void onPermissionGranted(String

permission) { switch (permission) { case

Manifest.permission.ACCESS_FINE_LOCATION: if (Build.VERSION.SDK_INT >=

Build.VERSION_CODES.M && !checkGPSIsOpen()) { new AlertDialog.Builder(this)

.setTitle("提示") .setMessage("当前手机扫描蓝牙需要打开定位功能。") .setNegativeButton("取消", new

DialogInterface.OnClickListener() { @Override public void

onClick(DialogInterface dialog, int which) { finish(); } })

.setPositiveButton("前往设置", new DialogInterface.OnClickListener() { @Override

public void onClick(DialogInterface dialog, int which) { Intent intent = new

Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);

startActivityForResult(intent, REQUEST_CODE_OPEN_GPS); } })

.setCancelable(false) .show(); } else { //GPS已经开启了 } break; } }

(4)检查GPS是否开启

/** * 检查GPS是否打开 * @return */ private boolean checkGPSIsOpen() {

LocationManager locationManager = (LocationManager)

this.getSystemService(Context.LOCATION_SERVICE); if (locationManager == null)

return false; return

locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);

}

扫描蓝牙

1.扫描周围蓝牙设备(配对上的设备有可能扫描不出来)

/** * 扫描的方法 返回true 扫描成功 * 通过接收广播获取扫描到的设备 * @return */ public boolean

scanBlue(){ if (!isBlueEnable()){ Log.e(TAG, "Bluetooth not enable!"); return

false; } //当前是否在扫描,如果是就取消当前的扫描,重新扫描 if (mBluetoothAdapter.isDiscovering()){

mBluetoothAdapter.cancelDiscovery(); } //此方法是个异步操作,一般搜索12秒 return

mBluetoothAdapter.startDiscovery(); }

2.取消扫描蓝牙

/** * 取消扫描蓝牙 * @return true 为取消成功 */ public boolean cancelScanBule(){ if

(isSupportBlue()){ return mBluetoothAdapter.cancelDiscovery(); } return true; }

3.通过广播的方式接收扫描结果

(1)注册广播

IntentFilter filter1 = new

IntentFilter(android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED);

IntentFilter filter2 = new

IntentFilter(android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

IntentFilter filter3 = new IntentFilter(BluetoothDevice.ACTION_FOUND);

registerReceiver(scanBlueReceiver,filter1);

registerReceiver(scanBlueReceiver,filter2);

registerReceiver(scanBlueReceiver,filter3);

(2)接收广播

/** *扫描广播接收类 * Created by zqf on 2018/7/6. */ public class ScanBlueReceiver

extends BroadcastReceiver { private static final String TAG =

ScanBlueReceiver.class.getName(); private ScanBlueCallBack callBack; public

ScanBlueReceiver(ScanBlueCallBack callBack){ this.callBack = callBack; }

//广播接收器,当远程蓝牙设备被发现时,回调函数onReceiver()会被执行 @Override public void

onReceive(Context context, Intent intent) { String action = intent.getAction();

Log.d(TAG, "action:" + action); BluetoothDevice device =

intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); switch (action){ case

BluetoothAdapter.ACTION_DISCOVERY_STARTED: Log.d(TAG, "开始扫描...");

callBack.onScanStarted(); break; case

BluetoothAdapter.ACTION_DISCOVERY_FINISHED: Log.d(TAG, "结束扫描...");

callBack.onScanFinished(); break; case BluetoothDevice.ACTION_FOUND: Log.d(TAG,

"发现设备..."); callBack.onScanning(device); break; } } }

配对蓝牙

1.开始配对

/** * 配对(配对成功与失败通过广播返回) * @param device */ public void pin(BluetoothDevice

device){ if (device == null){ Log.e(TAG, "bond device null"); return; } if

(!isBlueEnable()){ Log.e(TAG, "Bluetooth not enable!"); return; } //配对之前把扫描关闭

if (mBluetoothAdapter.isDiscovering()){ mBluetoothAdapter.cancelDiscovery(); }

//判断设备是否配对,没有配对在配,配对了就不需要配了 if (device.getBondState() ==

BluetoothDevice.BOND_NONE) { Log.d(TAG, "attemp to bond:" + device.getName());

try { Method createBondMethod = device.getClass().getMethod("createBond");

Boolean returnValue = (Boolean) createBondMethod.invoke(device);

returnValue.booleanValue(); } catch (Exception e) { // TODO Auto-generated

catch block e.printStackTrace(); Log.e(TAG, "attemp to bond fail!"); } } }

2.取消配对

/** * 取消配对(取消配对成功与失败通过广播返回 也就是配对失败) * @param device */ public void

cancelPinBule(BluetoothDevice device){ if (device == null){ Log.d(TAG, "cancel

bond device null"); return; } if (!isBlueEnable()){ Log.e(TAG, "Bluetooth not

enable!"); return; } //判断设备是否配对,没有配对就不用取消了 if (device.getBondState() !=

BluetoothDevice.BOND_NONE) { Log.d(TAG, "attemp to cancel bond:" +

device.getName()); try { Method removeBondMethod =

device.getClass().getMethod("removeBond"); Boolean returnValue = (Boolean)

removeBondMethod.invoke(device); returnValue.booleanValue(); } catch (Exception

e) { // TODO Auto-generated catch block e.printStackTrace(); Log.e(TAG, "attemp

to cancel bond fail!"); } } }

3.通过广播的方式接收配对结果

(1)注册广播

IntentFilter filter4 = new

IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST); IntentFilter filter5 =

new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

registerReceiver(pinBlueReceiver,filter4);

registerReceiver(pinBlueReceiver,filter5);

(2)接收广播

/**配对广播接收类 * Created by zqf on 2018/7/7. */ public class PinBlueReceiver

extends BroadcastReceiver { private String pin = "0000";

//此处为你要连接的蓝牙设备的初始密钥,一般为1234或0000 private static final String TAG =

PinBlueReceiver.class.getName(); private PinBlueCallBack callBack; public

PinBlueReceiver(PinBlueCallBack callBack){ this.callBack = callBack; }

//广播接收器,当远程蓝牙设备被发现时,回调函数onReceiver()会被执行 @Override public void

onReceive(Context context, Intent intent) { String action = intent.getAction();

Log.d(TAG, "action:" + action); BluetoothDevice device =

intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if

(BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)){ try {

callBack.onBondRequest(); //1.确认配对 //

ClsUtils.setPairingConfirmation(device.getClass(), device, true); Method

setPairingConfirmation =

device.getClass().getDeclaredMethod("setPairingConfirmation",boolean.class);

setPairingConfirmation.invoke(device,true); //2.终止有序广播 Log.d("order...",

"isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast());

abortBroadcast();//如果没有将广播终止,则会出现一个一闪而过的配对框。 //3.调用setPin方法进行配对... // boolean

ret = ClsUtils.setPin(device.getClass(), device, pin); Method removeBondMethod

= device.getClass().getDeclaredMethod("setPin", new Class[]{byte[].class});

Boolean returnValue = (Boolean) removeBondMethod.invoke(device, new

Object[]{pin.getBytes()}); } catch (Exception e) { // TODO Auto-generated catch

block e.printStackTrace(); } }else if

(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)){ switch

(device.getBondState()) { case BluetoothDevice.BOND_NONE: Log.d(TAG, "取消配对");

callBack.onBondFail(device); break; case BluetoothDevice.BOND_BONDING:

Log.d(TAG, "配对中"); callBack.onBonding(device); break; case

BluetoothDevice.BOND_BONDED: Log.d(TAG, "配对成功");

callBack.onBondSuccess(device); break; } } } }

连接蓝牙

经典蓝牙连接相当于socket连接,是个非常耗时的操作,所以应该放到子线程中去完成。

1.连接线程

/**连接线程 * Created by zqf on 2018/7/7. */ public class ConnectBlueTask extends

AsyncTask { private static final

String TAG = ConnectBlueTask.class.getName(); private BluetoothDevice

bluetoothDevice; private ConnectBlueCallBack callBack; public

ConnectBlueTask(ConnectBlueCallBack callBack){ this.callBack = callBack; }

@Override protected BluetoothSocket doInBackground(BluetoothDevice...

bluetoothDevices) { bluetoothDevice = bluetoothDevices[0]; BluetoothSocket

socket = null; try{ Log.d(TAG,"开始连接socket,uuid:" + ClassicsBluetooth.UUID);

socket =

bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(ClassicsBluetooth.UUID));

if (socket != null && !socket.isConnected()){ socket.connect(); } }catch

(IOException e){ Log.e(TAG,"socket连接失败"); try { socket.close(); } catch

(IOException e1) { e1.printStackTrace(); Log.e(TAG,"socket关闭失败"); } } return

socket; } @Override protected void onPreExecute() { Log.d(TAG,"开始连接"); if

(callBack != null) callBack.onStartConnect(); } @Override protected void

onPostExecute(BluetoothSocket bluetoothSocket) { if (bluetoothSocket != null &&

bluetoothSocket.isConnected()){ Log.d(TAG,"连接成功"); if (callBack != null)

callBack.onConnectSuccess(bluetoothDevice, bluetoothSocket); }else {

Log.d(TAG,"连接失败"); if (callBack != null)

callBack.onConnectFail(bluetoothDevice, "连接失败"); } } }

2.启动连接线程

/** * 连接 (在配对之后调用) * @param device */ public void connect(BluetoothDevice

device, ConnectBlueCallBack callBack){ if (device == null){ Log.d(TAG, "bond

device null"); return; } if (!isBlueEnable()){ Log.e(TAG, "Bluetooth not

enable!"); return; } //连接之前把扫描关闭 if (mBluetoothAdapter.isDiscovering()){

mBluetoothAdapter.cancelDiscovery(); } new

ConnectBlueTask(callBack).execute(device); }

3.判断是否连接成功

/** * 蓝牙是否连接 * @return */ public boolean isConnectBlue(){ return

mBluetoothSocket != null && mBluetoothSocket.isConnected(); }

4.断开连接

/** * 断开连接 * @return */ public boolean cancelConnect(){ if (mBluetoothSocket

!= null && mBluetoothSocket.isConnected()){ try { mBluetoothSocket.close(); }

catch (IOException e) { e.printStackTrace(); return false; } } mBluetoothSocket

= null; return true; }

5.MAC地址连接

/** * 输入mac地址进行自动配对 * 前提是系统保存了该地址的对象 * @param address * @param callBack */

public void connectMAC(String address, ConnectBlueCallBack callBack) { if

(!isBlueEnable()){ return ; } BluetoothDevice btDev =

mBluetoothAdapter.getRemoteDevice(address); connect(btDev, callBack); }

通信

1.读取数据线程

/**读取线程 * Created by zqf on 2018/7/7. */ public class ReadTask extends

AsyncTask { private static final String TAG =

ReadTask.class.getName(); private ReadCallBack callBack; private

BluetoothSocket socket; public ReadTask(ReadCallBack callBack, BluetoothSocket

socket){ this.callBack = callBack; this.socket = socket; } @Override protected

String doInBackground(String... strings) { BufferedInputStream in = null; try {

StringBuffer sb = new StringBuffer(); in = new

BufferedInputStream(socket.getInputStream()); int length = 0; byte[] buf = new

byte[1024]; while ((length = in.read()) != -1) { sb.append(new

String(buf,0,length)); } return sb.toString(); } catch (IOException e) {

e.printStackTrace(); }finally { try { in.close(); } catch (IOException e) {

e.printStackTrace(); } } return "读取失败"; } @Override protected void

onPreExecute() { Log.d(TAG,"开始读取数据"); if (callBack != null)

callBack.onStarted(); } @Override protected void onPostExecute(String s) {

Log.d(TAG,"完成读取数据"); if (callBack != null){ if ("读取失败".equals(s)){

callBack.onFinished(false, s); }else { callBack.onFinished(true, s); } } } }

2.写入数据线程

/**写入线程 * Created by zqf on 2018/7/7. */ public class WriteTask extends

AsyncTask{ private static final String TAG =

WriteTask.class.getName(); private WriteCallBack callBack; private

BluetoothSocket socket; public WriteTask(WriteCallBack callBack,

BluetoothSocket socket){ this.callBack = callBack; this.socket = socket; }

@Override protected String doInBackground(String... strings) { String string =

strings[0]; OutputStream outputStream = null; try{ outputStream =

socket.getOutputStream(); outputStream.write(string.getBytes()); } catch

(IOException e) { Log.e("error", "ON RESUME: Exception during write.", e);

return "发送失败"; }finally { try { outputStream.close(); } catch (IOException e) {

e.printStackTrace(); } } return "发送成功"; } @Override protected void

onPreExecute() { if (callBack != null) callBack.onStarted(); } @Override

protected void onPostExecute(String s) { if (callBack != null){ if

("发送成功".equals(s)){ callBack.onFinished(true, s); }else {

callBack.onFinished(false, s); } } } }

以上就是经典蓝牙的开发流程和部分代码,后期会提供demo下载。若有不当之处,请留言讨论,一起学习进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值