蓝牙通信传输,搜索,连接

一、注意事项

      1:android6.0使用蓝牙时,需要开启gps定位权限,不然无法搜索其它蓝牙设备。

二、权限

      1:权限配置

 

<!--允许程序连接到已配对的蓝牙设备-->

<uses-permission android:name="android.permission.BLUETOOTH" />

<!-- 允许程序发现和配对蓝牙设备 -->

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

<!--android 6.0 涉及到的权限-->

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

 

<!-- 在SDCard中创建与删除文件的权限 -->

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<!-- 往SDCard写入数据的权限 -->

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

2:动态权限代码

  由于需要用到存储卡,定位等,android6.0以上需要代码动态设置。

public static final int REQUEST_EXTERNAL_STORAGE = 1001;

 

public static String[] PERMISSIONS_STORAGE = {

Manifest.permission.BLUETOOTH,

Manifest.permission.ACCESS_COARSE_LOCATION,

Manifest.permission.ACCESS_FINE_LOCATION,

Manifest.permission.WRITE_EXTERNAL_STORAGE,

};

/**

* 首先判断当前系统是否是Android6.0(对应API 23)以及以上

* ActivityCompat.requestPermission方法的

* 第一个参数是目标Activity,填写this即可,

* 第二个参数是String[]字符数组类型的权限集,

* 第三个即请求码:

* @param activity

*/

public static void verifyStoragePermissions(Activity activity) {

 

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

 

//检查权限是否被授权 被授权返回值为PERMISSION_GRANTED,否则返回PERMISSION_DENIED

 

if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)

!= PackageManager.PERMISSION_GRANTED) {

//申请权限

ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);

}

}

 

/**

*  * 判断权限集合

*  * permissions 权限数组

*  * return true-表示没有开权限 false-表示权限已开启

*/

public static boolean lacksPermissions(Context mContexts, String[] permissions) {

for (String permission : permissions) {

if (lacksPermission(mContexts,permission)) {

return true;

}

}

return false;

}

 

/**

* 判断是否缺少权限

*/

private static boolean lacksPermission(Context mContexts, String permission) {

return ContextCompat.checkSelfPermission(mContexts, permission) ==

PackageManager.PERMISSION_DENIED;

}

//这块是在调动搜索方法的时候判断权限

if (lacksPermissions(MainActivity.this, PermisionUtils.PERMISSIONS_STORAGE)) {

//申请权限

ActivityCompat.requestPermissions(MainActivity.this, PermisionUtils.PERMISSIONS_STORAGE, PermisionUtils.REQUEST_EXTERNAL_STORAGE);

} else {

if (null != bluemanager) {

//判断蓝牙是否开启

if (!bluemanager.getBlueToothStatus()) {

bluemanager.requestEnableBt();

} else {

//搜索方法

bluemanager.searchDevices();

}

}

}

 

/**

* 申请权限后回调onRequestPermissionResult函数,

* 第一个参数为请求码,

* 第二个参数是刚刚请求的权限集,

* 第三个参数是请求结果,0表示授权成功,-1表示授权失败:

*

* @param requestCode

* @param permissions

* @param grantResults

*/

@Override

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

super.onRequestPermissionsResult(requestCode, permissions, grantResults);

if (requestCode == PermisionUtils.REQUEST_EXTERNAL_STORAGE) {

for (int i = 0; i < permissions.length; i++) {

if (grantResults[i] == 0) {

//授权成功!

} else if (grantResults[i] == -1) {

// verifyStoragePermissions(this);

Toast.makeText(MainActivity.this, "您拒绝了程序需要的权限,无法使用App!!!", Toast.LENGTH_SHORT).show();

}

}

}

}

三、开启蓝牙

// 检查设备是否支持蓝牙      

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();    

if (adapter == null)    

{    

    // 设备不支持蓝牙      

}    

/**

* 当前蓝牙状态

*

* @return true 打开,false 关闭

*/

