Android实现蓝牙(BlueTooth)设备检测连接
无论是wifi还是4g网络,建立网络连接后都是访问互联网资源,并不能直接访问局域网资源。比如两个人在一起,a要把手机上的视频传给b,通常情况是打开手机qq,通过qq传送文件给对方。不过上传视频很耗流量,如果现场没有可用的wifi,手机的数据流量又不足,那又该怎么办呢?为了解决这种邻近传输文件的问题,蓝牙技术应运而生。蓝牙技术是一种无线技术标准,可实现设备之间的短距离数据交换。
android为蓝牙技术提供了4个工具类,分别是蓝牙适配器bluetoothadapter、蓝牙设备bluetoothdevice、蓝牙服务端套接字bluetoothserversocket和蓝牙客户端套接字bluetoothsocket。
蓝牙适配器bluetoothadapter
bluetoothadapter的作用其实跟其它的**manger差不多,可以把它当作蓝牙管理器。下面是bluetoothadapter的常用方法说明。
getdefaultadapter:静态方法,获取默认的蓝牙适配器对象;
enable:打开蓝牙功能;
disable:关闭蓝牙功能;
isenable:判断蓝牙功能是否打开;
startdiscovery:开始搜索周围的蓝牙设备;
canceldiscovery:取消搜索操作;
isdiscovering:判断当前是否正在搜索设备;
getbondeddevices:获取已绑定的设备列表;
setname:设置本机的蓝牙名称;
getname:获取本机的蓝牙名称;
getaddress:获取本机的蓝牙地址;
getremotedevice:根据蓝牙地址获取远程的蓝牙设备;
getstate:获取本地蓝牙适配器的状态;
listenusingrfcommwithservicerecord:根据名称和uuid创建并返回bluetoothservicesocket;
listenusingrfcommon:根据渠道编号创建并返回bluetoothservicesocket。
蓝牙设备bluetoothdevice
bluetoothdevice用于指代某个蓝牙设备,通常表示对方设备。bluetoothadapter管理的是本机蓝牙设备。下面是bluetoothdevice的常用方法说明。
- getname:获得该设备的名称;
- getaddress:获得该设备的地址;
- getbondstate:获得该设备的绑定状态;
- createbond:创建匹配对象;
- createrfcommsockettoservicerecord:根据uuid创建并返回一个bluetoothsocket。
蓝牙服务器套接字bluetoothservicesocket
bluetoothservicesocket是服务端的socket,用来接收客户端的socket连接请求。下面是常用的方法说明。
accept:监听外部的蓝牙连接请求;
close:关闭服务端的蓝牙监听。
蓝牙客户端套接字bluetoothsocket
bluetoothsocket是客户端的socket,用于与对方设备进行数据通信。下面是常用的方法说明。
- connect:建立蓝牙的socket连接;
- close:关闭蓝牙的socket连接;
- getinputstream:获取socket连接的输入流对象;
- getoutputstream:获取socket连接的输出流对象;
- getremotedevice:获取远程设备信息。
layout\activity_bluetooth.xml界面布局代码如下:界面布局代码如下:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp"> <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <checkbox android:id="@+id/ck_bluetooth" android:layout_width="wrap_content" android:layout_height="wrap_content" android:button="@null" android:checked="false" android:drawableleft="@drawable/ck_status_selector" android:text="蓝牙" android:textcolor="#ff000000" android:textsize="17sp" /> <textview android:id="@+id/tv_discovery" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="right|center" android:textcolor="#ff000000" android:textsize="17sp" /> </linearlayout> <linearlayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <textview android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="4" android:gravity="center" android:text="名称" android:textcolor="#ff000000" android:textsize="17sp" /> <textview android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="5" android:gravity="center" android:text="地址" android:textcolor="#ff000000" android:textsize="17sp" /> <textview android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:gravity="center" android:text="状态" android:textcolor="#ff000000" android:textsize="17sp" /> </linearlayout> <listview android:id="@+id/lv_bluetooth" android:layout_width="match_parent" android:layout_height="match_parent" /> </linearlayout>
bluetoothactivity.java逻辑代码如下:
package com.fukaimei.bluetoothtest; import java.io.ioexception; import java.lang.reflect.method; import java.util.arraylist; import android.app.alertdialog; import android.bluetooth.bluetoothadapter; import android.bluetooth.bluetoothdevice; import android.bluetooth.bluetoothsocket; import android.content.broadcastreceiver; import android.content.context; import android.content.intent; import android.content.intentfilter; import android.content.pm.packagemanager; import android.os.asynctask; import android.os.bundle; import android.os.handler; import android.os.message; import android.support.annotation.nonnull; import android.support.v4.app.activitycompat; import android.support.v4.content.contextcompat; import android.support.v7.app.appcompatactivity; import android.util.log; import android.view.view; import android.view.view.onclicklistener; import android.widget.adapterview; import android.widget.adapterview.onitemclicklistener; import android.widget.checkbox; import android.widget.compoundbutton; import android.widget.listview; import android.widget.compoundbutton.oncheckedchangelistener; import android.widget.textview; import android.widget.toast; import com.fukaimei.bluetoothtest.adapter.bluelistadapter; import com.fukaimei.bluetoothtest.bean.bluedevice; import com.fukaimei.bluetoothtest.task.blueaccepttask; import com.fukaimei.bluetoothtest.task.blueconnecttask; import com.fukaimei.bluetoothtest.task.bluereceivetask; import com.fukaimei.bluetoothtest.util.bluetoothutil; import com.fukaimei.bluetoothtest.widget.inputdialogfragment; public class bluetoothactivity extends appcompatactivity implements onclicklistener, onitemclicklistener, oncheckedchangelistener, blueconnecttask.blueconnectlistener, inputdialogfragment.inputcallbacks, blueaccepttask.blueacceptlistener { private static final string tag = "bluetoothactivity"; private checkbox ck_bluetooth; private textview tv_discovery; private listview lv_bluetooth; private bluetoothadapter mbluetooth; private arraylist<bluedevice> mdevicelist = new arraylist<bluedevice>(); @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_bluetooth); bluetoothpermissions(); ck_bluetooth = (checkbox) findviewbyid(r.id.ck_bluetooth); tv_discovery = (textview) findviewbyid(r.id.tv_discovery); lv_bluetooth = (listview) findviewbyid(r.id.lv_bluetooth); if (bluetoothutil.getbluetoothstatus(this) == true) { ck_bluetooth.setchecked(true); } ck_bluetooth.setoncheckedchangelistener(this); tv_discovery.setonclicklistener(this); mbluetooth = bluetoothadapter.getdefaultadapter(); if (mbluetooth == null) { toast.maketext(this, "本机未找到蓝牙功能", toast.length_short).show(); finish(); } } // 定义获取基于地理位置的动态权限 private void bluetoothpermissions() { if (contextcompat.checkselfpermission(this, android.manifest.permission.access_coarse_location) != packagemanager.permission_granted) { activitycompat.requestpermissions(this, new string[]{ android.manifest.permission.access_coarse_location}, 1); } } /** * 重写onrequestpermissionsresult方法 * 获取动态权限请求的结果,再开启蓝牙 */ @override public void onrequestpermissionsresult(int requestcode, @nonnull string[] permissions, @nonnull int[] grantresults) { if (requestcode == 1 && grantresults[0] == packagemanager.permission_granted) { if (bluetoothutil.getbluetoothstatus(this) == true) { ck_bluetooth.setchecked(true); } ck_bluetooth.setoncheckedchangelistener(this); tv_discovery.setonclicklistener(this); mbluetooth = bluetoothadapter.getdefaultadapter(); if (mbluetooth == null) { toast.maketext(this, "本机未找到蓝牙功能", toast.length_short).show(); finish(); } } else { toast.maketext(this, "用户拒绝了权限", toast.length_short).show(); } super.onrequestpermissionsresult(requestcode, permissions, grantresults); } @override public void oncheckedchanged(compoundbutton buttonview, boolean ischecked) { if (buttonview.getid() == r.id.ck_bluetooth) { if (ischecked == true) { begindiscovery(); intent intent = new intent(bluetoothadapter.action_request_discoverable); startactivityforresult(intent, 1); // 下面这行代码为服务端需要,客户端不需要 mhandler.postdelayed(maccept, 1000); } else { canceldiscovery(); bluetoothutil.setbluetoothstatus(this, false); mdevicelist.clear(); bluelistadapter adapter = new bluelistadapter(this, mdevicelist); lv_bluetooth.setadapter(adapter); } } } private runnable maccept = new runnable() { @override public void run() { if (mbluetooth.getstate() == bluetoothadapter.state_on) { blueaccepttask accepttask = new blueaccepttask(true); accepttask.setblueacceptlistener(bluetoothactivity.this); accepttask.executeonexecutor(asynctask.thread_pool_executor); } else { mhandler.postdelayed(this, 1000); } } }; @override public void onclick(view v) { if (v.getid() == r.id.tv_discovery) { begindiscovery(); } } @override protected void onactivityresult(int requestcode, int resultcode, intent intent) { super.onactivityresult(requestcode, resultcode, intent); if (requestcode == 1) { if (resultcode == result_ok) { toast.maketext(this, "允许本地蓝牙被附近的其它蓝牙设备发现", toast.length_short).show(); } else if (resultcode == result_canceled) { toast.maketext(this, "不允许蓝牙被附近的其它蓝牙设备发现", toast.length_short).show(); } } } private runnable mrefresh = new runnable() { @override public void run() { begindiscovery(); mhandler.postdelayed(this, 2000); } }; private void begindiscovery() { if (mbluetooth.isdiscovering() != true) { mdevicelist.clear(); bluelistadapter adapter = new bluelistadapter(bluetoothactivity.this, mdevicelist); lv_bluetooth.setadapter(adapter); tv_discovery.settext("正在搜索蓝牙设备"); mbluetooth.startdiscovery(); } } private void canceldiscovery() { mhandler.removecallbacks(mrefresh); tv_discovery.settext("取消搜索蓝牙设备"); if (mbluetooth.isdiscovering() == true) { mbluetooth.canceldiscovery(); } } @override protected void onstart() { super.onstart(); mhandler.postdelayed(mrefresh, 50); bluereceiver = new bluetoothreceiver(); //需要过滤多个动作,则调用intentfilter对象的addaction添加新动作 intentfilter foundfilter = new intentfilter(bluetoothdevice.action_found); foundfilter.addaction(bluetoothadapter.action_discovery_finished); foundfilter.addaction(bluetoothdevice.action_bond_state_changed); registerreceiver(bluereceiver, foundfilter); } @override protected void onstop() { super.onstop(); canceldiscovery(); unregisterreceiver(bluereceiver); } private bluetoothreceiver bluereceiver; private class bluetoothreceiver extends broadcastreceiver { @override public void onreceive(context context, intent intent) { string action = intent.getaction(); log.d(tag, "onreceive action=" + action); // 获得已经搜索到的蓝牙设备 if (action.equals(bluetoothdevice.action_found)) { bluetoothdevice device = intent.getparcelableextra(bluetoothdevice.extra_device); bluedevice item = new bluedevice(device.getname(), device.getaddress(), device.getbondstate() - 10); mdevicelist.add(item); bluelistadapter adapter = new bluelistadapter(bluetoothactivity.this, mdevicelist); lv_bluetooth.setadapter(adapter); lv_bluetooth.setonitemclicklistener(bluetoothactivity.this); } else if (action.equals(bluetoothadapter.action_discovery_finished)) { mhandler.removecallbacks(mrefresh); tv_discovery.settext("蓝牙设备搜索完成"); } else if (action.equals(bluetoothdevice.action_bond_state_changed)) { bluetoothdevice device = intent.getparcelableextra(bluetoothdevice.extra_device); if (device.getbondstate() == bluetoothdevice.bond_bonding) { tv_discovery.settext("正在配对" + device.getname()); } else if (device.getbondstate() == bluetoothdevice.bond_bonded) { tv_discovery.settext("完成配对" + device.getname()); mhandler.postdelayed(mrefresh, 50); } else if (device.getbondstate() == bluetoothdevice.bond_none) { tv_discovery.settext("取消配对" + device.getname()); } } } } @override public void onitemclick(adapterview<?> parent, view view, int position, long id) { canceldiscovery(); bluedevice item = mdevicelist.get(position); bluetoothdevice device = mbluetooth.getremotedevice(item.address); try { if (device.getbondstate() == bluetoothdevice.bond_none) { method createbondmethod = bluetoothdevice.class.getmethod("createbond"); log.d(tag, "开始配对"); boolean result = (boolean) createbondmethod.invoke(device); } else if (device.getbondstate() == bluetoothdevice.bond_bonded && item.state != bluelistadapter.connected) { tv_discovery.settext("开始连接"); blueconnecttask connecttask = new blueconnecttask(item.address); connecttask.setblueconnectlistener(this); connecttask.executeonexecutor(asynctask.thread_pool_executor, device); } else if (device.getbondstate() == bluetoothdevice.bond_bonded && item.state == bluelistadapter.connected) { tv_discovery.settext("正在发送消息"); inputdialogfragment dialog = inputdialogfragment.newinstance( "", 0, "请输入要发送的消息"); string fragtag = getresources().getstring(r.string.app_name); dialog.show(getfragmentmanager(), fragtag); } } catch (exception e) { e.printstacktrace(); tv_discovery.settext("配对异常:" + e.getmessage()); } } //向对方发送消息 @override public void oninput(string title, string message, int type) { log.d(tag, "oninput message=" + message); log.d(tag, "mbluesocket is " + (mbluesocket == null ? "null" : "not null")); bluetoothutil.writeoutputstream(mbluesocket, message); } private bluetoothsocket mbluesocket; //客户端主动连接 @override public void onblueconnect(string address, bluetoothsocket socket) { mbluesocket = socket; tv_discovery.settext("连接成功"); refreshaddress(address); } //刷新已连接的状态 private void refreshaddress(string address) { for (int i = 0; i < mdevicelist.size(); i++) { bluedevice item = mdevicelist.get(i); if (item.address.equals(address) == true) { item.state = bluelistadapter.connected; mdevicelist.set(i, item); } } bluelistadapter adapter = new bluelistadapter(this, mdevicelist); lv_bluetooth.setadapter(adapter); } //服务端侦听到连接 @override public void onblueaccept(bluetoothsocket socket) { log.d(tag, "onblueaccept socket is " + (socket == null ? "null" : "not null")); if (socket != null) { mbluesocket = socket; bluetoothdevice device = mbluesocket.getremotedevice(); refreshaddress(device.getaddress()); bluereceivetask receive = new bluereceivetask(mbluesocket, mhandler); receive.start(); } } //收到对方发来的消息 private handler mhandler = new handler() { @override public void handlemessage(message msg) { if (msg.what == 0) { byte[] readbuf = (byte[]) msg.obj; string readmessage = new string(readbuf, 0, msg.arg1); log.d(tag, "handlemessage readmessage=" + readmessage); alertdialog.builder builder = new alertdialog.builder(bluetoothactivity.this); builder.settitle("我收到消息啦").setmessage(readmessage).setpositivebutton("确定", null); builder.create().show(); } } }; @override protected void ondestroy() { super.ondestroy(); if (mbluesocket != null) { try { mbluesocket.close(); } catch (ioexception e) { e.printstacktrace(); } } } }
添加蓝牙所需的相应权限:
<!-- 蓝牙 --> <uses-permission android:name="android.permission.bluetooth_admin" /> <uses-permission android:name="android.permission.bluetooth" /> <!--基于地理位置--> <uses-permission android:name="android.permission.access_coarse_location" />
demo程序运行效果界面截图如下:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 男性尿路感染 男性尿路感染的症状及危害
推荐阅读
-
Android开发实现实时检测蓝牙连接状态的方法【附源码下载】
-
Android实现蓝牙的搜索,配对(不需要输入PIN,自动匹配),连接,通信
-
Android实现蓝牙(BlueTooth)设备检测连接
-
Android设备蓝牙连接扫描枪获取扫描内容
-
【Android BLE】蓝牙开发「防丢器」的相关知识点(二):连接设备并检测连接状态...
-
搭建直播带货平台,Android蓝牙连接状态检测
-
Android 检测是否连接蓝牙耳机
-
Android移动开发-蓝牙(BlueTooth)设备检测连接的实现
-
Android实现蓝牙的搜索,配对(不需要输入PIN,自动匹配),连接,通信
-
Android开发实现实时检测蓝牙连接状态的方法【附源码下载】