一:概要: 

 Android提供了Buletooth的API ,通过API 我们可以进行如下的一些操作:

    1.扫描其他的蓝牙设备

    2.查询能配对的蓝牙设备

    3.建立RFCOMM 通道

    4.连接其他的蓝牙设备

    5.传输数据

    6.管理多个连接

  学习和使用蓝牙应该以这样的步骤: 配置蓝牙权限---->设置本机蓝牙适配器---->发现蓝牙设备----->进行配对,连接------>利用Socket进行通信

  需要熟悉的一些类:如图

    

二详细步骤:

  1.设置蓝牙权限

    为了能够使用蓝牙的功能必须在清单文件中进行权限的声明:(必须至少声明以下权限中 的一个)

        BULETOOTH/BULETOOTH_ADMIN:

<uses-permission android:name="android.permission.BLUETOOTH" />//允许应用程序连接到已配对的蓝牙设备(远端蓝牙,非本机蓝牙)
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />//允许应用程序搜索并且配对蓝牙设备。
注意:在使用BULETOOTH_ADMIN权限时必须配置BULETOOTH的权限

  2.配置本机的蓝牙模块

     在这里需要掌握 BuletoothAdapter的类:

     在使用蓝牙的功能时必须先检查本机的设备是否有蓝牙的功能,如果不支持那么白搭,如果支持就要检查蓝牙功能是否激活,如果没激活我们要提醒用户开启蓝牙功能

     那么此时就需要BuletoothAdapter的相关方法。

  step 1: 检查是否支持蓝牙  

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//getDefaultAdapter是一个static的方法,可以直接类名调用
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}//==null,表示该设备并不支持蓝牙

  step2: 判断是否激活蓝牙

  

if (!mBluetoothAdapter.isEnabled()) {  

Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
如果没有激活,那么启动服务进行激活,此时会弹出下面的图片:

另外: 我们还可以对蓝牙的状态改变进行监听,当用户的蓝牙状态改变时会发送一条广播告诉系统自己的状态发生了改变:

   listen ACTION_STATE_CHANGED broadcast Intent, which the system will broadcast whenever the Bluetooth state has changed.

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
//直接打开系统的蓝牙设置面板
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 0x1);
//直接打开蓝牙
adapter.enable();
//关闭蓝牙
adapter.disable();
//打开本机的蓝牙发现功能(默认打开120秒,可以将时间最多延长至300秒)
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置持续时间(最多300秒)Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

  3.搜索蓝牙设备

    调用startDiscovery()来发现蓝牙设备:startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。

    该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。

    

    注册监听:
      在执行Discovery的方法时,系统会发出三个广播:开始搜素,结束搜素和找到设备。对这些广播进行监听可以实现一些功能。

    一般监听较多的是找到了设备:

    ACTION_FOUND:找到设备,这个Intent中包含两个extra fields:EXTRA_DEVICE和EXTRA_CLASS,分别包含BluetooDevice和BluetoothClass。

  接下来看一个例子:监听当发现了一个设备的时候进行某些动作:  

      

// 创建一个接收ACTION_FOUND广播的BroadcastReceiver
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// 发现设备
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// 从Intent中获取设备对象
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 将设备名称和地址放入array adapter,以便在ListView中显示
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// 注册BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // 不要忘了之后解除绑定

Caution: Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources. Once you have found a device to connect, be certain that you always stop discovery with cancelDiscovery() before attempting a connection. Also, if you already hold a connection with a device, then performing discovery can significantly reduce the bandwidth available for the connection, so you should not perform discovery while connected.

   注意:为了节省资源,当找到了要连接的设备务必取消查找。调用cancelDiscovery()

        

  当然,我们还可以调用一些方法使得自己的蓝牙设备能够被其他设备发现:代码如下

  Intent discoverableIntent = newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
  discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
  startActivity(discoverableIntent);

  此时,系统会弹出下面的对话框供用户进行选择:

    

  4.连接设备,并用Socket通信

  欲建立连接必须同时实现客户端和服务器端的socket。因为一个手机终端其实即扮演者服务器端的角色也扮演着客户端的角色,涉及到了收发数据。

  当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。注意了解RFCOMM。

  服务器设备与客户端设备获取BluetoothSocket的途径是不同的。服务器设备是通过accepted一个incoming connection来获取的,而客户端设备则是通过打开一个到服务       器的RFCOMM channel来获取的。

  作为一个server:

    基本步骤:

      1.获得serversocket对象:

      2.开启accept:

      3.close():

    实现代码如下:

        

private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket; public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
        //step 1:获得serverSocket对象,
} catch (IOException e) { }
mmServerSocket = tmp;
} public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
          //step:建立连接获得socket对象
          //注意:在调用accept方法后就建立的连接不需要再调用connect的方法了
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
            //注意这个方法,应用程序将启动传输数据的线程
mmServerSocket.close();
          //step3 :用完资源关闭
