Android藍牙使用(一)

Android通過BluetoothAdapter來檢測藍牙狀態,打開或關閉藍牙,掃描藍牙並得到藍牙信息等功能。
在使用時,通過BluetoothAdapter.getDefaultAdapter()方法來獲取系統的BluetoothAdapter,如果系統支持藍牙則會返回實例,如果不支持,則返回空;寫個簡單的demo來看看吧:

先在MainActivity.class 中定義BluetoothAdapter、BluetoothDevice等變量

public class MainActivity extends Activity implements View.OnClickListener,TBluetoothListAdapter.OnBluetoothItemClickListener {

    //adapter 
    private BluetoothAdapter bluetoothAdapter ;
    //遠程的藍牙設備,可以創建到各個藍牙設備的連接,並獲取遠程藍牙設備的信息(如名字,地址,類名和匹配狀態)
    private BluetoothDevice mDevice ;
    //用列表顯示搜索得到的藍牙設備信息
    private RecyclerView rvBluetooth ;
    //自定義的數據展示adapter
    private TBluetoothListAdapter adapter ;
    //簡單的藍牙信息實體類,用於展示
    private List<TBlueToothInfo> datas = new ArrayList<>() ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main) ;
        initView();
        initData();
    }
}

然後在initView方法中初始化佈局等相關信息:

private void initView() {
        //初始化佈局
        rvBluetooth = (RecyclerView)findViewById(R.id.rv_bluetooth) ;
        findViewById(R.id.tv_search_bluetooth).setOnClickListener(this) ;
        //初始化TBluetoothListAdapter
        adapter = new TBluetoothListAdapter(datas,this) ;
        //設置數據列表的點擊事件
        adapter.setOnBluetoothItemClickListener(this) ;
        rvBluetooth.setAdapter(adapter) ;
        rvBluetooth.setLayoutManager(new LinearLayoutManager(this)) ;
}

在initData方法中初始化bluetoothAdapter

private void initData() {
        //初始化adapter和權限
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    }

通過點擊事件,開始判斷藍牙狀態,如果未打開則打開藍牙,如果可用,則開始掃描藍牙設備:

@Override
    public void onClick(View v) {
        if(bluetoothAdapter != null) {//代表系統有藍牙功能
            if(!bluetoothAdapter.isEnabled()) {  //如果藍牙不可用
                //啓動藍牙
                Intent bluetoothIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) ;
                startActivity(bluetoothIntent);
                //搜索藍牙
                searchBluetooth();
            } else { // 藍牙可用
                //搜索藍牙
                searchBluetooth();
            }
        }
    }

搜索藍牙的方法如下,主要是通過發送系統廣播來監聽掃描得到的結果。BluetoothDevice有多個ACTION,這裏我們用到了2個

  • ACTION_FOUND:掃描到任一遠程藍牙設備時,會發送;
  • ACTION_DISCOVERY_FINISHED:掃描完成時會發送,一般掃描過程最長爲12秒
//搜索藍牙
    private void searchBluetooth() {
        hasRegist = true ;
        IntentFilter filter = new IntentFilter() ;
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(receiver,filter);
        if (bluetoothAdapter.isDiscovering()) {
            //通過cancelDiscovery方法來取消掃描
            bluetoothAdapter.cancelDiscovery();
        } 
        datas.clear();
        //通過調用BluetoothAdapter的startDiscovery方法來掃描,掃描的結果通過廣播來監聽
        blutoothAdapter.startDiscovery() ;
    }

在廣播的receiver裏,通過BluetoothDevice得到遠程的藍牙設備的信息:

private 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) ;

                String itemName = device.getName() ;
                String hasPaired = device.getBondState == BluetoothDevice.BOND_BONDED ?"(已配對)":"(未配對)" ;
                String address = device.getAddress() ;
                TBlueToothInfo info = new TBlueToothInfo() ;
                info.setDeviceName(itemName + hasPaired) ;
                info.setDeviceAddr(address) ;
                if (!hasContainedDevice(info)) {
                    datas.add(info) ;
                    adapter.notifyDataSetChanged() ;
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                if (datas.size == 0 ) {
                    //沒有發現任何設備
                }
            }
        }
    }
    //判斷掃描出的設備是不是已經存在於數據列表中了
    private boolean hasContainedDevice(TBlueToothInfo info) {
        for (TBlueToothInfo blueToothInfo : datas) {
            if (info.getDeviceAddr.equals(blueToothInfo.getDeviceAddr())) {
                return true ;
            }
        }
        return false ;
    }

註冊了receiver,也自然要註銷:

@Override
protected void onStop() {
    super.onStop() ;
    if (hasRegist) {
        unregisterReceiver(receiver) ;
    }
}

在receiver中,我們得到了掃描出的藍牙設備信息,並且展示到了列表中,現在,我們設置recyclerview的item點擊事件,點擊配對當前設備:

@Override
public void clickItem(int position) {
    //取到當前點擊item的藍牙地址,通過adapter得到遠程設備
    mDevice = bluetoothAdapter.getRemoteDevice(datas.get(position).getDeviceAddr()) ;
    if (mDevice.getBondState() == BluetoothDevice.BOND_NONE) { //如果未配對過
        IntentFilter boundFilter = new IntentFilter() ;
        boundFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED) ;
        registerReceiver(boundReceiver,boundFilter);
        //已經配對,則解除配對
        pairOrConnect(true) ;
    } else {
        //未配對,則開始配對
        pairOrConnect(false) ;
    }
}

這裏我們獲取到遠程設備的配對狀態,如果是沒有配對過的設備,則開始配對:

private void pairOrConnect(boolean pair) {
    boolean success ;// 配對 或 解除配對是否成功
    if (pair) {//未配對過的設備,開始配對
        try {
            Method createBound = BluetoothDevice.class.getMethod("createBond");
            success = (boolean) createBoundMethod.invoke(mDevice) ;
        } catch(NoSuchMethonException e) {
            e.printStackTrace();
        } catch(InvocationTargetException e ) {
            e.printStackTrace();
        } catch(IllegalAccessException e) {
            e.printStackTrace();
        }
    } else {//已經配對過的設備,則取消配對
        try {
            Method removeBound = BluetoothDevice.class.getMethod("removeBound");
            success = (boolean) removeBound.invoke(mDevice) ;
        } catch(NoSuchMethonException e) {
            e.printStackTrace();
        } catch(InvocationTargetException e ) {
            e.printStackTrace();
        } catch(IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

這裏無論是配對還是移除配對(createBond/removeBond)都是通過反射來調用BluetoothDevice類裏的方法,具體有哪些方法可用可以加直接看BluetoothDevice.class的源碼。
藍牙配對狀態的改變,我們通過註冊boundReceiver來監聽:

private BroadcastReceiver boundReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context , Intent intent) {
        String action = intent.getAction() ;
        if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (!mDevice.equals(device)) {//得到的設備不是剛剛點擊的設備
                return ;
            }
            switch(device.getBondState()) {//得到設備的配對狀態
                case BluetoothDevice.BOND_BONDING:
                    //配對中...
                    breake;
                case BluetoothDevice.BOND_BONDED:
                    //配對成功
                    for (TBlueToothInfo info : datas ) {
                        if (info.getDeviceAddr().equals(device.getAddress())) {
                            String name = info.getDeviceName();
                            name = name.replace("未配對","已配對");
                            info.setDeviceName(name) ;  
                        }
                    }
                    adapter.notifyDataSetChanged();
                    unregisterReceiver(boundReceiver) ;
                    break ;
                case BluetoothDevice.BOND_NONE:
                    //配對成功
                    for (TBlueToothInfo info : datas ) {
                        if (info.getDeviceAddr().equals(device.getAddress())) {
                            String name = info.getDeviceName();
                            name = name.replace("未配對","已配對");
                            info.setDeviceName(name) ;  
                        }
                    }
                    adapter.notifyDataSetChanged();
                    //註銷boundReceiver
                    unregisterReceiver(boundReceiver) ;
                    break ;
                default:
                    break;
            }
        }
    }
}

現在,藍牙的打開、搜索、配對和取消配對就已經全部實現了,也算是完成了藍牙最基本的功能。完成配對後就可以開始連接並傳輸數據了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章