編輯:關於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; } }
今天還是給大家帶來自定義控件的編寫,自定義一個ListView的左右滑動刪除Item的效果,這個效果之前已經實現過了,有興趣的可以看下Android 使用Scroller
這是作為上一篇Android 數據存儲 如何搞定SQLite Database的實例練習,之所以單獨列出來是因為除了數據庫方面的知識,還涉及其它方面的知識,
Android使用Handler進行實例化(new)時, 如: private Handler handler = new Handler(); 會報錯Ha
本文主要內容就是用marix加上漸變色實現圖片倒影的效果,步驟如下: 1. 獲取需要倒影效果的圖片,這裡取原圖片的一半 2. 添加顏色漸變到倒影圖片上