break;
}
}
} /** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}

  作为一个client:

      实现步骤:

        step 1 :获取一个socket对象

        step 2 :发起连接,调用connect();

         step 3:使用完关闭资源.close()

        注意:在发起连接的时候,保证设备已经停止了discovery(),因为该操作会占用系统很多资源

        

      实现代码:

          

private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device; // Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
} public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery(); try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
} // Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
} /** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}

  5.管理蓝牙连接,进行数据的通信

    当获得了连接之后,我们便可以开始传输数据,传输数据的一般步骤如下:

    step 1 :打开输入输出流:InputStream -->getInputStream() . OutputStream --->getOutputStream().

    step 2 : 通过字节流来读取/写入数据:调用write(byte[])/read(byte[]).

     注意:建立专用的线程进行数据的读写操作,以防堵塞。相对于write操作,read更容易堵塞。

    

    实现代码

    

private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null; // Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { } mmInStream = tmpIn;
mmOutStream = tmpOut;
} public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
} /* Call this from the main Activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
} /* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}

  

Android 之Buletooth的更多相关文章

  1. 〖Android〗(how-to) fix k860/k860i buletooth.

    bluedroid.so for k860/k860i 1./media/Enjoy/AndroidCode/cm10.1/device/lenovo/stuttgart/bluetooth/blue ...

  2. Android开发之蓝牙--扫描已经配对的蓝牙设备

    一. 什么是蓝牙(Bluetooth)? 1.1  BuleTooth是目前使用最广泛的无线通信协议 1.2  主要针对短距离设备通讯(10m) 1.3  常用于连接耳机,鼠标和移动通讯设备等. 二. ...

  3. Android手机一键Root原理分析

    图/文 非虫 一直以来,刷机与Root是Android手机爱好者最热衷的事情.即使国行手机的用户也不惜冒着失去保修的风险对Root手机乐此不疲.就在前天晚上,一年一度的Google I/O大会拉开了帷 ...

  4. 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程

    原文网址:http://blog.sina.com.cn/s/blog_602c72c50102uzoj.html 关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP ...

  5. android PakageManagerService启动流程分析

    PakageManagerService的启动流程图 1.PakageManagerService概述 PakageManagerService是android系统中一个核心的服务,它负责系统中Pac ...

  6. Android Bluetooth模块学习笔记

    一.蓝牙基础知识 1.蓝牙( Bluetooth )是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据交换.蓝牙基于设备低成本的收发器芯片,传输距离近.低功耗. 2.微波频段: ...

  7. Android权限注解

    Android应用程序在使用很多功能的时候必须在Mainifest.xml中声明所需的权限,否则无法运行.下面是一个Mainifest.xml文件的例子: <?xml version=" ...

  8. Android开发之蓝牙(Bluetooth)操作(一)--扫描已经配对的蓝牙设备

    版权声明:本文为博主原创文章,未经博主允许不得转载. 一. 什么是蓝牙(Bluetooth)? 1.1  BuleTooth是目前使用最广泛的无线通信协议 1.2  主要针对短距离设备通讯(10m) ...

  9. Android bluetooth介绍(两): android 蓝牙源架构和uart 至rfcomm过程

    关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP RFCOMM  版本号:基于android4.2先前版本 bluez内核:linux/linux3.08系统:an ...

随机推荐

  1. 一款查询天气的WebApp

    一.WebApp介绍 1.初始界面 2.搜索结果页面 二.项目代码 1.项目目录 --------app ----------app.component.ts ----------app.compon ...

  2. element 列表中已选的标记

    //表格列表中已选的标记initSelFn(data){ let listData = []      listData = data.content ? data.content : []; let ...

  3. Mysql jar包

    密码cngb https://pan.baidu.com/share/init?surl=bSGA6T-LTwjx-qaNAiipCA

  4. oracle 监听服务配置

    最近在red hat 6.6虚拟机上安装了Oracle 11gR2数据库,安装完毕,使用没有问题,通过主机也可以访问到虚拟机上的数据库.然而,在重新启动虚拟机后,主机无法访问到数据库,提示错误: PS ...

  5. window/linux下获取文件MD5

    MD5消息摘要算法(英语: MD5 Message-Digest Algorithm), 主要用于确保信息传输过程的一致性校验.   首先介绍两个工具: window: WinMD5Free Linu ...

  6. LVS-DR模式实现调度负载

    本篇文章主要梳理一下LVS前端调度过程及用户请求过程 实验架构 准备工作 添加各主机路由联通主机通信 Client IP route add default gw 172.20.17.19 Route ...

  7. python3.5怎么打包编译

    问题:用Python开发的小工具有时需要编译打包为Windows(*.exe).Mac等操作系统下的可执行性文件以供非程序员使用. 解决方案: 一.py2exe 目前只支持到Python3.4,暂不支 ...

  8. sql sever 基础 练习题

    --1. 求半径2米,高3米的圆柱体体积. declare r @hight float,@r float,@ratio float ,@ v float --声明变量 set @hight=3 -- ...

  9. java 堆栈内存分析详解

    计算机术语里面堆和栈代表不同的存储结构:stack-栈:heap-堆 所以java虚拟机(JVM)中堆和栈是两种内存 堆.栈对比 对比点 堆 栈 JVM中的功能 内存数据区 内存指令区 动静态 运行时 ...

  10. Java线程和多线程(十)——TimerTask

    Java中的java.util.Timer是一个工具类,可以用于调度一个线程在将来的某一个时刻执行特定的任务.Java Timer类可以将一个任务定时执行一次,或者是以后以每隔一定的时间间隔来触发一次 ...