public boolean getBlueToothStatus() {

assert (mBluetoothAdapter != null);

return mBluetoothAdapter.isEnabled();

}

 

/**

* 开启蓝牙

* mBluetoothAdapter.disable(); // 关闭

*/

public void requestEnableBt() {

if (!mBluetoothAdapter.isEnabled())

//开启蓝牙

mBluetoothAdapter.enable();

}

四、搜索周围的蓝牙设备

适配器搜索蓝牙设备后将结果以广播形式传出去,所以需要自定义一个继承广播的类,在onReceive方法中获得并处理蓝牙设备的搜索结果。

/**

* 注册广播

*/

public void registerBTReceiver() {

// 设置广播信息过滤

IntentFilter intentFilter = new IntentFilter();

// 注册接收查找到设备action接收器

intentFilter.addAction(BluetoothDevice.ACTION_FOUND);

// 注册开始搜索action接收器

intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);

// 注册查找结束action接收器

intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

// 手机蓝牙开启关闭时发送 监听手机本身蓝牙状态的广播

intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);

// 指明一个远程设备的连接状态的 蓝牙设备配对和解除配对时发送

intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

// 注册广播接收器,接收并处理搜索结果

mContext.registerReceiver(BTReceive, intentFilter);

}

 

/**

* 广播接收者

*/

private BroadcastReceiver BTReceive = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

 

switch (action) {

case BluetoothAdapter.ACTION_STATE_CHANGED:

int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);

switch (blueState) {

case BluetoothAdapter.STATE_TURNING_ON:

Log.i(TAG, "onReceive: 蓝牙打开中");

break;

case BluetoothAdapter.STATE_ON:

Log.i(TAG, "onReceive: 蓝牙已打开");

break;

case BluetoothAdapter.STATE_TURNING_OFF:

Log.i(TAG, "onReceive: 蓝牙关闭中");

break;

case BluetoothAdapter.STATE_OFF:

Log.i(TAG, "onReceive已关闭");

break;

}

 

break;

case BluetoothDevice.ACTION_FOUND:

// 获取查找到的蓝牙设备

device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

// 如果查找到的设备符合要连接的设备,处理

if (null != device.getName()) {

if (device.getName().equalsIgnoreCase("HC-06")) {

//获取距离

int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);

DevicesModel devicesModel = new DevicesModel();

devicesModel.setAddress(device.getAddress());

devicesModel.setName(device.getName());

devicesModel.setRssi(rssi);

mBondedList.add(devicesModel);

}

}

 

 

 

break;

case BluetoothDevice.ACTION_BOND_STATE_CHANGED:

//蓝牙设备配对和解除配对时发送

 

/* // 获取蓝牙设备的连接状态

BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

String name = device.getName();

Log.d("aaa", "device name: " + name);

int connectState = device.getBondState();

// 已配对

switch (connectState) {

case BluetoothDevice.BOND_NONE:

 

break;

case BluetoothDevice.BOND_BONDING:

Log.i(TAG, "onReceive: 正在配对");

DevicesModel devicesModel = new DevicesModel();

devicesModel.setName(device.getName());

devicesModel.setAddress(device.getAddress());

mNewList.add(devicesModel);

break;

case BluetoothDevice.BOND_BONDED:

//配对成功可以直接连接

Log.i(TAG, "onReceive: 配对成功");

DevicesModel model = new DevicesModel();

model.setName(device.getName());

model.setAddress(device.getAddress());

mBondedList.add(model);

break;

default:

break;

}*/

break;

case BluetoothAdapter.ACTION_DISCOVERY_STARTED:

if (mOnSearchDeviceListener != null)

mOnSearchDeviceListener.onStartDiscovery();

break;

case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:

 

//搜索完成 选择要连接的设备

mOnSearchDeviceListener.onSearchCompleted(mBondedList);

break;

}

}

};

五、蓝牙连接

/**

* 连接蓝牙服务的线程

*/

