欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Android——藍(lán)牙技術(shù) 帶你實(shí)現(xiàn)終端間數(shù)據(jù)傳輸

 更新時(shí)間:2016年12月15日 11:01:09   作者:郭朝  
藍(lán)牙技術(shù)在智能硬件方面有很多用武之地,本篇文章主要介紹了Android——藍(lán)牙技術(shù),實(shí)現(xiàn)兩個(gè)終端間數(shù)據(jù)的傳輸,有興趣的朋友可以了解一下。

藍(lán)牙技術(shù)在智能硬件方面有很多用武之地,今天我就為大家分享一下藍(lán)牙在Android系統(tǒng)下的使用方法技巧,并實(shí)現(xiàn)一下兩個(gè)終端間數(shù)據(jù)的傳輸。

藍(lán)牙(Bluetooth)是一種短距離的無(wú)線通信技術(shù)標(biāo)準(zhǔn),藍(lán)牙協(xié)議分為4層,即核心協(xié)議層、電纜替代協(xié)議層、電話控制協(xié)議層和采納的其它協(xié)議層。

這4種協(xié)議中最重要的是核心協(xié)議。藍(lán)牙的核心協(xié)議包括基帶、鏈路管理、邏輯鏈路控制和適應(yīng)協(xié)議四部分。其中鏈路管理(LMP)負(fù)責(zé)藍(lán)牙組件間連接的建立。邏輯鏈路控制與適應(yīng)協(xié)議(L2CAP)位于基帶協(xié)議層上,屬于數(shù)據(jù)鏈路層,是一個(gè)為高層傳輸和應(yīng)用層協(xié)議屏蔽基帶協(xié)議的適配協(xié)議。

1.打開(kāi)和關(guān)閉藍(lán)牙

第一種方法相對(duì)簡(jiǎn)單,直接調(diào)用系統(tǒng)對(duì)話框啟動(dòng)藍(lán)牙:

在AndroidManifest文件中添加需要的權(quán)限,高版本也不需要?jiǎng)討B(tài)授權(quán):

<uses-permission android:name="android.permission.BLUETOOTH" />
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);

第一種方法

如果不想讓用戶看到這個(gè)對(duì)話框,那么我們還可以選擇第二種方法,進(jìn)行靜默開(kāi)啟藍(lán)牙。

第二種方法,靜默開(kāi)啟,不會(huì)有方法一的對(duì)話框:

在AndroidManifest文件中添加需要的權(quán)限:

<!-- 已適配Android6.0 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-feature
  android:name="android.hardware.bluetooth_le"
  android:required="true" />

由于藍(lán)牙所需要的權(quán)限包含Dangerous Permissions,所以我們需要在Java代碼中進(jìn)行動(dòng)態(tài)授權(quán)處理:

private static final int REQUEST_BLUETOOTH_PERMISSION=10;

private void requestBluetoothPermission(){
  //判斷系統(tǒng)版本
  if (Build.VERSION.SDK_INT >= 23) {
    //檢測(cè)當(dāng)前app是否擁有某個(gè)權(quán)限
    int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, 
        Manifest.permission.ACCESS_COARSE_LOCATION);
    //判斷這個(gè)權(quán)限是否已經(jīng)授權(quán)過(guò)
    if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED){
      //判斷是否需要 向用戶解釋,為什么要申請(qǐng)?jiān)摍?quán)限
      if(ActivityCompat.shouldShowRequestPermissionRationale(this, 
          Manifest.permission.ACCESS_COARSE_LOCATION))
        Toast.makeText(this,"Need bluetooth permission.", 
            Toast.LENGTH_SHORT).show();
      ActivityCompat.requestPermissions(this ,new String[]
          {Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_BLUETOOTH_PERMISSION);
      return;
    }else{
    }
  } else {
  }
}

接下來(lái)我們就可以靜默開(kāi)啟藍(lán)牙了:

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.enable(); //開(kāi)啟
//mBluetoothAdapter.disable(); //關(guān)閉

下面我們來(lái)看一下如何通過(guò)代碼搜索藍(lán)牙設(shè)備。

2.通過(guò)代碼搜索藍(lán)牙設(shè)備

搜索分為主動(dòng)搜索和被動(dòng)搜索。

我們開(kāi)始進(jìn)行主動(dòng)搜索:

(1)創(chuàng)建BluetoothAdapter對(duì)象

TextView tvDevices = (TextView)findViewById(R.id.tv_devices);
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

(2)我們先獲取并顯示一下已經(jīng)配對(duì)的藍(lán)牙設(shè)備列表

//獲取已經(jīng)配對(duì)的藍(lán)牙設(shè)備
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
  for (BluetoothDevice device : pairedDevices) {
    tvDevices.append(device.getName() + ":" + device.getAddress());
  }
}

