一:概要: 

 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. data-ng-disabled指令

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  2. apache开启.htaccess及使用方法

    1 . 如何让的本地APACHE器.htaccess 如何让的本地APACHE呢?其实只要简朴修改一下apache的httpd.conf设置就让APACHE.htaccess开启了,来看看操作 打开h ...

  3. JS JavaScript中的this

    this是JavaScript语言中的一个关键字 它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用. function test() { this.x = 1; } 上面代码中,函 ...

  4. ATK 设计框架 之 Atk.CustomExpression

    在ATK-DataPortal框架中的xxxHandel中常用到的一种类型,形如: 1.protected virtual D ItemHandle(D item, Func<E, E> ...

  5. TCP套接字

    端口的概念 每个电脑一根网线,但是你挂着QQ的同时还可以浏览网页.两个不同应用的数据在同一根网线里是如何传输的呢?根据七层互联网模型,这个功能由运输层(TCP是运输层主要协议)实现.怎么实现呢,在网络 ...

  6. 关于SQLNET.AUTHENTICATION_SERVICES= (NTS) 的解释

    原文转自:http://www.360doc.com/content/12/0207/12/3446769_184740592.shtml       标题所代表的意思为 使用操作系统本地验证,一般不 ...

  7. awk分隔符

    最近需要检测日志,shell中用到了awk,因为分割条件不止一个,并且包括了中括号.在此记录一下关于多分隔符并且包含中括号的情况 awk -F'[=,]|[][]+' '{print $6}'

  8. 监听浏览器返回,pushState,popstate 事件,window.history对象

    在WebApp或浏览器中,会有点击返回.后退.上一页等按钮实现自己的关闭页面.调整到指定页面.确认离开页面或执行一些其它操作的需求.可以使用 popstate 事件进行监听返回.后退.上一页操作. 一 ...

  9. python网络编程,通过服务名称和会话类型(tcp,udp)获取端口号,简单的异常处理

    作为一个php程序员,同时有对网络方面感兴趣,php就比较蛋疼了,所以就抽了些时间看python 之前学python基础因为工作原因,断断续续的看了个基础,差不多是可以写代码了 最近在看<pyt ...

  10. 第一个python代码

    # -*- coding:utf-8 -*- user = raw_input("请输入用户名") passwd = raw_input("请输入密码") if ...