Android 教你如何寫藍牙程序1——消息傳遞、啓動藍牙

注意:我的這個工程的目的主要是爲了連接單片機的HC-06藍牙模塊
參考資料:
藍牙的資料:
Android 藍牙開發(1)
Android 藍牙開發(2)
Android 藍牙開發(3)

1 消息傳遞

我打算把講解分成這三個部分,這三個部分是相對獨立的,你最好一塊一塊學,我之前一口氣學了之後,感覺非常難理解。這三個部分是:啓動藍牙功能、獲取目標藍牙設備的信息、與藍牙設備建立連接。

在講藍牙之前,你需要先知道兩個關於Android信息傳遞的重要知識點,這兩個知識點在其他地方也是用的到的。

1.1 廣播監聽

Android廣播事件,這個其實很好理解,你可以發送廣播消息,你也可以接收廣播消息。廣播消息可能來自你自己,也可能來自系統。主要用於監聽某些事件的變化,假設該事件爲actionA,當actionA發生變化的時候,你可以利用廣播監聽進入對應的函數當中,執行你的命令。
這部分知識不難,網上教程很多,我就不自己寫了。
你需要學會如下內容:
如何寫廣播監聽函數?如何註冊廣播監聽函數? 如何發送廣播?

1.2 Handler、Message、Looper

這三個比較麻煩需要花時間消化一下
Android的消息機制(一)
Android的消息機制(二)
你要知道以下內容:
如何在主線程中創建一個Handler類的實例,來實現信息接收的功能?
如何在其他地方用Message類包裝數據,用主線程的handler實例來向主線程發送信息?

如何在子線程中利用Looper和Handler創建一個子線程的信息接收器?

這個網上也有很多教程,不過我還是再說幾句。
假設消息傳遞者 A 打算傳遞消息給 B,分爲兩種情況:B 是主線程,或 B 是子線程。爲什麼區分這兩種情況。原因在於,利用Handle轉遞消息時會進入由循環程序中,該循環程序是在Looper 中實現的,而每個線程只能有一個Looper。主線程默認是有一個 Looper 的,子線程的Looper需要自己創建。 在該循環程序中,會持續判斷是否有消息傳過來,有就處理,沒有就繼續循環。消息處理的機制是由MessageQueue實現的,它的本質是隊列,就是先到的消息先處理,後到的消息後處理。

1.2.1 消息接收者 B 如果是主線程

由於默認有一個Looper,所以直接創建一個 Handler 類的成員就好了

private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //消息傳遞是由Message類進行封裝的。
        switch (msg.what)
        {
            //寫入判斷+處理程序
        }
    }
};
1.2.2 消息接收者 B 如果是主線程

至於爲什麼下列語句就可以使得 mHandler 與該線程的 Looper 綁定,大家可以去網上查查,是由靜態實現的。

//在子線程中
void run(){
	Looper.prepare();                            //創建一個Looper
	mHandler= new Handler() {                    //通過該語句處理消息
	    public void handleMessage(Message msg) {
	        int what = msg.what;
	        Object obj = msg.obj;
	        switch (what) {
	            //此處寫入對應的消息處理程序
	        }
	    }
	};
	Looper.loop();                                //打開消息泵
}
1.2.3 發送消息
//用Message類進行封裝
Message msg = new Message();
msg.what = 1;//該參數指定消息類型
msg.arg1 = 1;//該參數看你的需求
msg.arg2 = 1;//該參數看你的需求
msg.obj = "這裏可以存儲任意類型的數據,不過接收後,記得強轉";//這裏存放消息
handler.sendMessage(msg);//發送消息
//注意,handler必須是目標的handler,你可以使得主線程創建的handler傳進這裏來

2 啓動藍牙

先講講最簡單的部分,啓動藍牙。

2.1 藍牙權限

在 AndroidManifest.xml 文件中添加權限
在 manifest 屬性中,application 屬性上面添加下面內容

<uses-permission android:name="android.permission.BLUETOOTH" />
<!--允許啓動藍牙功能-->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!--允許程序進行發現和配對新的藍牙設備-->

