Android藍芽開發簡介

來源:互聯網
上載者:User

標籤:

Android藍芽系統

藍芽是一種支援裝置短距離通訊(一般10m內)的無線電技術,可以在眾多裝置之間進行無線資訊交換。

Android系統中的藍芽模組

Android包含了對藍芽網路通訊協定棧的支援,使藍牙裝置能夠無線串連其他藍牙裝置以便交換資料。

通過使用藍芽API,一個Android應用程式能夠實現如下功能:
- 掃描其他藍牙裝置
- 查詢本地藍芽適配器用於配對藍牙裝置
- 建立RFCOMM通道
- 通過服務發現串連其他裝置
- 資料通訊
- 管理多個串連

Android平台中藍芽系統從上到下主要包括Java架構中的BlueTooth類、Android適配庫、BlueZ庫、驅動程式和協議。

藍芽模組中的源碼
  • 初始化藍芽晶片

    通過BlueZ工具hciattach進行的,命令格式如下:    hciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]type決定了要初始化的裝置的型號,可以使用hciattach -1來列出所支援的裝置型號。Hciattach命令內部的工作步驟是:首先開啟制定的tty裝置,再做一些通用的設定,如flow等, 之後設定傳輸速率為initial_speed,然後根據type調用各自的初始化代碼,最後將傳輸速率重新設定為speed。
  • 藍芽服務

    一般不需要自己定義,只需要使用初始化指令檔init.rc中的預設內容即可。
  • 管理藍芽電源

    可以調用rfkill介面來控制電源管理,如果已經實現了rfkill介面,則無需再進行配置。
和藍芽相關的類BluetoothSocket類
  • BluetoothSocket類基礎

    Android的藍芽系統和Socket通訊端密切相關,藍芽端的監聽介面和TCP連接埠類似,都是使用 Socket和ServerSocket類。在伺服器端使用BluetoothServerSocket類來建立一個監聽服務連接埠。當一個串連被BluetoothServerSocket所接受,它會返回一個新的BluetoothSocket來管理該串連。在用戶端,使用一個單獨的BluetoothSocket類去初始化一個外接串連和管理該串連。

    最通常使用的藍芽連接埠是RFCOMM,它是一個連線導向,通過藍芽模組進行資料流傳輸方式,也被稱為序列埠規範(SPP)。

    建立一個BluetoothSocket去串連到一個已知裝置,使用方法BluetoothDevice.createRfcommSocketToServiceRecord()。然後調用connect()方法去嘗試一個面向遠程裝置的串連。這個調用將被阻塞指導一個串連已經建立或者該連結失效。

    當連接埠串連成功後,通過getInputStream()和getOutputStream()來開啟I/O流,從而獲得各自的InputStream和OutputStream對象。

    BluetoothSocket類的線程是安全的,因為close()方法會馬上放棄外界操作並關閉伺服器連接埠。

  • BluetoothSocket類的公用方法

    • public void close()
    • public void connect()
    • public InputStream getInputStream()
    • public OutputStream getOutputStream()
    • public BluetoothDevice getRemoteDevice()
BluetoothServerSocket類
  • BluetoothServerSocket類的公用方法

    • public BluetoothSocket accept(int timeout)
    • public BluetoothSocket accept()
    • public void close()