(3)下面我們定義廣播接收器

// 設(shè)置廣播信息過(guò)濾
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);//每搜索到一個(gè)設(shè)備就會(huì)發(fā)送一個(gè)該廣播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//當(dāng)全部搜索完后發(fā)送該廣播
filter.setPriority(Integer.MAX_VALUE);//設(shè)置優(yōu)先級(jí)
// 注冊(cè)藍(lán)牙搜索廣播接收者,接收并處理搜索結(jié)果
this.registerReceiver(receiver, filter);

藍(lán)牙設(shè)備的廣播接收器如下:

/**
 * 定義廣播接收器
 */
private final BroadcastReceiver receiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (BluetoothDevice.ACTION_FOUND.equals(action)) {
      BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
      if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
        tvDevices.append(device.getName() + ":"+ device.getAddress());
      }
    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
      //已搜素完成
    }
  }
};

(4)我們創(chuàng)建一個(gè)Button按鈕,當(dāng)點(diǎn)擊Button時(shí)進(jìn)行搜索,Button點(diǎn)擊事件如下:

//如果當(dāng)前在搜索,就先取消搜索
if (mBluetoothAdapter.isDiscovering()) {
  mBluetoothAdapter.cancelDiscovery();
}
//開(kāi)啟搜索
mBluetoothAdapter.startDiscovery();

搜索藍(lán)牙設(shè)備

3.藍(lán)牙的UUID

兩個(gè)藍(lán)牙設(shè)備進(jìn)行連接時(shí)需要使用同一個(gè)UUID。但很多讀者可能發(fā)現(xiàn),有很多型號(hào)的手機(jī)(可能是非Android系統(tǒng)的手機(jī))之間使用了不同的程序也可以使用藍(lán)牙進(jìn)行通訊。從表面上看,它們之間幾乎不可能使用同一個(gè)UUID。

UUID的格式如下:

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

UUID的格式被分成5段,其中中間3段的字符數(shù)相同,都是4,第1段是8個(gè)字符,最后一段是12個(gè)字符。所以UUID實(shí)際上是一個(gè)8-4-4-4-12的字符串。

實(shí)際上,UUID和TCP的端口一樣,也有一些默認(rèn)的值。例如,將藍(lán)牙模擬成串口的服務(wù)就使用了一個(gè)標(biāo)準(zhǔn)的UUID:

00001101-0000-1000-8000-00805F9B34FB

除此之外,還有很多標(biāo)準(zhǔn)的UUID,如下面就是兩個(gè)標(biāo)準(zhǔn)的UUID:

信息同步服務(wù):00001104-0000-1000-8000-00805F9B34FB

文件傳輸服務(wù):00001106-0000-1000-8000-00805F9B34FB

4.藍(lán)牙終端間數(shù)據(jù)傳輸

通過(guò)藍(lán)牙傳輸數(shù)據(jù)與Socket類似。在網(wǎng)絡(luò)中使用Socket和ServerSocket控制客戶端和服務(wù)端的數(shù)據(jù)讀寫(xiě)。而藍(lán)牙通訊也由客戶端和服務(wù)端Socket來(lái)完成。藍(lán)牙客戶端Socket是BluetoothSocket,藍(lán)牙服務(wù)端Socket是BluetoothServerSocket。這兩個(gè)類都在android.bluetooth包中。

無(wú)論是BluetoothSocket,還是BluetoothServerSocket,都需要一個(gè)UUID(全局唯一標(biāo)識(shí)符,Universally Unique Identifier),UUID相當(dāng)于Socket的端口,而藍(lán)牙地址相當(dāng)于Socket的IP。

我們開(kāi)始進(jìn)行模擬一個(gè)藍(lán)牙數(shù)據(jù)的傳輸:

首先來(lái)看客戶端:

(1)定義全局常量變量

private ListView lvDevices;
private BluetoothAdapter mBluetoothAdapter;
private List<String> bluetoothDevices = new ArrayList<String>();
private ArrayAdapter<String> arrayAdapter;
private final UUID MY_UUID = UUID
    .fromString("abcd1234-ab12-ab12-ab12-abcdef123456");//隨便定義一個(gè)
private BluetoothSocket clientSocket;
private BluetoothDevice device; 
private OutputStream os;//輸出流

(2)在onCreate方法中做初始化操作

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

lvDevices = (ListView) findViewById(R.id.lv_devices);
//獲取已經(jīng)配對(duì)的藍(lán)牙設(shè)備
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
  for (BluetoothDevice device : pairedDevices) {
    bluetoothDevices.add(device.getName() + ":"+ device.getAddress());
  }
}
arrayAdapter = new ArrayAdapter<String>(this,
    android.R.layout.simple_list_item_1, android.R.id.text1,bluetoothDevices);
