




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、本文我們將通過學(xué)習(xí)Android的藍(lán)牙聊天示例應(yīng)用程序來介紹藍(lán)牙開發(fā)包的使用,該示例程序完整的包含了藍(lán)牙開發(fā)的各個(gè)部分,將實(shí)現(xiàn)兩個(gè)設(shè)備通過藍(lán)牙進(jìn)行連接并聊天。AndroidManifest.xml前面我們說過,在使用藍(lán)牙API時(shí)就需要開啟某些權(quán)限,同時(shí)我們還可以從AndroidManifest.xml文件中找到應(yīng)用程序啟動(dòng)時(shí)所進(jìn)入的界面Activity等信息,因此下面我們首先打開AndroidManifest.xml文件,代碼如下:復(fù)制到剪貼板Java代碼1. manifestxmlns:android="roid"package="com.example.and
2、roid.BluetoothChat"android:versionCode="1"android:versionName="1.0"><!-最小的sdk版本->><uses-sdkminSdkVersion="6"/><!-權(quán)限申明->><uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/><uses-permissionandroid:name=&qu
3、ot;android.permission.BLUETOOTH"/><applicationandroid:label="string/app_name"android:icon="drawable/app_icon"><!-默認(rèn)Activity->><activityandroid:name=".BluetoothChat"android:label="string/app_name"android:configChanges="orientation
4、|keyboardHidden"><intent-filter><actionandroid:name="ent.action.MAIN"/><categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity><!-用于顯示藍(lán)牙設(shè)備列表的Activity-><activityandroid:name=".DeviceListAct
5、ivity"android:label="string/select_device"android:theme="android:style/Theme.Dialog"android:configChanges="orientation|keyboardHidden"/></application></manifest>首先minSdkVersion用于說明該應(yīng)用程序所需要使用的最小SDK版本,這里設(shè)置為6,也就是說最小需要使用android1.6版本的sdk,同時(shí)Ophone則需要使用oms2
6、.0版本,然后打開了BLUETOOTH和BLUETOOTH_ADMIN兩個(gè)藍(lán)牙操作相關(guān)的權(quán)限,最后看到了兩個(gè)Activity的聲明,他們分別是BluetoothChat(默認(rèn)主Activity)和DeviceListActivity(顯示設(shè)備列表),其中DeviceListActivity風(fēng)格被定義為一個(gè)對(duì)話框風(fēng)格,下面我們將分析該程序的每個(gè)細(xì)節(jié)。BluetoothChat首先,程序啟動(dòng)進(jìn)入BluetoothChat,在onCreate函數(shù)中對(duì)窗口進(jìn)行了設(shè)置,代碼如下:復(fù)制到剪貼板Java代碼1./設(shè)置窗口布局requestWindowFeature(Window.FEATURE_CUSTOM
7、_TITLE);setContentView(R.layout.main);getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.custom_title);這里可以看到將窗口風(fēng)格設(shè)置為自定義風(fēng)格了,并且指定了自定義title布局為custom_title,其定義代碼如下:復(fù)制到剪貼板Java代碼1.<RelativeLayoutxmlns:android="s/android"android:layout_width="match_parent"android:layout_
8、height="match_parent"><TextViewandroid:id=ut_alignParentLeft="true"gleLine="true"style=android:gravity="center_vertical""+id/title_left_text"android:layoandroid:ellipsize="end"android:sinlayout_width="wrap_content"android:la
9、yout_height="match_parent"android:layout_weight="1"/><TextViewandroid:id=+id/title_right_text"android:ellipsize="end"yout_width="wrap_content"android:layout_alignParentRight=android:singleLine="true"android:layout_height=t"android:tex
10、tColor="#fff"/></RelativeLayout>android:layout_weight="true"android:lamatch_paren"1"該布局將title設(shè)置為一個(gè)相對(duì)布局RelativeLayout,其中包含了兩個(gè)TextView,一個(gè)在左邊一個(gè)在右邊,分別用于顯示應(yīng)用程序的標(biāo)題稱,如下圖所示。title和當(dāng)前的藍(lán)牙配對(duì)鏈接名"?android:attr/windowTitleStyle"android:其中左邊顯示為應(yīng)用程序名稱"BluetoothCh
11、at",右邊顯示一個(gè)connected:scort則表示當(dāng)前配對(duì)成功正在進(jìn)行聊天的鏈接名稱。整個(gè)聊天界面的布局在main.xml中實(shí)現(xiàn),代碼如下:復(fù)制到剪貼板Java代碼1.<LinearLayoutxmlns:android="android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><!-顯示設(shè)備列表-><Lis
12、tViewandroid:id="+id/in"android:layout_width="match_parent"android:layout_height="match_parent"android:stackFromBottom="true"android:transcriptMode="alwaysScroll"android:layout_weight="1"/><!-顯示發(fā)送消息的編輯框-><LinearLayoutandroid:ori
13、entation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><EditTextandroid:id="+id/edit_text_out"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1&q
14、uot;android:layout_gravity="bottom"/><Buttonandroid:id="+id/button_send"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="string/send"/></LinearLayout></LinearLayout>整個(gè)界面的布局將是一個(gè)線性布局LinearLayout,
15、其中包含了另一個(gè)ListView(用于顯示聊天的對(duì)話信息)和另外一個(gè)線性布局來實(shí)現(xiàn)一個(gè)發(fā)送信息的窗口,發(fā)送消息發(fā)送框有一個(gè)輸入框和一個(gè)發(fā)送按鈕構(gòu)成。整個(gè)界面如下圖所示。布局好界面,下面我們需要進(jìn)入編碼狀態(tài),首先看BluetoothChat所要那些成員變量,如下代碼所示:復(fù)制到剪貼板Java代碼1.publicclassBluetoothChatextendsActivity/DebuggingprivatestaticfinalStringTAG="BluetoothChat"privatestaticfinalbooleanD=true;/從BluetoothChatSe
16、rviceHandler發(fā)送的消息類型publicstaticfinalintMESSAGE_STATE_CHANGE=1;publicstaticfinalintMESSAGE_READ=2;publicstaticfinalintMESSAGE_WRITE=3;publicstaticfinalintMESSAGE_DEVICE_NAME=4;publicstaticfinalintMESSAGE_TOAST=5;/從BluetoothChatServiceHandler接收消息時(shí)使用的鍵名(鍵-值模型)publicstaticfinalStringDEVICE_NAME="de
17、vice_name"publicstaticfinalStringTOAST="toast"/Intent請(qǐng)求代碼(請(qǐng)求鏈接,請(qǐng)求可見)privatestaticfinalintREQUEST_CONNECT_DEVICE=1;privatestaticfinalintREQUEST_ENABLE_BT=2;/LayoutViewsprivateTextViewmTitle;privateListViewmConversationView;privateEditTextmOutEditText;privateButtonmSendButton;/鏈接的設(shè)備的名稱p
18、rivateStringmConnectedDeviceName=null;/ArrayadapterfortheconversationthreadprivateArrayAdapter<String>mConversationArrayAdapter;/將要發(fā)送出去的字符串privateStringBuffermOutStringBuffer;/本地藍(lán)牙適配器privat/聊天服務(wù)的對(duì)象/log打印日志用,其他部分,它是我們自己定義的一個(gè)eBluetoothAdaptermBluetoothAdapter=null;privateBluetoothChatServicemCha
19、tService=null;其中Debugging部分則將用于我們?cè)谡{(diào)試程序時(shí)通過我們都加入了注釋,需要說明的是BluetoothChatService用來管理藍(lán)牙的端口監(jiān)聽,鏈接,管理聊天的程序,后面我們會(huì)介紹。在這里需要說明一點(diǎn),這些代碼都出自google的員工之手,大家在學(xué)習(xí)時(shí),可以借鑒很多代碼編寫的技巧和風(fēng)格,這都將對(duì)我們有非常大的幫助。然后,我們就需要對(duì)界面進(jìn)行一些設(shè)置,如下代碼將用來設(shè)置我們自定義的標(biāo)題title需要顯示的內(nèi)容:復(fù)制到剪貼板Java代碼1./設(shè)置自定義title布局mTitle=(TextView)findViewById(R.id.title_left_text)
20、;mTitle.setText(R.string.app_name);mTitle=(TextView)findViewById(R.id.title_right_text);左邊的TextView被設(shè)置為顯示應(yīng)用程序名稱,右邊的則需要我們?cè)阪溄又笤谠O(shè)置更新,目前則顯示沒有鏈接字樣,所以這里我們暫不設(shè)置,進(jìn)一步就需要獲取本地藍(lán)牙適配器BluetoothAdapter了,因?yàn)閷?duì)于有關(guān)藍(lán)牙的任何操作都需要首先獲得該藍(lán)牙適配器,獲取代碼非常簡(jiǎn)單,如下:復(fù)制到剪貼板Java代碼1./得到一個(gè)本地藍(lán)牙適配器mBluetoothAdapter=BluetoothAdapter.getDefaultAda
21、pter();/如果適配器為null,則不支持藍(lán)牙if(mBluetoothAdapter=null)Toast.makeText(this,"Bluetoothisnotavailable",Toast.LENGTH_LONG).show();finish。;return;getDefaultAdapter()函數(shù)用于獲取本地藍(lán)牙適配器,然后檢測(cè)是否為null,如果為null則表示沒有藍(lán)牙設(shè)備的支持,將通過toast告知用戶。在onStart()函數(shù)中,我們將檢測(cè)藍(lán)牙是否被打開,如果沒有打開,則請(qǐng)求打開,否則就可以設(shè)置一些聊天信息的準(zhǔn)備工作,代碼如下:Overridepu
22、blicvoidonStart()super.onStart();if(D)Log.e(TAG,"+ONSTART+");/如果藍(lán)牙沒有打開,則請(qǐng)求打開/setupChat()willthenbecalledduringonActivityResultif(!mBluetoothAdapter.isEnabled()IntentenableIntent=newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableIntent,REQUEST_ENABLE_BT);/否貝U,設(shè)置
23、聊天會(huì)話elseif(mChatService=null)setupChat();如果藍(lán)牙沒有打開,我們貝U通過BluetoothAdapter.ACTION_REQUEST_ENABLE來請(qǐng)求打開藍(lán)牙,REQUEST_ENABLE_BT則是我們自己定義的用于請(qǐng)求打開藍(lán)牙的Intent代碼,最后當(dāng)我們調(diào)用startActivityForResult來執(zhí)行請(qǐng)求時(shí),就會(huì)在onActivityResult函數(shù)中得到一個(gè)反饋,如果當(dāng)前藍(lán)牙已經(jīng)打開,那么就可以調(diào)用setupChat函數(shù)來準(zhǔn)備藍(lán)牙聊天相關(guān)的工作,稍后分析該函數(shù)的具體實(shí)現(xiàn)。下面我們分析一下請(qǐng)求打開藍(lán)牙之后,在onActivityResult
24、中得到的反饋信息,我們傳遞了REQUEST_ENABLE_BT代碼作為請(qǐng)求藍(lán)牙打開白命令,因此在onActivityResult中,需要會(huì)得到一個(gè)請(qǐng)求代碼為如下代碼所示:REQUEST_ENABLE_B的消息,對(duì)于其處理復(fù)制到剪貼板Java代碼1. caseREQUEST_ENABLE_BT:/在請(qǐng)求打開藍(lán)牙時(shí)返回的代碼2. if(resultCode=Activity.RESULT_OK)3. /藍(lán)牙已經(jīng)打開,所以設(shè)置一個(gè)聊天會(huì)話4. setupChat();5. else6. /請(qǐng)求打開藍(lán)牙出錯(cuò)7. Log.d(TAG,"BTnotenabled");8. Toast.
25、makeText(this,R.string.bt_not_enabled_leaving,Toast.LENGTH_SHORT).show();9. finish();10. 在請(qǐng)求時(shí),如果返回代碼為Activity.RESULT_OK,則表示請(qǐng)求打開藍(lán)牙成功,那么我們就可以和上面的操作進(jìn)度一樣,調(diào)用setupChat來設(shè)置藍(lán)牙聊天相關(guān)信息,如果返回其他代碼,則表示請(qǐng)求打開藍(lán)牙失敗,這時(shí)我們同樣通過一個(gè)Toast來告訴用戶,同時(shí)也需要調(diào)用finish()函數(shù)來結(jié)束應(yīng)用程序。如果打開藍(lán)牙無(wú)誤,那么下面我們開始進(jìn)入setupChat的設(shè)置,其代碼實(shí)現(xiàn)如下:復(fù)制到剪貼板Java代碼1. priva
26、tevoidsetupChat()Log.d(TAG,"setupChat。");/初始化對(duì)話進(jìn)程mConversationArrayAdapter=newArrayAdapter<String>(this,R.layout.message);/初始化對(duì)話顯示列表mConversationView=(ListView)findViewById(R.id.in);/設(shè)置話顯示列表源mConversationView.setAdapter(mConversationArrayAdapter);/初始化編輯框,并設(shè)置一個(gè)監(jiān)聽,用于處理按回車鍵發(fā)送消息mOutEditT
27、ext=(EditText)findViewById(R.id.edit_text_out);mOutEditText.setOnEditorActionListener(mWriteListener);/初始化發(fā)送按鈕,并設(shè)置事件監(jiān)聽mSendButton=(Button)findViewById(R.id.button_send);mSendButton.setOnClickListener(newOnClickListener()publicvoidonClick(Viewv)/取彳TTextView中的內(nèi)容來發(fā)送消息TextViewview=(TextView)findViewById
28、(R.id.edit_text_out);Stringmessage=view.getText().toString();sendMessage(message););/初始化BluetoothChatService并執(zhí)行藍(lán)牙連接mChatService=newBluetoothChatService(this,mHandler);/初始化將要發(fā)出的消息的字符串mOutStringBuffer=newStringBuffer("");首先構(gòu)建一個(gè)話進(jìn)程mConversationArrayAdapter,然后從xml中取得用于顯示對(duì)話信息的列表mConversationVie
29、w,最后將列表的數(shù)據(jù)來源Adapter設(shè)置為mConversationArrayAdapter,這里我們可以看至UmConversationArrayAdapter所指定的資源為message.xml,其定義實(shí)現(xiàn)如下:復(fù)制到剪貼板Java代碼1.<TextViewxmlns:android="roid"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="18sp"android:pad
30、ding="5dp"/>很簡(jiǎn)單,就包含了一個(gè)TextView用來顯示對(duì)話內(nèi)容即可,這里設(shè)置了文字標(biāo)簽的尺寸大小textSize和padding屬性。然后我們?nèi)〉昧司庉嬁騧OutEditText,用于輸入聊天內(nèi)容的輸入框,并對(duì)其設(shè)置了一個(gè)事件監(jiān)聽mWriteListener,其監(jiān)聽函數(shù)的實(shí)現(xiàn)如下:復(fù)制到剪貼板Java代碼1./TheactionlistenerfortheEditTextwidget,tolistenforthereturnkeyprivateTextView.OnEditorActionListenermWriteListener=newTextVie
31、w.OnEditorActionListener()publicbooleanonEditorAction(TextViewview,intactionId,KeyEventevent)/按下回車鍵并且是按鍵彈起的事件時(shí)發(fā)送消息if(actionId=EditorInfo.IME_NULL&&event.getAction()=KeyEvent.ACTION_UP)Stringmessage=view.getText().toString();sendMessage(message);if(D)Log.i(TAG,"ENDonEditorAction");r
32、eturntrue;首先在其監(jiān)聽中實(shí)現(xiàn)了onEditorAction函數(shù),我們通過判斷其參數(shù)actionId來確定事件觸發(fā)的動(dòng)作,其中的"EditorInfo.IME_NULL"在Ophone中表示回車鍵消息,然后再加上KeyEvent.ACTION_UP,則表示當(dāng)用戶按下回車鍵并彈起時(shí)才觸發(fā)消息的處理,處理過程也很簡(jiǎn)單,將輸入框中內(nèi)容取出到變量message中,然后調(diào)用sendMessage函數(shù)來發(fā)送一條消息,具體的發(fā)送細(xì)節(jié),我們稍后分析。在setupChat函數(shù)中,我們還對(duì)發(fā)送消息的按鈕進(jìn)行的初始化,同樣為其設(shè)置了事件監(jiān)聽(setOnClickListener),監(jiān)聽的
33、內(nèi)容則也是取得輸入框中的信息,然后調(diào)用sendMessage函數(shù)來發(fā)送消息,和用戶按回車鍵來發(fā)送消息一樣。最后一個(gè)重要的操作就是初始化了BluetoothChatService對(duì)象mChatService用來管理藍(lán)牙的鏈接,聊天的操作,并且設(shè)置了其Handler對(duì)象mHandler來負(fù)責(zé)數(shù)據(jù)的交換和線程之間的通信。另外還準(zhǔn)備了一個(gè)空的字符串對(duì)象mOutStringBuffer,用于當(dāng)我們?cè)诎l(fā)送消息之后,對(duì)輸入框的清理。應(yīng)用菜單該應(yīng)用程序除了這些界面的布局之外,我們還為其設(shè)置了一個(gè)菜單,菜單包括了"掃描設(shè)備"和"使設(shè)備可見(能夠被其他設(shè)備所搜索到)",創(chuàng)建
34、菜單的方式有很多種,這里gogole的員工,比較喜歡和推崇使用xml布局(將界面和邏輯分開),所以我們首先看一下對(duì)于該應(yīng)用程序通過xml所定義的菜單布局,代碼如下:復(fù)制到剪貼板Java代碼1.<menuxmlns:android="d"><!-掃描菜單-><itemandroid:id="+id/scan"android:icon="android:drawable/ic_menu_search"android:title="string/connect"/><!-可見操作
35、-><itemandroid:id="+id/discoverable"android:icon="android:drawable/ic_menu_mylocation"android:title="string/discoverable"/></menu>這樣的定義的確非常的清晰,我們可以隨意向這個(gè)Menu中添加菜單選項(xiàng)(itme),這里就定義了上面我們所說的兩個(gè)菜單。然后再程序中通過onCreateOptionsMenu函數(shù)中來裝載該菜單布局,遂于菜單的點(diǎn)擊可以通過onOptionsItemSele
36、cted函數(shù)的不同參數(shù)來辨別,下面是該應(yīng)用程序中對(duì)菜單選項(xiàng)的處理和裝載菜單布局:復(fù)制到剪貼板Java代碼1./創(chuàng)建一個(gè)菜單OverridepublicbooleanonCreateOptionsMenu(Menumenu)MenuInflaterinflater=getMenuInflater();inflater.inflate(R.menu.option_menu,menu);returntrue;/處理菜單事件OverridepublicbooleanonOptionsItemSelected(MenuItemitem)switch(item.getItemId()caseR.id.sc
37、an:/啟動(dòng)DeviceListActivity查看設(shè)備并掃描IntentserverIntent=newIntent(this,DeviceListActivity.class);startActivityForResu代(serverIntent,REQUEST_CONNECT_DEVICE);returntrue;caseR.id.discoverable:/確保設(shè)備處于可見狀態(tài)ensureDiscoverable();returntrue;returnfalse;裝載菜單布局的時(shí)候使用了MenuInflater對(duì)象,整個(gè)過程很簡(jiǎn)單,大家可以參考上面的代碼實(shí)現(xiàn),在處理菜單事件的時(shí)候,通過
38、item.getItemId()我們可以得到當(dāng)前選擇的菜單項(xiàng)的ID,首先是掃描設(shè)備(R.id.scan),這里我們有啟動(dòng)了另外一個(gè)Activity來專門處理掃描設(shè)備DeviceListActivity,如果掃描之后我們將通過startActivityForResult函數(shù)來請(qǐng)求鏈接該設(shè)備,同樣我們也會(huì)在onActivityResult函數(shù)中收到一個(gè)反饋信息,命令代碼為REQUEST_CONNECT_DEVICE,如果反饋的請(qǐng)求代碼為Activity.RESULT_OK,則表示掃描成功(掃描過程我們稍后介紹),那么下面就可以開始準(zhǔn)備鏈接了,實(shí)現(xiàn)代碼如下:復(fù)制到剪貼板Java代碼1.caseREQ
39、UEST_CONNECT_DEVICE:/當(dāng)DeviceListActivity返回設(shè)備連接if(resultCode=Activity.RESULT_OK)/從Intent中得到設(shè)備的MAC地址Stringaddress=data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);/得至U藍(lán)牙設(shè)備對(duì)象BluetoothDevicedevice=mBluetoothAdapter.getRemoteDevice(address);/嘗試連接這個(gè)設(shè)備mChatService.connect(device);break;首
40、先我們可以通過DeviceListActivity.EXTRA_DEVICE_ADDRESS來取得設(shè)備的Mac地址,然后通過Mac地址使用藍(lán)牙適配器mBluetoothAdapter的getRemoteDevice函數(shù)來查找到該地址的設(shè)備BluetoothDevice,查詢到之后我們可以通過mChatService對(duì)象的connect來鏈接該設(shè)備。般藍(lán)牙設(shè)備在打開之后都需要設(shè)上面我們說的是掃描藍(lán)牙設(shè)備并鏈接的過程,置可見狀態(tài),下面我們來看一下另一個(gè)菜單選項(xiàng)的實(shí)現(xiàn),用于使設(shè)備處于可見狀態(tài),其菜單項(xiàng)的ID為R.id.discoverable,具體實(shí)現(xiàn)過程則位于ensureDiscoverable函
41、數(shù)中,其實(shí)現(xiàn)如下代碼:復(fù)制到剪貼板Java代碼1.privatevoidensureDiscoverable()if(D)Log.d(TAG,"ensurediscoverable");/判斷掃描模式是否為既可被發(fā)現(xiàn)又可以被連接if(mBluetoothAdapter.getScanMode()!=BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)/請(qǐng)求可見狀態(tài)IntentdiscoverableIntent=newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
42、/添加附加屬性,可見狀態(tài)的時(shí)間discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);startActivity(discoverableIntent);這里首先通過mBluetoothAdapter.getScanMode()函數(shù)取得該藍(lán)牙的掃描模式,然后通過BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE設(shè)置可見屬性,在這里我們加入一個(gè)附加屬性BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,用來設(shè)置可見狀態(tài)的時(shí)
43、間,表示在指定的時(shí)間中藍(lán)牙處于可見狀態(tài),設(shè)置好之后通過startActivity來執(zhí)行即可。這里憂一個(gè)需要注意的問題,在鏈接某個(gè)設(shè)備之前,我們需要開啟一個(gè)端口監(jiān)聽,該應(yīng)用程序?qū)⑵浞旁趏nResume()函數(shù)中來處理了,代碼如下:復(fù)制到剪貼板Java代碼1.OverridepublicsynchronizedvoidonResume()super.onResume();if(D)Log.e(TAG,"+ONRESUME+");/PerformingthischeckinonResume()coversthecaseinwhichBTwas/notenabledduringon
44、Start(),sowewerepausedtoenableit./onResume()willbecalledwhenACTION_REQUEST_ENABLEactivityreturns.if(mChatService!=null)/如果當(dāng)前狀態(tài)為STATE_NONE,則需要開啟藍(lán)牙聊天服務(wù)if(mChatService.getState()=BluetoothChatService.STATE_NONE)/開始一個(gè)藍(lán)牙聊天服務(wù)mChatService.start();首先卞測(cè)mChatService是否被初始化,然后檢測(cè)其狀態(tài)是否為STATE_NONE,STATE_NONE表示初始化之
45、后處于等待的狀態(tài),當(dāng)我們?cè)趕etupChat函數(shù)中初始時(shí),其實(shí)就已經(jīng)將其狀態(tài)設(shè)置為STATE_NONE了(該操作是在BluetoothChatService的構(gòu)造函數(shù)中處理的),所以這里就可以通過一個(gè)start函數(shù)來啟動(dòng)一個(gè)進(jìn)程即可,實(shí)際上就是啟動(dòng)了一個(gè)端口監(jiān)聽進(jìn)程,當(dāng)有設(shè)備連接時(shí),該監(jiān)聽進(jìn)程結(jié)束,然后轉(zhuǎn)向鏈接進(jìn)程,鏈接之后同樣又將轉(zhuǎn)換到一個(gè)聊天管理進(jìn)程。本文主要包括以下兩個(gè)部分的內(nèi)容:其一,分析掃描設(shè)備部分DeviceListActivity,其二,分析具體的聊天過程的完整通信方案,包括端口監(jiān)聽、鏈接配對(duì)、消息發(fā)送和接收等,如果有對(duì)上一篇文章不太熟悉的,可以返回去在過一次,這樣會(huì)有利于本文的
46、理解。設(shè)備掃描(DeviceListActivity)在上一篇文章的介紹中,當(dāng)用戶點(diǎn)擊了掃描按鈕之后,則會(huì)執(zhí)行如下代碼:復(fù)制到剪貼板Java代碼1./啟動(dòng)DeviceListActivity查看設(shè)備并掃描Intentserverintent=newIntent(this,DeviceListActivity.class);startActivityForResult(serverintent,REQUEST_CONNECT_DEVICE);該代碼將跳轉(zhuǎn)到DeviceListActivity進(jìn)行設(shè)備的掃描,并且通過REQUEST_CONNECT_DEVICE來請(qǐng)求鏈接掃描到的設(shè)備。從Androi
47、dManifest.xml文件中我們知道DeviceListActivity將為定義為一個(gè)對(duì)話框的風(fēng)格,下圖是該應(yīng)用程序中,掃描藍(lán)牙設(shè)備臼*的|日公53*的截圖。其中DeviceListActivity則為圖中對(duì)話框部分,其界面的布局如下代碼所示。復(fù)制到剪貼板Java代碼1.<LinearLayoutxmlns:android="android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="
48、match_parent"><!-已經(jīng)配對(duì)的設(shè)備-><TextViewandroid:id="+id/title_paired_devices"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="string/title_paired_devices"android:visibility="gone"android:background=&quo
49、t;#666"android:textColor="#fff"android:paddingLeft="5dp"/><!-已經(jīng)配對(duì)的設(shè)備信息-><ListViewandroid:id="+id/paired_deviandroid:layout_heices"android:layout_width="match_parent"ght="wrap_content"layout_weight="1"<TextViewandroid:id=
50、width="match_parent"android:stackFromBottom="true"android:/><!-掃描出來沒有經(jīng)過配對(duì)的設(shè)備->"+id/title_new_devices"android:layout_android:layout_height="wrap_content"android:text="string/title_other_devices"android:visibility="gone"android:backg
51、round="#666"android:textColor="#fff"android:paddingLeft="5dp"/><!-掃描出來沒有經(jīng)過配對(duì)的設(shè)layout_width="match_parent"nt"android:stackFromBottom=2"/><!-掃描按鈕->_scan"android:layout_width=android:layout_height="wrap_conte"true"andr
52、oid:layout_weight=<Buttonandroid:id="+id/buttonmatch_parent"android:layout_height="wrap_content"android:text="string/button_scan"/></LinearLayout>備信息-><ListViewandroid:id="+id/new_devices"android:該布局整體由一個(gè)線性布局LinearLayout組成,其中包含了兩個(gè)textview中來顯示
53、已經(jīng)配對(duì)的設(shè)備和信掃描出來的設(shè)備(還沒有經(jīng)過配對(duì))和兩個(gè)ListView分別用于顯示已經(jīng)配對(duì)和沒有配對(duì)的設(shè)備的相關(guān)信息。按鈕則用于執(zhí)行掃描過程用,整個(gè)結(jié)構(gòu)很簡(jiǎn)單,下面我們開始分析如何編碼實(shí)現(xiàn)了。同樣開始之前,我們先確定該類中的變量的作用,定義如下:復(fù)制到剪貼板Java代碼1.publicclassDeviceListActivityextendsActivity/DebuggingprivatestaticfinalStringTAG="DeviceListActivity"privatestaticfinalbooleanD=true;/ReturnIntentextra
54、publicstaticStringEXTRA_DEVICE_ADDRESS="device_address"/藍(lán)牙適配器privateBluetoothAdaptermBtAdapter;/已經(jīng)配對(duì)的藍(lán)牙設(shè)備privateArrayAdapter<String>mPairedDevicesArrayAdapter;/新的藍(lán)牙設(shè)備privateArrayAdapter<String>mNewDevicesArrayAdapter;其中Debugging部分,同樣用于調(diào)試,這里定義了一個(gè)EXTRA_DEVICE_ADDRESS,用于在通過Intent傳
55、遞數(shù)據(jù)時(shí)的附加信息,即設(shè)備的地址,當(dāng)掃描出來之后,返回到BluetoothChat中的0nAetivityResult函數(shù)的REQUEST_CONNECT_DEVICE命令,這是我們就需要通過DeviceListActivity.EXTRA_DEVICE_ADDRESS來取得該設(shè)備的Mac地址,因此當(dāng)我們掃描完成之后在反饋掃描結(jié)果時(shí)就需要綁定設(shè)備地址作為EXTRA_DEVICE_ADDRESS的附加值,這和我們上一篇介紹的并不矛盾。另外其他幾個(gè)變量則分別是本地藍(lán)牙適配器、已經(jīng)配對(duì)的藍(lán)牙列表和掃描出來還沒有配對(duì)的藍(lán)牙設(shè)備列表,稍后我們可以看到對(duì)他們的使用。進(jìn)入DeviceListActivity
56、之后我們首先分析onCreate,首先通過如下代碼對(duì)窗口進(jìn)行了設(shè)置:復(fù)制到剪貼板Java代碼1./設(shè)置窗口requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);setContentView(R.layout.device_list);setResult(Activity.RESULT_CANCELED);這里我們?cè)O(shè)置了窗口需要帶一個(gè)進(jìn)度條,當(dāng)我們?cè)趻呙钑r(shí)就看有很容易的高速用戶掃描進(jìn)度。具體布局則設(shè)置為device_list.xml也是我們文本第一段代碼的內(nèi)容,接下來首先初始化掃描按鈕,代碼如下:復(fù)制到剪貼板Java代碼1./初始
57、化掃描按鈕ButtonscanButton=(Button)findViewById(R.id.button_scan);scanButton.setOnClickListener(newOnClickListener()publicvoidonClick(Viewv)doDiscovery();v.setVisibility(View.GONE););首先取得按鈕對(duì)象,然后為其設(shè)置一個(gè)事件監(jiān)聽,當(dāng)事件觸發(fā)時(shí)就通過doDiscovery函數(shù)來執(zhí)行掃描操作即可,具體掃描過程稍后分析。然后需要初始化用來顯示設(shè)備的列表和數(shù)據(jù)源,使用如下代碼即可:復(fù)制到剪貼板Java代碼1./初始化ArrayAdap
58、ter,一個(gè)是已經(jīng)配對(duì)的設(shè)備,一個(gè)是新發(fā)現(xiàn)的設(shè)備mPairedDevicesArrayAdapter=newArrayAdapter<String>(this,R.layout.device_name);mNewDevicesArrayAdapter=newArrayAdapter<String>(this,R.layout.device_name);/檢測(cè)并設(shè)置已配對(duì)的設(shè)備ListViewListViewpairedListView=(ListView)findViewById(R.id.paired_devices);pairedListView.setAdapte
59、r(mPairedDevicesArrayAdapter);pairedListView.setOnItemClickListener(mDeviceClickListener);/檢查并設(shè)置行發(fā)現(xiàn)的藍(lán)牙設(shè)備ListViewListViewnewDevicesListView=(ListView)findViewById(R.id.new_devices);newDevicesListView.setAdapter(mNewDevicesArrayAdapter);newDevicesListView.setOnItemClickListener(mDeviceClickListener);并
60、分別對(duì)這些列表中的選項(xiàng)設(shè)置了監(jiān)聽mDeviceClickListener,用來處理,當(dāng)選擇該選項(xiàng)時(shí),就進(jìn)行鏈接和配對(duì)操作。既然是掃描,我們就需要對(duì)掃描的結(jié)果進(jìn)行監(jiān)控,這里我們構(gòu)建了一個(gè)廣播BroadcastReceiver來對(duì)掃描的結(jié)果進(jìn)行處理,代碼如下:復(fù)制到剪貼板Java代碼1./當(dāng)一個(gè)設(shè)備被發(fā)現(xiàn)時(shí),需要注冊(cè)一個(gè)廣播IntentFilterfilter=newIntentFilter(BluetoothDevice.ACTION_FOUND);this.registerReceiver(mReceiver,filter);/當(dāng)顯示檢查完畢的時(shí)候,需要注冊(cè)一個(gè)廣播filter=newIntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);this.registerReceiver(mReceiver,filter);這里我們注冊(cè)到廣播mReceiver的IntentFilter主要包括了發(fā)現(xiàn)藍(lán)牙設(shè)備(BluetoothDevice.ACTION_FOUND)和掃描結(jié)束(BluetoothAdapter.ACTION_DISCOVERY_FINISHED),稍后我們分析如何在mReceiver
溫馨提示
- 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 河南循環(huán)包裝管理辦法
- 1850年以來吳語(yǔ)文獻(xiàn)的詞匯演變與語(yǔ)法特征研究
- 民航包機(jī)乘客管理辦法
- 高壓變電站主接線系統(tǒng)優(yōu)化設(shè)計(jì)研究
- 對(duì)話自我與外界:探索個(gè)體與社會(huì)的互動(dòng)
- 數(shù)字經(jīng)濟(jì)時(shí)代船舶物資采購(gòu)策略:創(chuàng)新管理模式與應(yīng)用探討
- 江蘇倉(cāng)儲(chǔ)藥劑管理辦法
- 施工現(xiàn)場(chǎng)安全管理稿件
- 2025?;繁9軉T崗位操作規(guī)程
- 到哪里學(xué)習(xí)網(wǎng)絡(luò)安全工程師
- 食品安全事故流行病學(xué)調(diào)查技術(shù)指南
- 內(nèi)蒙古呼和浩特實(shí)驗(yàn)教育集團(tuán)2025屆七年級(jí)英語(yǔ)第二學(xué)期期末考試模擬試題含答案
- 2025年廣東省高考生物試題
- 2025至2030中國(guó)匹克球市場(chǎng)前景預(yù)判與未來發(fā)展形勢(shì)分析報(bào)告
- 防護(hù)窗拆除合同范本
- 關(guān)于問責(zé)的工作報(bào)告
- 城市交通流優(yōu)化的AI驅(qū)動(dòng)預(yù)測(cè)模型研究-洞察闡釋
- 香港勞工合同保密協(xié)議
- 會(huì)議活動(dòng)復(fù)盤報(bào)告
- 隧道安全運(yùn)營(yíng)管理制度
- 山東省2024年藝術(shù)類本科批美術(shù)與設(shè)計(jì)類第1次志愿投檔情況表(公布)
評(píng)論
0/150
提交評(píng)論