BluetoothAdapter類
  • BluetoothAdapter類基礎

    代表本地的藍芽適配器裝置,通過此類可以讓使用者能執行基本的藍芽任務,如初始化裝置的搜尋、查詢可匹配的裝置集、使用一個已知的MAC地址來初始化一個BluetoothDevice類、建立一個BluetoothServerSocket類以監聽其他裝置對原生串連請求等。

    調用靜態方法getDefaultAdapter()獲得,這是所有藍芽動作使用的第一步。當擁有本地適配器以後,使用者可以獲得一系列的BluetoothDevice對象,這些對象代表所有擁有getBondedDevice()方法的已經匹配的裝置;用startDiscovery()方法來開始裝置的搜尋;或者建立一個BluetoothServerSocket類,通過listenUsingRfcommWithServiceRecord(String,UUID)方法來監聽新來的串連請求。

    大部分方法需要BLUETOOTH許可權,一些方法同時需要BLUETOOTH_ADMIN許可權。

  • BluetoothAdapter類的常量

    • String ACTION_DISCOVERY_FINISHED

      廣播事件:本地藍芽適配器已經完成裝置的搜尋過程,需要BLUETOOTH許可權接收。常量值:android.bluetooth.adapter.action.DISCOVERY_FINISHED
    • String ACTION_DISCOVERY_STARTED

      廣播事件:本地藍芽適配器已經開始對遠程裝置的搜尋過程。使用者可以通過cancelDiscovery()類來取消正在執行的尋找過程,需要BLUETOOTH許可權接收。常量值:android.bluetooth.adapter.action.DISCOVERY_STARTED
    • String ACTION_LOCAL_NAME_CHANGED

      廣播事件:本地藍芽適配器已經更改了它的藍芽名稱,需要BLUETOOTH許可權接收。常量值:android.bluetooth.adapter.action.LOCAL_NAME_CHANGED
    • String ACTION_REQUEST_DISCOVERABLE

      Activity活動:顯示一個請求被搜尋模式的系統活動。Android運用onActivityResult(int,int,Intent)回收方法來傳遞該活動結果的通知。需要BLUETOOTH許可權。常量值:android.bluetooth.adapter.action.REQUEST_DISCOVERYABLE
    • String ACTION_REQUEST_ENABLE

      Activity活動:顯示一個允許使用者開啟藍芽模組的系統活動。Android運用onActivityResult(int,int,Intent)回收方法來傳遞該活動結果的通知。需要BLUETOOTH許可權。常量值:android.bluetooth.adapte.action.REQUEST_ENABLE
    • String ACTION_SCAN_MODE_CHANGED

      廣播活動:指明藍芽掃描模組或者本地適配器已經發生變化,需要BLUETOOTH許可權。常量值:android.bluetooth.adapter.action.SCAN_MODE_CHANGED
    • String ACTION_STATE_CHANGED

      廣播活動:本來的藍芽適配器的狀態已經改變,如藍芽模組已經被開啟或者關閉,需要BLUETOOTH許可權接收。常量值:android.bluetooth.adapter.action.STATE_CHANGED
    • int ERROR

      功能:標記該類的錯誤值,確保和該類中的任意其他整數常量不相等。它為需要一個標記錯誤值的函數提供了便利,例如:Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR);
    • String EXTRA_DISCOVERABLE_DURATION

      功能:試圖在ACTION_REQUEST_DISCOVERABLE常量中作為一個可選的整型附加域,來為短時間內的裝置發現請求一個特定的期間,預設值為120秒,超過300秒的請求將被限制。常量值:android.bluetooth.adapter.extra.DISCOVERABLE_DURATION
    • String EXTRA_LOCAL_NAME

      功能:試圖在ACTION_LOCAL_NAME_CHANGED常量中作為一個字串附加域,來請求本地藍芽的名稱。常量值:android.bluetooth.adapter.extra.LOCAL_NAME
    • String EXTRA_PREVIOUS_SCAN_MODE

      功能:試圖在ACTION_SCAN_MODE_CHANGED常量中作為一個整型附加域,來請求以前的掃描模式,可能值如下:    SCAN_MODE_NONE    SCAN_MODE_CONNECTABLE    SCAN_MODE_CONNECTABLE_DISCOVERABLE常量值:android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE
    • String EXTRA_PREVIOUS_STATE

      功能:試圖在ACTION_STATE_CHANGED常量中作為一個整型附加域,來請求以前的供電狀態。可能值如下:    STATE_OFF    STATE_TURNING_ON    STATE_ON    STATE_TURNING_OFF常量:android.bluetooth.adapter.extra.PREVIOUS_STATE
    • String EXTRA_SCAN_MODE

      功能:試圖在ACTION_SCAN_MODE_CHANGED常量作為一個整型附加域,來請求當前的掃描模式,可能值如下:    SCAN_MODE_NONE    SCAN_MODE_CONNECTABLE    SCAN_MODE_CONNECTABLE_DISCOVERABLE常量值:android.bluetooth.adapter.extra.SCAN_MODE
    • String EXTRA_STATE

      功能:試圖在ACTION_STATE_CHANGED常量中作為一個整型附加域,來請求當前供電狀態,可能值如下:    STATE_OFF    STATE_TURNING_ON    STATE_ON    STATE_TURNING_OFF常量值:android.bluetooth.adapter.extra.STATE
    • int SCAN_MODE_CONNECTABLE

      功能:指明在本地藍芽適配器中,查詢掃描功能失效,但頁面掃描功能有效。因此,該裝置不能被遠程藍牙裝置發現,但如果以前曾經發現過該裝置,則遠程裝置可以對其進行串連。常量值:21(0x00000015)
    • int SCAN_MODE_CONNECTABLE_DISCOVERABLE

      功能:指明在本地藍芽適配器中, 查詢掃描功能都有效,因此,該裝置既可以被遠程藍牙裝置發現,也可以被其串連。常量值:23(0x00000017)
    • int SCAN_MODE_NONE

      功能:指明在本地藍芽適配器中,查詢掃描功能和頁面掃描功能都失效,因此,該裝置既不可以被遠程藍牙裝置發現,也不可以被串連。常量值:20(0x00000014)
    • int STATE_OFF

      功能:指明本地藍芽適配器模式已經關閉常量值:10(0x0000000a)
    • int STATE_ON

      功能:指明本地藍芽適配器模組已經開啟,並且準備被使用
    • int STATE_TURNING_OFF

      功能:指明本地藍芽適配器模組正在關閉。本地用戶端可以立刻嘗試友好地斷開任意外部串連。常量值:13(0x0000000d)
    • int STATE_TURNING_ON

      功能:指明本地藍芽適配器模組正在開啟,然而本地客戶在嘗試使用這個適配器之前需要為STATE_ON狀態而等待常量值:11(0x000000b)
  • BluetoothAdapter類的公用方法

    • public boolean cancelDiscovery()
    • public static boolean checkBluetoothAddress(String address)
    • public boolean disable()
    • public boolean enable()
    • public String getAddress()
    • public Set getBondedDevices()
    • public static synchronized BluetoothAdapter getDefaultAdapter()
    • public String getName()
    • public BluetoothDevice getRemoteDevice(String address)
    • public int getScanMode()
    • public int getState()
    • public boolean isDiscovering()
    • public boolean isEnabled()
    • public BluetoothServerSocket ListenUsingRfcommWithServiceRecord(String name,UUID uuid)
    • public boolean setName(String name)
    • public boolean startDiscovery()