lvDevices.setAdapter(arrayAdapter);
lvDevices.setOnItemClickListener(this);//Activity實(shí)現(xiàn)OnItemClickListener接口

//每搜索到一個(gè)設(shè)備就會(huì)發(fā)送一個(gè)該廣播
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(receiver, filter);
//當(dāng)全部搜索完后發(fā)送該廣播
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(receiver, filter);

藍(lán)牙設(shè)備的廣播接收器如下:

/**
 * 定義廣播接收器
 */
private final BroadcastReceiver receiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (BluetoothDevice.ACTION_FOUND.equals(action)) {
      BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
      if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
        bluetoothDevices.add(device.getName() + ":" + device.getAddress());
        arrayAdapter.notifyDataSetChanged();//更新適配器
      }

    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
      //已搜素完成
    }
  }
};

(4)我們創(chuàng)建一個(gè)Button按鈕,當(dāng)點(diǎn)擊Button時(shí)進(jìn)行搜索,Button點(diǎn)擊事件如下:

//如果當(dāng)前在搜索,就先取消搜索
if (mBluetoothAdapter.isDiscovering()) {
  mBluetoothAdapter.cancelDiscovery();
}
//開(kāi)啟搜索
mBluetoothAdapter.startDiscovery();

(5)接下來(lái)我們?cè)O(shè)置列表的點(diǎn)擊事件:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  String s = arrayAdapter.getItem(position);
  String address = s.substring(s.indexOf(":") + 1).trim();//把地址解析出來(lái)
  //主動(dòng)連接藍(lán)牙服務(wù)端
  try {
    //判斷當(dāng)前是否正在搜索
    if (mBluetoothAdapter.isDiscovering()) {
      mBluetoothAdapter.cancelDiscovery();
    }
    try {
      if (device == null) {
        //獲得遠(yuǎn)程設(shè)備
        device = mBluetoothAdapter.getRemoteDevice(address);
      }
      if (clientSocket == null) {
        //創(chuàng)建客戶端藍(lán)牙Socket
        clientSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
        //開(kāi)始連接藍(lán)牙,如果沒(méi)有配對(duì)則彈出對(duì)話框提示我們進(jìn)行配對(duì)
        clientSocket.connect();
        //獲得輸出流(客戶端指向服務(wù)端輸出文本)
        os = clientSocket.getOutputStream();
      }
    } catch (Exception e) {
    }
    if (os != null) {
      //往服務(wù)端寫(xiě)信息
      os.write("藍(lán)牙信息來(lái)了".getBytes("utf-8"));
    }
  } catch (Exception e) {
  }
}

接下來(lái)看服務(wù)端:

服務(wù)端使用的是另一部手機(jī),接受上面手機(jī)通過(guò)藍(lán)牙發(fā)送過(guò)來(lái)的信息并顯示。

(1)定義全局常量變量:

private BluetoothAdapter mBluetoothAdapter;
private AcceptThread acceptThread;
private final UUID MY_UUID = UUID
    .fromString("abcd1234-ab12-ab12-ab12-abcdef123456");//和客戶端相同的UUID
private final String NAME = "Bluetooth_Socket";
private BluetoothServerSocket serverSocket;
private BluetoothSocket socket;
private InputStream is;//輸入流

(2)定義服務(wù)端線程類:

private Handler handler = new Handler() {
  public void handleMessage(Message msg) {
    Toast.makeText(getApplicationContext(), String.valueOf(msg.obj),
        Toast.LENGTH_LONG).show();
    super.handleMessage(msg);
  }
};

//服務(wù)端監(jiān)聽(tīng)客戶端的線程類
private class AcceptThread extends Thread {
  public AcceptThread() {
    try {
      serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
    } catch (Exception e) {
    }
  }
  public void run() {
    try {
      socket = serverSocket.accept();
      is = socket.getInputStream();
      while(true) {
        byte[] buffer =new byte[1024];
        int count = is.read(buffer);
        Message msg = new Message();
        msg.obj = new String(buffer, 0, count, "utf-8");
        handler.sendMessage(msg);
      }
    }
    catch (Exception e) {
    }
  }
}

(3)在onCreate方法中初始化線程類并開(kāi)啟

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
acceptThread = new AcceptThread();
acceptThread.start();

我們運(yùn)行程序看一下效果圖:

client

點(diǎn)擊“搜索藍(lán)牙設(shè)備”按鈕,就會(huì)搜索到另一臺(tái)手機(jī)的藍(lán)牙信息,我們點(diǎn)擊條目,另一臺(tái)手機(jī)會(huì)出現(xiàn)如下變化:

server

彈出Toast,此時(shí)證明我們的藍(lán)牙數(shù)據(jù)已經(jīng)傳輸過(guò)來(lái)了。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論