android 藍牙鎖應用開發實例(三)藍牙相關功能實現【第一部分】

本人水平有限,文章中如果出現什麼不正確或者模糊的地方,還請各位小夥伴留下評論,多多指教 : )

正式開始前的話

  之前2篇關於藍牙的文章是很久之前寫的博文,算是CSDN的開篇之作,裏面存在許多的不足,而且後面也沒能堅持下來,有一些小夥伴私信我要這部分的代碼,剛好最近手上的一個項目也是和藍牙有關,所以今天特意特意把這個項目又下下來,一方面總結最近一段時間關於藍牙的開發,另一方也算把前兩篇的坑給填上~~

  至於這個項目當中涉及到的其他內容,例如數據庫的使用,界面的編寫等都不再在這個系列的博客做詳細介紹(當時寫的太菜了……沒啥好介紹的(:з」∠)有興趣的小夥伴屆時可以看看源碼~),本系列的博客將會把重點放在藍牙的處理上。這裏附上之前寫的兩篇文章地址,有興趣的小夥伴可以去看一看~~
android 藍牙鎖應用實例開發(一) 簡介
android 藍牙鎖應用開發實例(二)客戶端基本頁面

藍牙開發梳理

整體思路

  我一直認爲,無論做什麼樣的開發,一定要思路先行,在瞭解大致的工作流程後,才便於我們後面對各種瑣碎細節的研究。不僅能加深理解,還能養成良好的思維模式。接下來就帶大家簡單梳理一下藍牙開發的流程。

(1)獲取藍牙開發的權限
(2)掃描附近的藍牙設備,並將這些設備加入到devices列表
(3)選擇要配對的設備,將次設備加入到已配對設備列表
(4)進行數據通信或其他操作
(5)接觸配對狀態

若干年之後,你可能具體的代碼細節忘記 ,但是上面的步驟應該是做過一次開發就不會忘記了。

在第2步和第3部中涉及了2個列表,一個是【設備列表】,一個是【匹配設備列表】。

設備列表——是指附近的可見藍牙設備,但是還沒匹配
匹配設備列表——是指已經完成匹配的列表

大家要理解這2種列表的區別。因爲列表的區別,也代表了設備狀態。

即【未匹配狀態】、【匹配狀態】、【配對狀態】

未匹配,就是指從來沒有匹配過的設備。
匹配狀態,就是指設備間已經相互完成了身份驗證,處於待配對(待建立Socket)狀態。

不知大家還記不記得,以前藍牙配對的時候,手機會彈出一個對話框,提示輸入pin碼,其實也就是提前約定的一個配對碼,到後來,手機與與手機之間的連接就不需要配對碼了(實際上是程序內部完成了配對的過程)。

當然,手機與一些藍牙硬件(例如單片機+藍牙模塊的組合)配對時,還是需要輸入pin碼(不過也能通過程序自動完成驗證)

那麼什麼配對狀態呢?

配對的過程,其實就是Socket通信的一個過程,兩個藍牙設備僅僅匹配是還不能夠傳遞數據的,只有當二者建立了Socket通道之後,才能進行數據的傳遞。

好了,基本是思路差不多介紹完了,爲了加深大家對藍牙的理解,我這裏再把上面的內容,通過圖的形式再總結一下。同時我也會把藍牙相關操作的核心API給列在次圖中,讓大家對下一節的內容有大致的瞭解

這裏寫圖片描述

接下來,將對涉及藍牙操作的幾個核心API進行介紹。

核心API

本節內容將講解藍牙操作的核心API,這裏說明一下,android的藍牙開發有涉及到不同的藍牙種類,例如低功耗藍牙(BluetoothGatt)、藍牙健康(BlueToothHealth)等,這裏介紹的依然是常規的藍牙開發API

再多囉嗦一句……API查看哪家強……那肯定是官方文檔啦~當然是對於英文基礎不錯的小夥伴,不過英語一般的小夥伴也不用太擔心,畢竟有很多優秀的翻譯軟件及API中文站,這裏我提供一個傳送們,希望深入理解的BlueTooth或者其他API的小夥伴有空可以經常去看看。

Bluetooth www.android-doc.com

BlueToothAdapter

簡介