private class ConnectDeviceRunnable implements Runnable {

private String mac;

 

public ConnectDeviceRunnable(String mac) {

this.mac = mac;

}

 

@Override

public void run() {

try {

if (onConnectListener == null) {

Log.i(TAG, "the connectListener is null !");

return;

}

// 准备连接设备,关闭服务查找

mBluetoothAdapter.cancelDiscovery();

// 得到蓝牙设备句柄

BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(mac);

Log.d(TAG, "准备连接" + remoteDevice.getAddress() + " " + remoteDevice.getName());

// 用服务号得到socket

try {

mSocket = remoteDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(Constants.STR_UUID));

} catch (IOException e) {

ToestUtil.showToast(mContext, "--连接失败!");

}

//正在连接

onConnectListener.onConnectting();

try {

mSocket.connect();

onConnectListener.onConnectSuccess(remoteDevice.getName());

} catch (IOException e) {

Log.i(TAG, "连接失败!!!!" + e.toString());

return;

}

//打开接收线程

try {

mInputStream = mSocket.getInputStream(); //得到蓝牙数据输入流

} catch (IOException e) {

Log.i(TAG, "接收数据失败!!!" + e.toString());

return;

}

try {

mOutputStream = mSocket.getOutputStream(); //得到蓝牙数据输出流

} catch (IOException e) {

Log.i(TAG, "读取数据失败!!!" + e.toString());

return;

}

} catch (Exception e) {

e.printStackTrace();

//连接失败

onConnectListener.onConnectFailed();

}

}

}

六、读取设备消息

/**

* 读取bluetooth流线程

*/

private class ReadRunnable implements Runnable {

@Override

public void run() {

try {

if (mSocket == null) {

Log.i(TAG, "run: 请先连接蓝牙设备");

return;

}

BufferedReader in = new BufferedReader(new InputStreamReader(

mInputStream));

String line = "";

StringBuffer oneRecord = new StringBuffer();

while ((line = in.readLine()) != null) {

Log.i(TAG, "读取到的每一行 " + line);

if (handler != null) {

Message message = handler.obtainMessage();

message.what = 1;

message.obj = line;

handler.sendMessage(message);

}

}

} catch (Exception e) {

e.printStackTrace();

onReceiveMessageListener.onConnectionLost(e);

}

}

}

//处理ui

private Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

String message = msg.obj.toString();

switch (msg.what) {

case 1:

Log.i(TAG, "读取到的每一行 " + message);

onReceiveMessageListener.readData(message);

break;

}

}

};

 

七、写数据

 

class WriteRunnable implements Runnable {

private String sendContent;

public WriteRunnable(String sendcontent) {

Log.i(TAG, "WriteRunnable: ");

this.sendContent = sendcontent;

}

@Override

public synchronized void run() {

if (mOutputStream != null) {

Log.i(TAG, "run: mOutputStream != null");

BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(mOutputStream));

try {

writer.write(sendContent);

writer.newLine();

writer.flush();

Log.d(TAG, "send string message: " + sendContent);

onSendMessageListener.onSuccess(Constants.STATUS_OK, "send string message is success callback !");

} catch (IOException e) {

Log.i(TAG, "run: 发送异常");

onSendMessageListener.onConnectionLost(e);

}

} else {

Log.i(TAG, "WriteRunnable:mOutputStream == null ");

if (mSocket == null) {

Log.i(TAG, "run: 请先连接蓝牙设备");

return;

}

try {

mOutputStream = mSocket.getOutputStream(); //蓝牙连接输出流

} catch (IOException e) {

Log.i(TAG, "输入流run: ");

}

BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(mOutputStream));

try {

writer.write(sendContent);

writer.newLine();

writer.flush();

Log.d(TAG, "send string message: " + sendContent);

onSendMessageListener.onSuccess(Constants.STATUS_OK, "send string message is success callback !");

} catch (IOException e) {

Log.i(TAG, "run: 发送异常");

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遥不可及zzz

我会用心写更多自己的经验。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值