赞
踩
最近在做蓝牙签到功能时,了解了蓝牙的一部分知识,虽然不够深入,但是感觉良好,他的整体思路如下:
在指定时间内,打开蓝牙,扫描周边蓝牙信号,如果有指定的蓝牙,则由用户确认连接蓝牙,最终签到成功.
首先,我们先写一个工具类,来判断当前时间是否在指定时间之内:
/**
* 判断时间是否在时间段内
*
* @param date
* 当前时间 yyyy-MM-dd HH:mm:ss
* @param strDateBegin
* 开始时间 00:00:00
* @param strDateEnd
* 结束时间 00:05:00
* @return
*/
public static boolean isInDate(Date date, String strDateBegin,
String strDateEnd) {
//首先,我们使用SimpleDateFormat来设置时间格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strDate = sdf.format(date);
// 截取当前时间时分秒,这里所填写的数字,是将当前时间转换成指定格式后,来截取字符串,数字为截取的范围
int strDateH = Integer.parseInt(strDate.substring(11, 13));
int strDateM = Integer.parseInt(strDate.substring(14, 16));
int strDateS = Integer.parseInt(strDate.substring(17, 19));
// 截取开始时间时分秒,这里截取传入的开始时间
int strDateBeginH = Integer.parseInt(strDateBegin.substring(0, 2));
int strDateBeginM = Integer.parseInt(strDateBegin.substring(3, 5));
int strDateBeginS = Integer.parseInt(strDateBegin.substring(6, 8));
// 截取结束时间时分秒,这里截取传入的结束时间
int strDateEndH = Integer.parseInt(strDateEnd.substring(0, 2));
int strDateEndM = Integer.parseInt(strDateEnd.substring(3, 5));
int strDateEndS = Integer.parseInt(strDateEnd.substring(6, 8));
if ((strDateH >= strDateBeginH && strDateH <= strDateEndH)) {
// 当前时间小时数在开始时间和结束时间小时数之间
if (strDateH > strDateBeginH && strDateH < strDateEndH) {
return true;
// 当前时间小时数等于开始时间小时数,分钟数在开始和结束之间
} else if (strDateH == strDateBeginH && strDateM >= strDateBeginM
&& strDateM <= strDateEndM) {
return true;
// 当前时间小时数等于开始时间小时数,分钟数等于开始时间分钟数,秒数在开始和结束之间
} else if (strDateH == strDateBeginH && strDateM == strDateBeginM
&& strDateS >= strDateBeginS && strDateS <= strDateEndS) {
return true;
}
// 当前时间小时数大等于开始时间小时数,等于结束时间小时数,分钟数小等于结束时间分钟数
else if (strDateH >= strDateBeginH && strDateH == strDateEndH
&& strDateM <= strDateEndM) {
return true;
// 当前时间小时数大等于开始时间小时数,等于结束时间小时数,分钟数等于结束时间分钟数,秒数小等于结束时间秒数
} else if (strDateH >= strDateBeginH && strDateH == strDateEndH
&& strDateM == strDateEndM && strDateS <= strDateEndS) {
return true;
} else {
return false;
}
} else {
return false;
}
}
判断时间结束后,我们来看看怎么连接和扫描蓝牙的,至于布局文件,这里就不说了,只有两个控件而已.
第一步:我们获取蓝牙适配器,来检测当前手机是否支持蓝牙:
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter ==null){
//不支持蓝牙
Toast.makeText(this, "该设备不支持蓝牙", Toast.LENGTH_SHORT).show();
}
如果蓝牙适配器为空的话,说明自手机不支持蓝牙,如果不为空的话,我们获取他曾经连接过得蓝牙设备信息.
else {
// 获取所有已经绑定的蓝牙设备
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
//遍历已绑定设备
if (devices.size() > 0) {
for (BluetoothDevice bluetoothDevice : devices) {
tvDevices.append(bluetoothDevice.getName() + ":"
+ bluetoothDevice.getAddress() + "\n\n");
}
}
这里的广播是查找蓝牙,查找完毕,和蓝牙连接状态发生改变时用于接受状态.
//蓝牙查询,可以在reciever中接受查询到的蓝牙设备
IntentFilter mFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, mFilter);
// 注册搜索完时的receiver
mFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, mFilter);
//蓝牙连接状态发生改变时,接收状态
mFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(mReceiver,mFilter);
}
广播注册完成了,那么接收呢?需要创建广播接受者:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// 获得已经搜索到的蓝牙设备
if (action.equals(BluetoothDevice.ACTION_FOUND)) {
//通过此方法获取搜索到的蓝牙设备
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 获取搜索到的蓝牙绑定状态,看看是否是已经绑定过的蓝牙
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 如果没有绑定过则将蓝牙名称和地址显示在TextView上
tvDevices.append(device.getName() + ":"
+ device.getAddress() + "\n");
//78:02:F8:D0:C0:D1
//如果指定地址的蓝牙和搜索到的蓝牙相同,则我们停止扫描
if ("38:A4:ED:77:A2:8C".equals(device.getAddress())) {
mBluetoothAdapter.cancelDiscovery();//这句话是停止扫描蓝牙
//根据蓝牙地址创建蓝牙对象
BluetoothDevice btDev = mBluetoothAdapter.getRemoteDevice(device.getAddress());
//通过反射来配对对应的蓝牙
try {
//这里是调用的方法,此方法使用反射,后面解释
createBond(btDev.getClass(), btDev);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 搜索完成
} else if (action
.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
setTitle("搜索蓝牙设备");
}else if(action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
//获取发生改变的蓝牙对象
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//根据不同的状态显示提示
switch (device.getBondState()) {
case BluetoothDevice.BOND_BONDING://正在配对
Log.d("yxs", "正在配对......");
break;
case BluetoothDevice.BOND_BONDED://配对结束
Log.d("yxs", "完成配对");
Toast.makeText(context, "签到成功", Toast.LENGTH_SHORT).show();
handler.sendEmptyMessageDelayed(1,2000);
break;
case BluetoothDevice.BOND_NONE://取消配对/未配对
Log.d("yxs", "取消配对");
default:
break;
}
}
}
};
上面有提到是用反射来连接蓝牙:这里贴一下代码,此代码为百度所得,懂得他是什么意思,但是反射我不太懂,就不说什么了.
/**
* 蓝牙配对
*
* @param btClass
* @param btDevice
* @return
* @throws Exception
*/
public boolean createBond(Class btClass, BluetoothDevice btDevice) throws Exception {
Method createBondMethod = btClass.getMethod("createBond");//获取蓝牙的连接方法
Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
return returnValue.booleanValue();//返回连接状态
}
咱们获取了扫描的数据,也连接了蓝牙,但是,怎么开启扫描的呢?在扫描之前我们是否还要判断此时蓝牙是否已经打开了呢?
在一开始,我们已经知道了当前手机是否支持蓝牙.那么,在开启扫描时,我们来判断蓝牙是否开起来了:
/**
* 判断是否支持蓝牙,并打开蓝牙
* 获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。
* 如果没打开,需要让用户打开蓝牙:
*/
public void checkBleDevice(Context context) {
//通过适配器对象调用isEnabled()方法,判断蓝牙是否打开了
if (mBluetoothAdapter.isEnabled()) {
//如果蓝牙已经打开,判断此时蓝牙是否正在扫描,如果正在扫描,则先停止当前扫描,然后在重新扫描
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// 开始搜索蓝牙设备,搜索到的蓝牙设备通过广播返回
mBluetoothAdapter.startDiscovery();
}else{
//如果没有开启蓝牙,调用系统方法,让用户确认开启蓝牙
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(enableBtIntent);
}
}
这是用户知晓的情况下,当用户没有手动去扫描蓝牙,但是此时已经到了签到时间,我们就会用到之前判断当前时间是否在指定时间之内的方法,
/**
* 判断是否到了指定时间,打开蓝牙,扫描指定设备
*/
public void currentTime(){
if(TimeUtils.isCurrentInTimeScope(13,33,13,50)){
//如果时间已经到了,则默认自动打开蓝牙,且使用handler发出一条通知,
mBluetoothAdapter.enable();
handler.sendEmptyMessageDelayed(0,2000);
}else{
//如果没有到指定时间,我们也发出一条通知,
handler.sendEmptyMessageDelayed(2,1000);
}
}
上面通过时间判断开启蓝牙发出消息,那么,我们要做什么呢,这要看你自己了,我是这么干的:,1.当时间到了之后,我接受到消息,此时自动调用checkBleDevice方法扫描蓝牙,2.如果么有到指定时间,我会依旧发出一条消息,在对应消息处理中,调用currentTime方法,判断当前时间,在currentTime方法中,无论到没到指定时间,都会发出一条消息,会继续在1和2中继续判断,循环往复,直到时间到了。
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == 0){
checkBleDevice(MainActivity.this);
}else if(msg.what ==1){
BluetoothDevice btDev = mBluetoothAdapter.getRemoteDevice("38:A4:ED:77:A2:8C");
try {
removeBond(btDev.getClass(),btDev);
} catch (Exception e) {
e.printStackTrace();
}
}else if(msg.what == 2){
Toast.makeText(MainActivity.this, "检查状态", Toast.LENGTH_SHORT).show();
handler.sendEmptyMessageDelayed(3,60000);
}else if(msg.what == 3){
currentTime();
}
}
};
因为,蓝牙连接成功后会记住,所以签到成功后,我会移除指定的已配对的蓝牙设备,通过调用另一个使用反射完成方法”:
/**
* 删除指定的已配对设备
* @param btClass
* @param btDevice
* @return
* @throws Exception
*/
public boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {
Method removeBondMethod = btClass.getMethod("removeBond");//获取移除蓝牙设备的方法
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);//得到操作结果
return returnValue.booleanValue();
}
最后由于我们注册了广播,所以,在页面销毁时,我们要解除注册:
@Override
protected void onDestroy() {
super.onDestroy();
//解除注册
unregisterReceiver(mReceiver);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。