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" />
     
     
     
     
     
  • 相关阅读:
    Exp5
    Exp4
    Exp3
    Exp02
    【TPM】tpm搭建基础指南
    20155316 Exp1 PC平台逆向破解(5)M
    个人早期写的一些组件
    关于spring @scope("prorotype") 和 @aspectj 一起用的问题
    ThreadLocal内存泄漏需要注意的
    Spring IoC 容器大概流程
  • 原文地址:https://www.cnblogs.com/androidsj/p/3857257.html
Copyright © 2011-2022 走看看