這個類代表着本地的藍牙適配器,讓你可以從事各種與藍牙相關的操作,例如開始和停止設備的查找;查詢已匹配的設備並以集合的形式返回;通過已知的設備地址,實例化一個BlueToothDevice;創建一個BluetoothServerSocket來監聽來自其他設備的鏈接請求等等,總之要想使用本機的藍牙,這個類是極其重要的。

getDefaultAdapter()

獲取本地的藍牙適配器,一般的調用代碼如下:

        //獲取本地藍牙適配器
        bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();

getBondedDevices()

獲取已經匹配的設備列表,並以set集合的方式返回
調用代碼如下:

    /*
    *獲取已經配對的設備
    * */
        private void setPairingDevice() {
        Set<BluetoothDevice> devices=bluetoothAdapter.getBondedDevices();
        if(devices.size()>0){ //存在已配對過的設備
           //利用for循環讀取每一個設備的信息
            for(Iterator<BluetoothDevice> it = devices.iterator(); it.hasNext();){
                BluetoothDevice btd=it.next();
                ```````
            }
        }else{   
        //不存在已經配對的藍牙設備
                    }
    }

isDiscovering()

判斷當前是否正在查找設備,是返回true

startDiscovery()

這裏需要注意一下,由於搜素是一個耗時操作,所以這個方法應該在線程中去調用,同時需要配合着廣播去使用,關於廣播的內容,將在下一個小節中詳細講解。
開始查找設備,一般的調用代碼如下:

/**
     * 開始附加設備的查找
     */
    private void doDiscovery() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //如果adapter正在查詢,停止查詢
                if(bluetoothAdapter.isDiscovering()){
                    bluetoothAdapter.cancelDiscovery();
                }
                bluetoothAdapter.startDiscovery();
            }
        }).start();
    }

這裏再注意一個細節,那就是如果當前的adapter正在查找,那麼必須停止當前查找,然後再重新查找,這是因爲查找操作佔用很多的系統資源,我們需要避免重複的查找

cancelDiscovery()

取消查找設備,在上面的已經調用過

getRemoteDevice(String address)

根據一個藍牙設備的地址來獲取該地址,這個方法返回一個BlueToothDevice的實例

enable() | disable()

字面意思,打開或者關閉本機的藍牙。
一般的調用代碼如下:

//獲取藍牙適配器
        mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
        //如果藍牙沒有打開則打開藍牙
        if (!mBluetoothAdapter.isEnabled()) {
            //請求用戶開啓
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_COMMUNICATE);
        }

getAddress() | getName() | getState()

getAddress()獲取本地藍牙地址
getName()獲取本地藍牙名稱
getState()獲取本地藍牙適配器當前狀態

listenUsingRfcommWithServiceRecord(String name,UUID uuid)

listenUsingRfcommWithServiceRecord(String name,UUID uuid)根據名稱,UUID創建並返回BluetoothServerSocket。這個方法是創建BluetoothSocket服務器端不可缺少的一步。

BluetoothDevice

簡介

這個類代表一個遠程設備,它能夠讓我們與一個其他相關設備創建連接,或者查詢與此設備相關的信息,例如名稱(name)、地址(address)、連接狀態(boud state)

createRfcommSocketToServiceRecord(UUIDuuid)

根據UUID創建並返回一個BluetoothSocket。

getAddress() | getName() | getState()

getAddress()獲取Address設備的藍牙地址
getName()獲取Address設備的地藍牙名稱
getState()獲取Address設備的藍牙適配器當前狀態

BluetoothServerSocket和BluetoothSocket

這裏把這兩個API放在一起說,這兩個方法相互對應,ServerSocket對應的服務端,Socket對應的是客戶端,具體內容在下一節中介紹

至此,所有的比較重要的API都已經介紹完畢了,現在正式進入代碼編寫的階段。

編碼階段

程序功能

本篇文章只完成附近藍牙設備的搜索和鏈接,關於數據通信的部分將在下一篇文章中介紹
功能:
(1)搜索附近藍牙設備
(2)與附近藍牙設備配對

程序設計

代碼目錄如下
這裏寫圖片描述

類詳解

DeviceListAdapter

這個類是自定義的BaseAdapter,作爲用來顯示藍牙設備的listView的適配器

源碼:

/**
 * Created by dell on 2016/9/22.
 * 存放以匹配藍牙設備的ListView的Adapter
 */
public class DeviceListAdapter extends BaseAdapter {
    //標識符,詳見【說明1】
    private final int NEAR_DEVICE=1;
    private final int PAIRING_DEVICE=2;
    //存儲設備的容器
    private DeviceListListener deviceListListener;
    private ArrayList<Device> devices;
    private BluetoothAdapter mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
    private LayoutInflater inflater;
    private Context context;
    //用於標示附近設備和以配對設備的標識
    private int flag;
    //接口
    public interface DeviceListListener{
        //更新ArrayList
         void notifyArrayList();
        //提示取消配對成功
        void cancelSuccess();
        //配對成功
        void bindSuccess();
    }

    public DeviceListAdapter(Context context, ArrayList<Device> devices){
        this.devices=devices;
        this.context=context;
        inflater=LayoutInflater.from(context);

    }

    //爲adapter設置一個flag
    public void setFlag(int i ){
        flag=i;
    }
    public void setDeviceListListener(DeviceListListener deviceListListener){
        this.deviceListListener=deviceListListener;
    }

    @Override
    public int getCount() {
        return devices.size();
    }

    @Override
    public Object getItem(int i) {
        return devices.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;
        //如果View是空,則實例化viewHolder
        if(view==null){
            viewHolder=new ViewHolder();
            view=inflater.inflate(R.layout.binding_device_list_item,null);
            viewHolder.deviceAddress= (TextView) view.findViewById(R.id.device_address);
            viewHolder.deviceName= (TextView) view.findViewById(R.id.device_name);
            view.setTag(viewHolder);
        }else{
            viewHolder= (ViewHolder) view.getTag();
        }
        final Device device=devices.get(i);
        //設置設備名稱和地址
        viewHolder.deviceAddress.setText(device.getAddress());
        viewHolder.deviceName.setText(device.getDevName());
        //爲view設置點擊事件
        switch (flag){
            case NEAR_DEVICE:
                setNearDeViceEvent(view,device);
                break;
            case PAIRING_DEVICE:
                setPairingDeviceEvent(view,device);
                break;
        }
        return view;
    }


    /**
     * 爲配對設備ListView設置相關事件
     */
    private void setPairingDeviceEvent(View view,final Device device) {
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });
        view.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                final AlertDialog.Builder builder =new AlertDialog.Builder(context);
                builder.setTitle("提示").
                        setMessage("您確定要與該設備取消配對嗎?").
                        setPositiveButton("確定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                BlueToothUnit.unBindDevice(mBluetoothAdapter,device,deviceListListener);

                            }
                        }).show();
                return false;
            }
        });
    }


    /**
     * 爲附近設備ListView設置相關事件
     */
    private void setNearDeViceEvent(View view,final Device device) {
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final AlertDialog.Builder builder=new AlertDialog.Builder(context);
                 builder.setTitle("提示").
                        setMessage("您確定要和此設備配對嗎?")
                        .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                try {
                                    BlueToothUnit.bindTargetDevice(mBluetoothAdapter,device,deviceListListener);
                                } catch (NoSuchMethodException e) {
                                    e.printStackTrace();
                                } catch (InvocationTargetException e) {
                                    e.printStackTrace();
                                } catch (IllegalAccessException e) {
                                    e.printStackTrace();
                                }
                            }
                        }).
                        setNegativeButton("取消",null).
                        show();
            }
        });

    }
    class ViewHolder
    {
        TextView deviceName;
        TextView deviceAddress;
    }
}

【說明1】
因爲這個adapter既要被已匹配設備的listView使用,也要被附近設備的listView使用,而兩個listView對應 item點擊事件又是不一樣的,所以,在一開始設置了2個標識符,用以區分。
【說明2】
與藍牙有關的操作,都封裝在了BluetoothUnit當中
【說明3】
此類是一個標準BaseAdapter的寫法,getView()當中通過LayoutInfater加載了一個自定義的佈局,同時使用了viewHolder對listView進行優化。

Device

一個標準的Java Bean,表示一個藍牙設備的實例

public class Device {
    //藍牙地址
    private String address;
    //設備名稱
    private String devName;

    public Device(String devName, String address) {
        this.address = address;
        this.devName = devName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getDevName() {
        return devName;
    }

    public void setDevName(String devName) {
        this.devName = devName;
    }
}

BlueToothUnit

封裝了與藍牙操作相關的方法

public class BlueToothUnit {
    private final String TAG = "--BlueToothUnit--";
    public static void unBindDevice(BluetoothAdapter mBluetoothAdapter, Device device, DeviceListAdapter.DeviceListListener  deviceListListener){
        //利用反射的方法取消配對
        BluetoothDevice device0 = mBluetoothAdapter.getRemoteDevice(device.getAddress());
        try {
            Boolean returnValue ;
            Method m = device0.getClass().getMethod("removeBond");
            returnValue = (Boolean) m.invoke(device0);
            if (returnValue)
                deviceListListener.cancelSuccess();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //成功取消配對後更新listView
        deviceListListener.notifyArrayList();
    }
    /**
     * 配對指定的設備
     */
    public static void bindTargetDevice(BluetoothAdapter localBluetoothAdapter, Device device, DeviceListAdapter.DeviceListListener deviceListListener) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //在配對之前,一定要停止搜搜
        if (localBluetoothAdapter.isDiscovering()) {
            localBluetoothAdapter.cancelDiscovery();
        }
        //獲取配對的設備
        BluetoothDevice btDev = localBluetoothAdapter.getRemoteDevice(device.getAddress());
        Boolean returnValue;
        if (btDev.getBondState() == BluetoothDevice.BOND_NONE) {
            //利用反射方法調用BluetoothDevice.createBond(BluetoothDevice remoteDevice);
            Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
            Log.d("---", "開始配對");
            returnValue = (Boolean) createBondMethod.invoke(btDev);
            if (returnValue){
                Log.d("---", "bindTargetDevice "+"配對成功");
                deviceListListener.bindSuccess();

            }
        }
    }

    /**
     * @param bluetoothAdapter 本地藍牙適配器
     * 開始藍牙設備的搜索
     */
    public static void findAvailableDevices(final BluetoothAdapter bluetoothAdapter) {
        //開始搜索工作
        new Thread(new Runnable() {
            @Override
            public void run() {
                //如果藍牙正在搜索,則停止搜索,然後再重新開始搜索
                if (bluetoothAdapter.isDiscovering()) {
                    bluetoothAdapter.cancelDiscovery();
                }
                //調用此方法會不斷的發送廣播,用戶只需自定義一個receiver接受即可
                bluetoothAdapter.startDiscovery();
            }
        }).start();
    }
}

通過反射的方法完成連接或取消配對

BtBrocastReceiver

接受藍牙相關的廣播,並作出相應的操作

public class BtBroadcastReceiver extends BroadcastReceiver {
    private final String TAG="--broadcastReceiver--";
    private ArrayList<Device> nearDevices;
    private DeviceListAdapter adapter;
    private ProgressDialog progressDialog;
    public interface  BroadcastListener{
         void finishSearch();
         void bindSuccess();
    }
    private BroadcastListener broadcastListener;
    public BtBroadcastReceiver(Context context, ArrayList<Device> nearDevices,DeviceListAdapter adapter,BroadcastListener broadcastListener){
        this.nearDevices=nearDevices;
        this.broadcastListener=broadcastListener;
        this.adapter=adapter;
        progressDialog=new ProgressDialog(context);
        progressDialog.setTitle("正在查詢附近設備");
        progressDialog.setCancelable(false);
        progressDialog.setMessage("請稍等……");
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        switch (action){
            case BluetoothAdapter.ACTION_DISCOVERY_STARTED: //索索開始
                Log.w(TAG,"--開始尋找設備");
                progressDialog.show();
                //清空nearList裏面的數據
                nearDevices.clear();
                break;

            case BluetoothDevice.ACTION_FOUND: //發現設備
                Log.w(TAG,"--找到設備");
                //拿到藍牙設備
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                //如果此設備的狀態是還未匹配,則把它加入到設備列表當中
                if(device.getBondState()==BluetoothDevice.BOND_NONE) {
                    Device d=new Device(device.getName(),device.getAddress());
                    nearDevices.add(d);
                    adapter.notifyDataSetChanged();
                }
                progressDialog.setMessage("已找到"+nearDevices.size()+"臺設備……");
                break;

            case BluetoothDevice.ACTION_BOND_STATE_CHANGED: //狀態改變
                device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_BONDING:
                        Log.w("BlueToothTestActivity", "正在配對......");
                        progressDialog.setTitle("正在配對");
                        progressDialog.setMessage("請稍等……");
                        progressDialog.show();
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        Log.w("BlueToothTestActivity", "配對完成");
                        broadcastListener.bindSuccess();
                        progressDialog.dismiss();
                        break;
                    case BluetoothDevice.BOND_NONE:
                        Log.w("BlueToothTestActivity", "取消配對");
                    default:
                        break;
                }

                break;

            case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:// 搜索完成
                Log.w("finish:----", "搜索完成!");

                progressDialog.dismiss();
                if(nearDevices.size()==0){
                    Toast.makeText(context,"附近沒有可用設備",Toast.LENGTH_SHORT).show();
                }else{
                    Toast.makeText(context,"搜索到"+nearDevices.size()+"臺設備",Toast.LENGTH_SHORT).show();
                }
                broadcastListener.finishSearch();

                break;

        }
    }
}

這個類主要是監聽藍牙相關的廣播,這些廣播的註冊邏輯放在了PairingDeviceActivity當中

PairingDeviceActivity

顯示已配對設備的listView,以及搜索附近的設備和廣播的註冊

/**
 * Created by dell on 2016/9/22.
 * 本類用於顯示已經和手機匹配了的設備,並且可以搜尋附近的設備
 */
public class PairingDeviceActivity extends AppCompatActivity implements BtBroadcastReceiver.BroadcastListener {
    private final String TAG="--Pairing--";
    //狀態標識符
    private final int NEAR_DEVICE=1;
    private final int PAIRING_DEVICE=2;
    private TextView emptyView;
    //顯示已經匹配的設備
    private ListView pairingListView;
    //藍牙適配器
    private BluetoothAdapter bluetoothAdapter;
    //存儲以匹配設備的容器
    private ArrayList<Device> pairingDevices=new ArrayList<>();
    //存儲附近設備的容器
    private ArrayList<Device> nearDevices=new ArrayList<>();

    //已匹配設備的Adapter
    private DeviceListAdapter pairingDeviceListAdapter;
    //附近設備的Adapter
    private DeviceListAdapter nearDeviceListAdapter;

    //匹配附近設備時彈出的alter
    private AlertDialog alertDialog;

    private LayoutInflater inflater;
    //是否進行了廣播接收器註冊的標識符
    private boolean hasRegister=false;
    //廣播接收器
    private BtBroadcastReceiver mReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.pairing_device_activity);

        //初始化控件
        init();

        //初始化適配器
        initAdapter();

        //獲取當前匹配的數據
        setPairingDevice();

        nearDeviceListAdapter.setDeviceListListener(new DeviceListAdapter.DeviceListListener() {
            @Override
            public void notifyArrayList() {
            }

            @Override
            public void cancelSuccess() {
            }

            @Override
            public void bindSuccess() {
              //  Toast.makeText(PairingDeviceActivity.this,"配對成功!",Toast.LENGTH_SHORT).show();
            }
        });
        //添加更新ListView的方法
        pairingDeviceListAdapter.setDeviceListListener(new DeviceListAdapter.DeviceListListener() {
            @Override
            public void notifyArrayList() {
                pairingDevices.clear();
                //讓adapter獲得以匹配的設備
                setPairingDevice();
                pairingDeviceListAdapter.notifyDataSetChanged();
            }

            @Override
            public void cancelSuccess() {
                Toast.makeText(PairingDeviceActivity.this,"已取消配對",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void bindSuccess() {
                Toast.makeText(PairingDeviceActivity.this,"配對成功!",Toast.LENGTH_SHORT).show();
            }
        });
}
    /*
        * 初始化ui及其他組件
        * */
    private void init() {
        pairingListView= (ListView) findViewById(R.id.list_binding_devices);
        emptyView= (TextView) findViewById(R.id.tv_empty);
        inflater=LayoutInflater.from(PairingDeviceActivity.this);


    }

    /**
     * 初始化適配器
     */
    private void initAdapter() {
        //獲取本地藍牙適配器
        bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
        //匹配設備和附加設備list的適配器
        nearDeviceListAdapter=new DeviceListAdapter(this,nearDevices);
        pairingDeviceListAdapter=new DeviceListAdapter(this,pairingDevices);
        //設置adapter的標識符
        pairingDeviceListAdapter.setFlag(PAIRING_DEVICE);
        nearDeviceListAdapter.setFlag(NEAR_DEVICE);
        //list與adapter綁定
        pairingListView.setAdapter(pairingDeviceListAdapter);

        //初始化接收器
        mReceiver=new BtBroadcastReceiver(PairingDeviceActivity.this,nearDevices,nearDeviceListAdapter,this);

    }

    //尋找附近設備
    public void onClickFindNearDevices(View view){
        //開始查詢工作
        doDiscovery();
    }

    /**
     * 開始附加設備的查找
     */
    private void doDiscovery() {
        BlueToothUnit.findAvailableDevices(bluetoothAdapter);
    }

    @Override
    protected void onStart() {
        super.onStart();
        //註冊廣播
        if(!hasRegister) {
            hasRegister = true;
            //尋找到設備的過濾器
            IntentFilter filterStar = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            //綁定狀態改變
            IntentFilter changeFilter= new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
            //搜索完成
            IntentFilter filterFinish = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
            //開始搜搜
            IntentFilter startSearch=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
            registerReceiver(mReceiver,startSearch);
            registerReceiver(mReceiver, filterFinish);
            registerReceiver(mReceiver, filterStar);
            registerReceiver(mReceiver, changeFilter);
        }
        //註冊的廣播在活動結束時需要註銷
    }



    /*
    *獲取已經配對的設備
    * */

    private void setPairingDevice() {
        Set<BluetoothDevice> devices=bluetoothAdapter.getBondedDevices();
        if(devices.size()>0){ //存在已配對過的設備
            emptyView.setVisibility(View.GONE);
            pairingListView.setVisibility(View.VISIBLE);
            pairingDevices.clear();
            for(Iterator<BluetoothDevice> it = devices.iterator(); it.hasNext();){
                BluetoothDevice btd=it.next();
                Device device =new Device(btd.getName(),btd.getAddress());
                Log.d("---", "setPairingDevice: name "+btd.getName()+" address is "+btd.getAddress());
                //將device添加到PairingDeviceActivity當中的devices,注意this
                pairingDevices.add(device);
            }
        }else{   //不存在已經配對的藍牙設備
            emptyView.setVisibility(View.VISIBLE);
            pairingListView.setVisibility(View.GONE);
            Toast.makeText(this,"不存在已配對設備",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //如果藍牙適配器正在掃描,則停止掃描
        if(bluetoothAdapter!=null&&bluetoothAdapter.isDiscovering())
            bluetoothAdapter.cancelDiscovery();

        //註銷廣播
        if(hasRegister){
            hasRegister=false;
            unregisterReceiver(mReceiver);
        }
    }


    @Override
    public void bindSuccess() {
        Log.d(TAG, "bindSuccess: ");
        alertDialog.dismiss();
        Toast.makeText(PairingDeviceActivity.this,"配對成功",Toast.LENGTH_SHORT).show();
        //更新數據
        setPairingDevice();
        pairingDeviceListAdapter.notifyDataSetChanged();
    }

    //廣播完成搜索時
    @Override
    public void finishSearch() {
        //停止查詢
        //如果藍牙適配器正在掃描,則停止掃描
        if(bluetoothAdapter!=null&&bluetoothAdapter.isDiscovering()){
            Log.d("---", "finishSearch: " +"停止掃描");
            bluetoothAdapter.cancelDiscovery();
        }
        AlertDialog.Builder builder=new AlertDialog.Builder(PairingDeviceActivity.this);
        View view1=inflater.inflate(R.layout.near_devices_alertdialog,null);
        ListView nearAvailableListView= (ListView) view1.findViewById(R.id.list_near_devices);
        //爲附近可用設備的list綁定adaper
        nearAvailableListView.setAdapter(nearDeviceListAdapter);
        alertDialog=builder.setTitle("附近的設備")
                .setView(view1)
                .create();
        alertDialog.show();
    }
}

【說明1】PairingDeviceActivity實現了BtBroadcastReceiver的接口,這個接口中需要重寫三個方法,finishSearch()和bindSuccess()表示完成搜索和綁定成功。

總結

至此,就完成了藍牙的搜索和配對,上面的代碼還請大家更多關注邏輯上的處理,完整的項目代碼,會在下此寫藍牙數據通信時一併貼出。

發佈了43 篇原創文章 · 獲贊 69 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章