2.2 啓動藍牙功能

我現在只要實現使手機啓動藍牙這個功能。
1)獲取藍牙適配器,後面要用到

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

2)嘗試開啓藍牙功能

Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(enableBtIntent);
//我這裏是另外寫了一個類,所以需要傳入主類的 Context 類實例
//如果是在主類中寫,只需要寫 startActivity(enableBtIntent);

3)廣播監聽藍牙開啓狀態
其實由2)就可以實現開啓藍牙的功能了,但是如果你想檢測藍牙什麼時候開啓,然後再自動運行指定程序的話,就需要利用廣播監聽。
先建立廣播監聽的接收類

private class BluetoothStateBroadcastReceive extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();//取出動作的字符串
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            switch (action) {//判斷來自哪一個動作
            	//動作來自藍牙功能變化
                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);//檢測當前藍牙狀態
                    if (blueState == BluetoothAdapter.STATE_ON) {
                        try {
                            //藍牙已經啓動,可以註銷該廣播監聽了
                           context.unregisterReceiver(bluetoothStateBroadcastReceive);
                        } catch (Exception e) {
                            Log.d("藍牙狀態", "註銷監聽失敗,監聽實例不存在");
                        }
                    }
                    //這裏可以執行下一步
                    
            }
        }
    }

4)註冊廣播監聽函數

//創建監聽函數的實例,該變量最後是類中的成員變量,因爲註銷的時候需要用該實例
BluetoothStateBroadcastReceive bluetoothStateBroadcastReceive = new BluetoothStateBroadcastReceive();
//指定監聽動作
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);      
//綁定監聽動作和監聽接收的函數
context.registerReceiver(bluetoothStateBroadcastReceive,filter);

最後附上啓動藍牙部分的完整代碼

public class BlueToothTool {
	//建立成員變量
	//來自佈局的信息
    BluetoothAdapter mBluetoothAdapter;//藍牙適配器
    Context context;
    Handler handlerToMain;

	//構造函數
	private BlueToothTool(){
		super();
	}

	public BlueToothTool(BluetoothAdapter mBluetoothAdapter, Context context, Handler handler){
		this.mBluetoothAdapter = mBluetoothAdapter;
		this.context = context;
		this.handlerToMain = handler;
		//打開藍牙功能
		BlueToothFuctionStart();
    }

	/**
     * 1.嘗試打開藍牙功能
     */
    private void BlueToothFuctionStart(){
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if(mBluetoothAdapter!=null){
            //檢測是否開啓了藍牙功能,注意startActivity會開啓子線程,無法在此語句後面直接判斷藍牙功能是否被開啓
            if(!mBluetoothAdapter.isEnabled()) {
                //嘗試開啓藍牙功能
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                context.startActivity(enableBtIntent);
                //註冊對藍牙狀態功能的監聽事件
                //實例化IntentFilter對象
                IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);      //可以用構造方法添加Action
                context.registerReceiver(bluetoothStateBroadcastReceive,filter);
            }else{
                //直接執行下一步
                //獲取過去配對過的信息
                //2.1查找已配對的設備
            }
        }else{
            Toast.makeText(context,"您的設備不支持藍牙系統",Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 1.1通過廣播對藍牙狀態進行監聽
     */
     private BluetoothStateBroadcastReceive bluetoothStateBroadcastReceive = new BluetoothStateBroadcastReceive();
    private class BluetoothStateBroadcastReceive extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            switch (action) {
                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                    if (blueState == BluetoothAdapter.STATE_ON) {
                        try {
                            //註銷對象
                            context.unregisterReceiver(bluetoothStateBroadcastReceive);
                        } catch (Exception e) {
                            Log.d("藍牙狀態", "註銷監聽失敗,監聽對象不存在");
                        }
                    }
                    //執行下一步
                    //獲取過去配對過的信息
                    //2.1查找已配對的設備
            }
        }
    }
}

這是第二篇內容:
Android 教你如何寫藍牙程序2——獲取目標信息

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