BluetoothClass.Service類

用於定義所有的服務類常量,任意BluetoothClass由0或多個服務類編碼組成。在類BluetoothClass.Service中包含如下常量:

  • int AUDIO
  • int CAPTURE
  • int INFORMATION
  • int LIMITED_DISCOVERABILITY
  • int NETWORKING
  • int OBJECT_TRANSFER
  • int POSITIONING
  • int RENDER
  • int TELEPHONY
BluetoothClass.Device類

用於定義所有的裝置類的常量,每個BluetoothClass有一個帶有主要和較小部分的裝置類進行編碼,裡面的常量代表主要和較小的裝置類部分(完整的裝置類)的組合。

在Android平台開發藍芽應用程式
  • 1.設定許可權

    <uses-permission android:name="android.permission.BLUETOOTH"/><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  • 2.啟動藍芽

    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if(mBluetoothAdapter == null){    //表示手機不支援藍芽    return;}if(!mBluetoothAdapter.isEnabled()){ //藍芽未開啟,則開啟藍芽    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    startActivityForResult(enableIntent,REQUEST_ENABLE_BT);}//...public void onActivityResult(int requestCode,int resultCode,Intent data){    if(requestCode == REQUEST_ENABLE_BT){        if(resultCode == RESULT_OK){            //藍芽已經開啟        }    }}
  • 3.發現藍牙裝置

    //使本機藍芽在300秒內可被搜尋private void ensureDiscoverable(){    if(mBluethAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){        Intent discoverableIntent = new Intent(BluetoothAdapter.ATION_REQUEST_DISCOVERABLE);         intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);        startActivity(discoverableIntent);    }}//尋找已經配對的藍牙裝置,即以前已經配對過的裝置Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();if(pairedDevices.size() > 0){    findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);    for(BluetoothDevice device : pairedDevices){        //device.getName() + " " + device.getAddress();    }}else{    mPairedDevicesArrayAdapter.add("沒有找到已配對的裝置");}//註冊,當一個裝置被發現時調用onReceiveIntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);this.registerReceiver(mReceiver,filter);//當搜尋結束後調用onReceivefilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);this.registerReceiver(mReceiver,filter);//...private BroadcastReceiver mReceiver = new BroadcastReceiver(){    @Override    public void onReceiver(Context context,Intent intent){        String action = intent.getAction();        if(BluetoothDevice.ACTION_FOUND.equal(action)){            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);            //已經配對的則跳過            if(device.getBondState() != BluetoothDevice.BOND_BONDED){                mNewDevicesArrayAdapter.add(device.getName()+"\n"+device.getAddress());             }        }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equal(action)){            //搜尋結束            if(mNewDevicesArrayAdapter.getCount() == 0){                mNewDevicesArrayAdapter.add("沒有搜尋到裝置");            }        }    }}
  • 4.建立串連

    //UUID可以看做一個連接埠號碼private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");//像一個伺服器一樣時刻監聽是否有串連建立private class AcceptThread extend Thread{    private BluetoothServerSocket serverSocket;    public AcceptThread(boolean secure){        BluetoothServerSocket temp = null;        try{            temp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_INSECURE,MY_UUID);        }catch(IOException e){            Log.e("TAG","listen() failed "+e);        }        serverSocket = temp;    }    public void run(){        BluetoothSocket socket = null;        while(true){            try{                socket = serverSocket.accept();            }catch(IOException e){                Log.e("TAG","accept() failed "+e);                break;            }        }        if(socket != null){            //此時可以建立一個資料交換線程,把此socket傳進去        }    }    //取消監聽    public void cancel(){        try{            serverSocket.close();        }catch(){            Log.e("TAG","Socket Type "+socketType+" close() of server failed "+e);        }    }}
  • 5.交換資料

    //另一個裝置去串連本機,相當於用戶端private class ConnectThread extends Thread{    private BluetoothSocket socket;    private BluetoothDevice device;    public ConnectThread(BluetoothDevice device,boolean secure){        this.device = device;        BluetoothSocket tmp = null;        try{            tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);        }catch(IOException e){            Log.e("TAG","create() failed "+e);        }    }    public void run(){        mBluetoothAdapter.cancelDiscovery(); //取消裝置尋找        try{            socket.connect();        }catch(IOException e){            try{                socket.close();            }catch(IOException e1){                Log.e("TAG","unable to close "+"socket during connection failure "+e1);            }            connectionFailed(); //串連失敗            return;        }        //此時可以建立一個資料交換線程,把此socket傳進去    }    public void cancel(){        try{            socket.close();        }catch(){            Log.e("TAG","close() of connect socket failed "+e);        }    }}
  • 6.建立資料通訊線程

    //建立串連後,進行資料通訊的線程private class ConnectedThread extend Thread{    private BluetoothSocket socket;    private InputStream inStream;    private OutputStream outStream;    public ConnectedThread(BluetoothSocket socket){        this.socket = socket;        try{            //擷取輸入/輸出流            inStream = socket.getInpuStream();            outStream = socket.getOutputStream();        }catch(IOException e){            Log.e("TAG","temp sockets not created "+e);        }    }    public void run(){        byte[] buff = new byte[1024];        int len = 0;        //讀取資料需不斷監聽,寫不需要        while(true){            try{                len = inStream.read(buff);                //把讀取到的資料發送給UI進行顯示                  Message msg = handler.obtainMessage(BluetoothChat.MESSAGE_READ,len,-1,buff);            }catch(IOException e){                Log.e("TAG","disconnected "+e);                connectionLost(); //失去串連                start(); //重新啟動伺服器                break;            }        }    }    public void write(byte[] buffer){        try{            outStream.write(buffer);            handler.obtainMessage(BluetoothChat.MESSAGE_WRITE,-1,-1,buffer);            msg.sendToTarget();        }catch(IOException e){            Log.e("TAG","Exception during write "+e);        }    }    public void cancel(){        try{                socket.close();        }catch(IOException e){            Log.e("TAG","close() of connect socket failed "+e);        }    }}

Android藍芽開發簡介

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.