zoukankan      html  css  js  c++  java
  • 16、蓝牙技术

    蓝牙简介

            蓝牙(Bluetooth)是一种短距离的无线通信技术标准。这个名子来源于10世纪丹麦国王Harald Blatand,英文名子是Harold Bluetooth。在无线行业协会组织人员的讨论后,有人认为用Blatand国王的名字命名这种无线技术是再好不过了,这是因为Blatand国王将挪威、瑞典和丹麦统一起来,这就如同这项技术将统一无线通信领域一样。至此,蓝牙的名字也就这样定了下来。

           蓝牙协议分为4层,即核心协议层、电缆替代协议层、电话控制协议层和采纳的其它协议层。这4种协议中最重要的是核心协议。蓝牙的核心协议包括基带、链路管理、逻辑链路控制和适应协议四部分。其中链路管理(LMP)负责蓝牙组件间连接的建立。逻辑链路控制与适应协议(L2CAP)位于基带协议层上,属于数据链路层,是一个为高层传输和应用层协议屏蔽基带协议的适配协议。

    打开和关闭蓝牙设备

    第1种打开蓝牙的方式

    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

    startActivityForResult(enableIntent, 1);

    必须设置权限

    <uses-permission android:name="android.permission.BLUETOOTH" />

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter()

    adapter.enable();

    adapter.disable();

    搜索蓝牙设备

    蓝牙数据传输

          通过蓝牙传输数据与Socket类似。在网络中使用Socket和ServerSocket控制客户端和服务端的数据读写。而蓝牙通讯也由客户端和服务端Socket来完成。蓝牙客户端Socket是BluetoothSocket,蓝牙服务端Socket是BluetoothServerSocket。这两个类都在android.bluetooth包中。

          无论是BluetoothSocket,还是BluetoothServerSocket,都需要一个UUID(全局唯一标识符,Universally Unique Identifier).格式如下:

    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

    UUID的格式被分成5段,其中中间3段的字符数相同,都是4,第1段是8个字符,最后一段是12个字符。所以UUID实际上是一个8-4-4-4-12的字符串。

    UUID相当于Socket的端口,而蓝牙地址相当于Socket的IP。

    蓝牙的UUID

          两个蓝牙设备进行连接时需要使用同一个UUID。但很多读者可能发现,有很多型号的手机(可能是非Android系统的手机)之间使用了不同的程序也可以使用蓝牙进行通讯。从表面上看,它们之间几乎不可能使用同一个UUID。 

           实际上,UUID和TCP的端口一样,也有一些默认的值。例如,将蓝牙模拟成串口的服务就使用了一个标准的UUID:

    00001101-0000-1000-8000-00805F9B34FB。除此之外,还有很多标准的UUID,如下面就是两个标准的UUID。

    信息同步服务:00001104-0000-1000-8000-00805F9B34FB
    文件传输服务:00001106-0000-1000-8000-00805F9B34FB
     
    DEMO:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="fill_parent"
     4     android:layout_height="fill_parent"
     5     android:orientation="vertical" >
     6 
     7     <Button
     8         android:layout_width="fill_parent"
     9         android:layout_height="wrap_content"
    10         android:onClick="onClick_Search"
    11         android:text="搜索" />
    12 
    13     <ListView
    14         android:id="@+id/lvDevices"
    15         android:layout_width="fill_parent"
    16         android:layout_height="wrap_content" />
    17 
    18 </LinearLayout>
      1 import java.io.InputStream;
      2 import java.io.OutputStream;
      3 import java.util.ArrayList;
      4 import java.util.List;
      5 import java.util.Set;
      6 import java.util.UUID;
      7 
      8 import android.app.Activity;
      9 import android.bluetooth.BluetoothAdapter;
     10 import android.bluetooth.BluetoothDevice;
     11 import android.bluetooth.BluetoothServerSocket;
     12 import android.bluetooth.BluetoothSocket;
     13 import android.content.BroadcastReceiver;
     14 import android.content.Context;
     15 import android.content.Intent;
     16 import android.content.IntentFilter;
     17 import android.os.Bundle;
     18 import android.os.Handler;
     19 import android.os.Message;
     20 import android.view.View;
     21 import android.view.Window;
     22 import android.widget.AdapterView;
     23 import android.widget.AdapterView.OnItemClickListener;
     24 import android.widget.ArrayAdapter;
     25 import android.widget.ListView;
     26 import android.widget.Toast;
     27 
     28 /**
     29  * 单击列表项蓝牙设备,去连接另外一个蓝牙设备,并且进行配对,
     30  * 配对完后,将一个文本信息,传递过去。
     31  * @author dr
     32  *
     33  */
     34 public class Main extends Activity implements OnItemClickListener {
     35 
     36     private ListView lvDevices;   // 蓝牙列表
     37     private BluetoothAdapter bluetoothAdapter;  // 蓝牙适配器
     38     // 用于储存所有搜索到的蓝牙名称和地址。
     39     private List<String> bluetoothDevices = new ArrayList<String>();
     40     // 数组适配器,显示列表
     41     private ArrayAdapter<String> arrayAdapter;
     42     // 
     43     private final UUID MY_UUID = UUID
     44             .fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3");
     45     // 自定义
     46     private final String NAME = "Bluetooth_Socket";
     47     // 客户端。
     48     private BluetoothSocket clientSocket;
     49     private BluetoothDevice device;
     50     //  
     51     private AcceptThread acceptThread;
     52     // 输出流(从客户端往服务端进行输出)。
     53     private OutputStream os;
     54     
     55     private Handler handler = new Handler() {
     56         public void handleMessage(Message msg) {
     57             Toast.makeText(Main.this, String.valueOf(msg.obj),
     58                     Toast.LENGTH_LONG).show();
     59             super.handleMessage(msg);
     60         }
     61     };
     62 
     63     @Override
     64     public void onCreate(Bundle savedInstanceState) {
     65         super.onCreate(savedInstanceState);
     66 
     67         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
     68         setContentView(R.layout.main);
     69         
     70         lvDevices = (ListView) findViewById(R.id.lvDevices);
     71 
     72         // 得到 BluetoothAdapter对象。
     73         bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
     74 
     75         // 得到已经配对的蓝牙,显示出来
     76         Set<BluetoothDevice> pairedDevices = bluetoothAdapter
     77                 .getBondedDevices();   
     78         if (pairedDevices.size() > 0) {  // 已经配完对的。
     79             for (BluetoothDevice device : pairedDevices) {
     80                 bluetoothDevices.add(device.getName() + ":"
     81                         + device.getAddress() + "
    ");
     82             }
     83         }
     84 
     85         // 将所有设备,显示在列表上。
     86         arrayAdapter = new ArrayAdapter<String>(this,
     87                 android.R.layout.simple_list_item_1, android.R.id.text1,
     88                 bluetoothDevices);
     89 
     90         lvDevices.setAdapter(arrayAdapter);
     91         lvDevices.setOnItemClickListener(this);
     92         
     93         // 每找到一个设备,发送一个广播。
     94         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
     95         this.registerReceiver(receiver, filter);
     96 
     97         // 全部搜索完后,发送一个广播。
     98         filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
     99         this.registerReceiver(receiver, filter);
    100         
    101         // 实例化,并且启动。
    102         acceptThread = new AcceptThread();
    103         acceptThread.start();
    104     }
    105 
    106     public void onClick_Search(View view) {
    107         // 显示进度条,扫描状态。
    108         setProgressBarIndeterminateVisibility(true);
    109         setTitle("正在扫描...");
    110         // 判断是否正在搜索。
    111         if (bluetoothAdapter.isDiscovering()) {
    112             bluetoothAdapter.cancelDiscovery();
    113         }
    114         bluetoothAdapter.startDiscovery();
    115     }
    116 
    117     /** 广播接收器 */ 
    118     private final BroadcastReceiver receiver = new BroadcastReceiver() {
    119         @Override
    120         public void onReceive(Context context, Intent intent) {
    121             String action = intent.getAction();
    122             // 当搜索到一个设备时
    123             if (BluetoothDevice.ACTION_FOUND.equals(action)) {
    124                 // 获得这个设备的信息。
    125                 BluetoothDevice device = intent
    126                         .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    127                 // 判断当前设备没有被绑定。
    128                 if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
    129                     bluetoothDevices.add(device.getName() + ":"
    130                             + device.getAddress() + "
    ");
    131                     arrayAdapter.notifyDataSetChanged();
    132                 }
    133             // 已经完成的情况。
    134             } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
    135                     .equals(action)) {
    136                 // 关闭进度条。
    137                 setProgressBarIndeterminateVisibility(false);
    138                 setTitle("连接蓝牙设备");
    139             }
    140         }
    141     };
    142 
    143     @Override    /** 客户端 */ 
    144     public void onItemClick(AdapterView<?> parent, View view, int position,
    145             long id) {
    146         String s = arrayAdapter.getItem(position);
    147         // 得到地址,相当于ip
    148         String address = s.substring(s.indexOf(":") + 1).trim();
    149 
    150         try {
    151             // 判断是否在搜索
    152             if (bluetoothAdapter.isDiscovering()) {  
    153                 bluetoothAdapter.cancelDiscovery();
    154             }
    155             try {
    156                 if (device == null) {
    157                     // 得到远程设备。
    158                     device = bluetoothAdapter.getRemoteDevice(address);
    159                 }
    160                 if (clientSocket == null) {
    161                     // 得到UUID
    162                     clientSocket = device
    163                             .createRfcommSocketToServiceRecord(MY_UUID);
    164                     // 开始连接。
    165                     clientSocket.connect();
    166                     // 获得输出流。
    167                     os = clientSocket.getOutputStream();
    168                 }
    169             } catch (Exception e) {
    170                 // TODO: handle exception
    171             }
    172             if (os != null) {
    173                 os.write("发送信息到其他蓝牙设备".getBytes("utf-8"));
    174             }
    175         } catch (Exception e) {
    176             // TODO: handle exception
    177         }
    178     }
    179 
    180     /** 服务端的东西 */  
    181     private class AcceptThread extends Thread {
    182         private BluetoothServerSocket serverSocket;
    183         private BluetoothSocket socket;
    184         private InputStream is;
    185         private OutputStream os;
    186 
    187         public AcceptThread() {
    188             try {
    189                 serverSocket = bluetoothAdapter
    190                         .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
    191             } catch (Exception e) {
    192                 // TODO: handle exception
    193             }
    194         }
    195 
    196         public void run() {  
    197             // 截获 客户端的  信息。
    198             try {
    199                 socket = serverSocket.accept();
    200                 is = socket.getInputStream();
    201                 os = socket.getOutputStream();
    202 
    203                 while (true) {
    204                     byte[] buffer = new byte[128];
    205                     int count = is.read(buffer);
    206                     Message msg = new Message();
    207                     msg.obj = new String(buffer, 0, count, "utf-8");
    208                     handler.sendMessage(msg);
    209                 }
    210             } catch (Exception e) {
    211                 // TODO: handle exception
    212             }
    213 
    214         }
    215     }
    216 
    217 }
    1 <uses-permission android:name="android.permission.BLUETOOTH" />
    2 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     
     
     
     
     
  • 相关阅读:
    java的构造方法 java程序员
    No result defined for action cxd.action.QueryAction and result success java程序员
    大学毕业后拉开差距的真正原因 java程序员
    hibernate的回滚 java程序员
    验证码 getOutputStream() has already been called for this response异常的原因和解决方法 java程序员
    浅谈ssh(struts,spring,hibernate三大框架)整合的意义及其精髓 java程序员
    你平静的生活或许会在某个不可预见的时刻被彻底打碎 java程序员
    Spring配置文件中使用ref local与ref bean的区别. 在ApplicationResources.properties文件中,使用<ref bean>与<ref local>方法如下 java程序员
    poj1416Shredding Company
    poj1905Expanding Rods
  • 原文地址:https://www.cnblogs.com/androidsj/p/3857257.html
Copyright © 2011-2022 走看看