Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android源碼分析]藍牙配對之jni之上的點點滴滴

[Android源碼分析]藍牙配對之jni之上的點點滴滴

編輯:關於Android編程

??

在之前曉東已經和大家分析完成了藍牙打開和藍牙搜索的過程了,在搜索到設備的下一步我們要做的就是藍牙的配對了。本文曉東將和大家一起來看看藍牙配對究竟涉及到了哪些內容。

1、UI上的點擊設備開始

在android中,對設備的點擊都是在onclicked函數中實現的,所以我們就從這個函數開始分析了:

 

 

//對對應設備點擊之後的操作
    void onClicked() {
        int bondState = mCachedDevice.getBondState();
        //若是該設備已經連接了,就斷開連接
        if (mCachedDevice.isConnected()) {
            askDisconnect();
        } else {
            // Single link version, reject the second connect request
            if (mLocalAdapter.isSingleLinkVersion() == true &&
                    mLocalAdapter.getAdapterConnectionState() != BluetoothAdapter.STATE_DISCONNECTED) {
                Context context = getContext();
                String toastMsg = context.getString(R.string.bluetooth_single_slave_pair_only_device);
                Toast.makeText(getContext(), toastMsg, Toast.LENGTH_SHORT).show();
                return;
            }

        //若是已經配對過了,就開始連接
            if (bondState == BluetoothDevice.BOND_BONDED) {
                mCachedDevice.connect(true);
        //若是還沒有配對,則開始配對
            } else if (bondState == BluetoothDevice.BOND_NONE) {
                pair();
            }
        }
}

 

所以,其實同樣一個點擊在設備處於不同狀態下是有不同操作的,毫無疑問,最開始我們總是位於最初的狀態,這個時候的點擊就是開始配對了。我們去看看配對是怎麼做的:

 

private void pair() {
        //開始配對
        if (!mCachedDevice.startPairing()) {
        //配對出問題,顯示error信息
            Utils.showError(getContext(), mCachedDevice.getName(),
                    R.string.bluetooth_pairing_error_message);
        }
    }

 

調動的是startpairing函數來實現真正的配對操作:

 

 boolean startPairing() {
        // Pairing is unreliable while scanning, so cancel discovery
        //若是正在掃描,就先cancel掉掃描操作
        if (mLocalAdapter.isDiscovering()) {
            mLocalAdapter.cancelDiscovery();
        }
        //開始配對,這就到framework層了
        if (!mDevice.createBond()) {
            return false;
        }
        //配對後自動連接
        mConnectAfterPairing = true;  // auto-connect after pairing
        return true;
    }

 

2、framework層的配對操作分析

上面的操作會真正調用下面這個framework的函數:

 

public synchronized boolean createBond(String address) {
        //看是否可以配對?比如有沒有設備正在配對之類
        if (!isBondingFeasible(address)) return false;
        //開始配對。timeout是1分鐘,詳細分析見4
        if (!createPairedDeviceNative(address, 60000  /*1 minute*/ )) {
            return false;
        }
        //把這個地址賦值到pendingoutgonigbonding中
        mBondState.setPendingOutgoingBonding(address);
			//設置狀態為bonding
        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
        return true;
    }

 

3、狀態改變到bonding的分析

設置bond的狀態

 

 

    /*package*/ synchronized boolean setBondState(String address, int state) {
        return setBondState(address, state, 0);
    }

    /*package*/ synchronized boolean setBondState(String address, int state, int reason) {
        mBondState.setBondState(address.toUpperCase(), state, reason);
        return true;
}

    public synchronized void setBondState(String address, int state) {
        setBondState(address, state, 0);
    }

    /** reason is ignored unless state == BOND_NOT_BONDED */
    public synchronized void setBondState(String address, int state, int reason) {
        if (DBG) Log.d(TAG, setBondState  + address +   + state + reason:  + reason);
    //檢查狀態是否真的改變
        int oldState = getBondState(address);
        if (oldState == state) {
            return;
        }

        // Check if this was an pending outgoing bonding.
        // If yes, reset the state.
        //看是不是從bonding的狀態變化的,若是,則把mPendingOutgoingBonding位清空
        if (oldState == BluetoothDevice.BOND_BONDING) {
            if (address.equals(mPendingOutgoingBonding)) {
                mPendingOutgoingBonding = null;
            }
        }
        if (state == BluetoothDevice.BOND_BONDED) {
            boolean setTrust = false;
            if (mPairingRequestRcvd.contains(address)) setTrust = true;

            mService.addProfileState(address, setTrust);
            mPairingRequestRcvd.remove(address);

        } else if (state == BluetoothDevice.BOND_BONDING) {
                //若是bonding,則先得到a2dpproxy和headsetproxy,這個是為了後面的連接做准備的
            if (mA2dpProxy == null || mHeadsetProxy == null) {
                getProfileProxy();
            }
        } else if (state == BluetoothDevice.BOND_NONE) {
            mPairingRequestRcvd.remove(address);
        }

        //主要是bonded和none的處理,我們暫時不看
        setProfilePriorities(address, state);

        if (DBG) {
            Log.d(TAG, address +  bond state  + oldState +  ->  + state
                +  ( + reason + ));
        }

 

3.1 getProfileProxy的分析

 

 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
                                   int profile) {
        if (context == null || listener == null) return false;

        //新建對應profile
        if (profile == BluetoothProfile.HEADSET) {
            BluetoothHeadset headset = new BluetoothHeadset(context, listener);
            return true;
        } else if (profile == BluetoothProfile.A2DP) {
            BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
            return true;
        } else if (profile == BluetoothProfile.INPUT_DEVICE) {
            BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
            return true;
        } else if (profile == BluetoothProfile.PAN) {
            BluetoothPan pan = new BluetoothPan(context, listener);
            return true;
        } else if (profile == BluetoothProfile.HEALTH) {
            BluetoothHealth health = new BluetoothHealth(context, listener);
            return true;
        } else {
            return false;
        }
    }

 

以a2dp為例,就是返回對應的類

 

 /*package*/ BluetoothA2dp(Context mContext, ServiceListener l) {
        IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
        mServiceListener = l;
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        if (b != null) { 
        //得到對應的service
            mService = IBluetoothA2dp.Stub.asInterface(b);
            if (mServiceListener != null) {
                //返回this
                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, this);
            }
        } else {
            Log.w(TAG, Bluetooth A2DP service not available!);

            // Instead of throwing an exception which prevents people from going
            // into Wireless settings in the emulator. Let it crash later when it is actually used.
            mService = null;
        }
    }

 

 

 

 

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved