一:概要: 

 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. AngularJS 控制器函数

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

  2. spring入门(四) spring mvc返回json结果

    前提:已搭建好环境 1.建立Controller package com.ice.controller; import com.ice.model.Person; import org.springf ...

  3. iOS之UIImagePickerController显示中文界面

    iOS开发中,我们经常遇到获取拍照.相册中图片的功能,就必然少不了UIImagePickerController,但是我们发现当我们使用它的时候,它的页面是英文的,看着很别扭,国人还是比较喜欢看中文界 ...

  4. MySQL备份恢复之mysqldump

      Preface       The day before yesterday,there's a motif about the lock procedure when backing up My ...

  5. Modify the apache2 default document and home page on ubuntu (ubuntu下修改apache2默认目录和默认主页)

    Change the apache2 default website directory As we know, The apache2 default directory at /var/www/, ...

  6. Ubuntu16.04采用FastCGI方式部署Flask web框架

    1    部署nginx 1.1    安装nginx服务 root@desktop:~# apt-get install nginx -y 1.2    验证nginx服务是否启动 root@des ...

  7. thinkphp 下多图ajax上传图片

    碰到一个项目,有一个比较繁琐的功能6个ajax上传,基本上每个上传逻辑多不一样,记录一下 thinkphp的view页面: id方便找到这个元素 name一定要加 [ ] <div class= ...

  8. mysql的数据操作和内置功能总结

    一.数据的增删改查 1.插入数据 a.插入完整数据(顺序插入) INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n); INSERT INTO 表名 ...

  9. tp3.2报错;syntax error, unexpected 'function' (T_FUNCTION), expecting identifier (T_STRING) or \\ (T_NS_SEPARATOR)

    出错原因:这个是php版本问题,laravel5.1的php版本要求是PHP >= 5.5.9,切换一下PHP版本就行.

  10. Java基础——继承和多态

    面向对象的编程允许从已经存在的类中定义新的类,这称为继承. 面向过程的范式重点在于方法的设计,而面向对象的范式将数据和方法结合在对象中.面向对象范式的软件设计着重于对象以及对象上的操作.面向对象的方法 ...