版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第7章Android開發(fā)實(shí)例7.1
GPS定位軟件7.2網(wǎng)絡(luò)監(jiān)控軟件7.3基于手機(jī)的便攜式遠(yuǎn)程醫(yī)療監(jiān)護(hù)系統(tǒng)7.1GPS定位軟件
1.設(shè)置權(quán)限
首先,添加GPS定位權(quán)限到AndroidManifest文件中,代碼如下:
<!--允許一個(gè)程序訪問(wèn)精確位置-->
<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--允許程序創(chuàng)建模擬位置用于測(cè)試-->
<uses-permissionandroid:name="android.permission.ACCESS_MOCK_LOCATION"/>
2.編寫主頁(yè)面代碼
在界面布局文件(main.xml)中添加TextView控件,分別用來(lái)顯示緯度和經(jīng)度數(shù)據(jù),其代碼如下:
<TextView
android:id="@+id/text_latitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/text_latitude"/><TextView
android:id="@+id/text_longitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/text_longitude"/>
3.編寫GPS主程序代碼
具體實(shí)現(xiàn)的步驟如下:
(1)首先,我們需要獲取LocationManager的一個(gè)實(shí)例,這里需要注意的是此實(shí)例只能通過(guò)下面這種方式來(lái)獲取,直接實(shí)例化LocationManager是不被允許的:
locationManager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);
(2)定義Location事件監(jiān)聽,當(dāng)位置改變或狀態(tài)變化,可用和不可用時(shí),設(shè)置相應(yīng)的處理方式。具體代碼如下:
LocationListenerlocationListener=newLocationListener()
{
@Override
publicvoidonLocationChanged(Locationlocation)
{
//這部分是自動(dòng)產(chǎn)生方法樁
updateLocation(location); }
@Override
publicvoidonProviderDisabled(Stringprovider)
{
//這部分是自動(dòng)產(chǎn)生方法樁
updateLocation(null);
}
@Override
publicvoidonProviderEnabled(Stringprovider) {
//這部分是自動(dòng)產(chǎn)生方法樁
updateLocation(location);
}
@Override
publicvoidonStatusChanged(Stringprovider,intstatus, Bundleextras){
//Provider的轉(zhuǎn)態(tài)在可用、暫時(shí)不可用和無(wú)服務(wù)三個(gè)狀態(tài)直接切換時(shí)觸發(fā)此函數(shù)
//這部分是自動(dòng)產(chǎn)生方法樁
}
};
(3)判讀GPS模式是否開啟,如果開啟將得到內(nèi)容提供器,并通過(guò)內(nèi)容提供器得到位置信息,調(diào)用updateLocation方法來(lái)更新位置數(shù)據(jù);如果沒(méi)有開啟,則轉(zhuǎn)到設(shè)置中的安全模塊,手動(dòng)開啟GPS,設(shè)置完成返回程序界面。通過(guò)GPS位置提供器獲得位置(指定具體的位置提供器),代碼如下:
Stringprovider=LocationManager.GPS_PROVIDER;
location=locationManager.getLastKnownLocation(provider);
(4)更新位置方法updateLocation(Locationlocation),當(dāng)位置信息location為空時(shí),設(shè)置經(jīng)緯度為0,否則讀取經(jīng)緯度信息,設(shè)置TextView信息。
privatevoidupdateLocation(Locationlocation)
{
//這部分是自動(dòng)產(chǎn)生方法樁
if(location!=null)
{
doublela=location.getLatitude();
doublelo=location.getLongitude();
latitude.setText("緯度為:"+la);
longitude.setText("經(jīng)度為:"+lo);
}
else
{
latitude.setText("緯度為:"+0);
longitude.setText("經(jīng)度為:"+0);
}
}圖7.1GPS軟件示例效果圖
4.實(shí)現(xiàn)效果經(jīng)過(guò)編譯,將GPS軟件安裝到AVD中后,效果實(shí)現(xiàn)圖如圖7.1所示。
7.2網(wǎng)絡(luò)監(jiān)控軟件
1.設(shè)置權(quán)限
在AndroidManifest文件中添加相應(yīng)的權(quán)限,代碼如下:
<!--允許一個(gè)程序訪問(wèn)CellID或WiFi熱點(diǎn)來(lái)獲取粗略的位置-->
<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/>
2.編寫主界面代碼
程序采用ListView來(lái)展示手機(jī)參數(shù),因此編寫的主界面布局文件代碼如下:
<ListView
android:id=“@+id/listview”
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”>
</ListView>
3.編寫數(shù)據(jù)頁(yè)面代碼
程序界面主體采用ListView作為數(shù)據(jù)展示方式,顯示數(shù)據(jù)采用自定義方式來(lái)實(shí)現(xiàn)。每一個(gè)ListView的Item都是由兩個(gè)TextView控件組成的,這兩個(gè)TextView控件采用水平布局,分別用來(lái)顯示標(biāo)題和內(nèi)容。編寫的數(shù)據(jù)頁(yè)面代碼如下:
<?xmlversion=“1.0”encoding=“utf-8”?>
<LinearLayout
xmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"><TextView
android:id="@+id/title"
android:layout_width="100sp"
android:layout_height="wrap_content"
android:textSize="15sp"/><TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"/>
</LinearLayout>
4.獲取網(wǎng)絡(luò)信息
1)?network方法
利用network方法獲取網(wǎng)絡(luò)信息包括如下兩步:
(1)調(diào)用系統(tǒng)服務(wù)方法獲取TelephonyManager,具體代碼如下:
tm=
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
(2)分別調(diào)用getNetworkType、getPhoneType、getCellLocation方法獲取網(wǎng)絡(luò)類型、手機(jī)制式和小區(qū)信息。具體代碼如下:
//網(wǎng)絡(luò)類型
networkType=tm.getNetworkType();
switch(networkType)
{case0:
showNetWorkType="NETWORK_TYPE_UNKNOWN";
break;
case1:
showNetWorkType="NETWORK_TYPE_GPRS";
break;
case2:
showNetWorkType="NETWORK_TYPE_EDGE";
break;case3:
showNetWorkType="NETWORK_TYPE_UMTS";
break;
case4:
showNetWorkType="NETWORK_TYPE_CDMA";
break;
case5:
showNetWorkType="NETWORK_TYPE_EVDO_0";
break;case6:
showNetWorkType="NETWORK_TYPE_EVDO_A";
break;
case7:
showNetWorkType="NETWORK_TYPE_1xRTT";
break;
case8:
showNetWorkType="NETWORK_TYPE_HSDPA";
break;case9:
showNetWorkType="NETWORK_TYPE_HSUPA";
break;
case10:
showNetWorkType="NETWORK_TYPE_HSPA";
break;
case11:
showNetWorkType="NETWORK_TYPE_IDEN";
break;case12:
showNetWorkType="NETWORK_TYPE_EVDO_B";
break;
case13:
showNetWorkType="NETWORK_TYPE_LTE";
break;
case14:
showNetWorkType="NETWORK_TYPE_EHRPD";
break;case15:
showNetWorkType="NETWORK_TYPE_HSPAP";
break;
}
//手機(jī)類型
phoneType=tm.getPhoneType();
switch(phoneType){
case0:
showPhoneType="PHONE_TYPE_NONE";
break;
case1:
showPhoneType="PHONE_TYPE_GSM";
break;
case2:
showPhoneType="PHONE_TYPE_CDMA";
break;case3:
showPhoneType="PHONE_TYPE_SIP";
break;
}
//服務(wù)小區(qū)信息
cellLocation=(GsmCellLocation)tm.getCellLocation();
2)?show方法
首先定義一個(gè)列表用來(lái)存放數(shù)據(jù),其中每個(gè)元素為HashMap<String,String>;然后使用SimpleAdapter作為L(zhǎng)istView的適配器,將列表數(shù)據(jù)與listview_item.xml中的TextView控件對(duì)應(yīng)起來(lái),并進(jìn)行數(shù)據(jù)填充,代碼如下:privatevoidshow()
{
t=newTime();
t.setToNow();
//創(chuàng)建列表用于存儲(chǔ)數(shù)據(jù)
ArrayList<HashMap<String,String>>list=newArrayList<HashMap<String,String>>();
//時(shí)間 HashMap<String,String>map0=newHashMap<String,String>();
map0.put("title","時(shí)間");
map0.put("value",String.valueOf(t.format("%Y-%m-%d%H:%M:%S")));
//手機(jī)類型
HashMap<String,String>map1=newHashMap<String,String>();
map1.put("title","手機(jī)類型");
map1.put("value",showPhoneType); //網(wǎng)絡(luò)類型
HashMap<String,String>map2=newHashMap<String,String>();
map2.put("title","網(wǎng)絡(luò)類型");
map2.put("value",showNetWorkType);
//運(yùn)營(yíng)商
HashMap<String,String>map3=newHashMap<String,String>();
map3.put("title","運(yùn)營(yíng)商名字"); map3.put("value",tm.getNetworkOperatorName());
//服務(wù)小區(qū)信息
HashMap<String,String>map4=newHashMap<String,String>();
map4.put("title","cellLocation");
map4.put("value",String.valueOf(cellLocation));
list.add(map0);
list.add(map1); list.add(map2);
list.add(map3);
list.add(map4);
SimpleAdaptersa=newSimpleAdapter(this,list,R.layout.listview_item,newString[]{"title","value"},newint[]{R.id.title,R.id.value});
listView.setAdapter(sa);
}
5.實(shí)現(xiàn)效果
程序運(yùn)行結(jié)果顯示的界面如圖7.2所示。圖7.2網(wǎng)絡(luò)信息獲取軟件運(yùn)行結(jié)果
7.3基于手機(jī)的便攜式遠(yuǎn)程醫(yī)療監(jiān)護(hù)系統(tǒng)
信息采集設(shè)備將人體生理參數(shù)采集后使用藍(lán)牙發(fā)送至基于Android系統(tǒng)的手機(jī),隨后由手機(jī)將數(shù)據(jù)通過(guò)移動(dòng)通信網(wǎng)絡(luò)傳至服務(wù)器端,并由基于Linux的服務(wù)器端進(jìn)行數(shù)據(jù)匯總、存儲(chǔ)和分析。
基于手機(jī)的便攜式遠(yuǎn)程醫(yī)療監(jiān)護(hù)系統(tǒng)框架圖如圖7.3
所示。圖7.3基于手機(jī)的便攜式遠(yuǎn)程醫(yī)療監(jiān)護(hù)系統(tǒng)框架圖7.3.1功能分析
(1)采集人體血氧與心率數(shù)據(jù)。該功能由單片機(jī)控制采集模塊實(shí)現(xiàn)。由于本書重點(diǎn)并不在單片機(jī)控制采集模塊上,所以這一部分不再介紹。
(2)將人體血氧與心率數(shù)據(jù)發(fā)送至手機(jī)。該功能使用了藍(lán)牙技術(shù),采集端由單片機(jī)控制藍(lán)牙模塊實(shí)現(xiàn)數(shù)據(jù)發(fā)送,手機(jī)上通過(guò)Java編程實(shí)現(xiàn)數(shù)據(jù)接收。
(3)手機(jī)人性化界面。該功能使用了Android操作系統(tǒng)提供的界面控件,通過(guò)XML語(yǔ)言進(jìn)行布局,通過(guò)Java編程實(shí)現(xiàn)控制。
(4)手機(jī)將生理參數(shù)發(fā)送至服務(wù)器。該功能使用了Socket通信,由Java語(yǔ)言實(shí)現(xiàn)。
(5)服務(wù)器接收生理數(shù)據(jù)。該功能運(yùn)行于一基于Linux的服務(wù)器,通過(guò)Java編程實(shí)現(xiàn)Socket監(jiān)聽和接收數(shù)據(jù)的功能。
(6)保存生理參數(shù)歷史數(shù)據(jù)。在服務(wù)器上通過(guò)使用Mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)數(shù)據(jù)的保存與備份,并且它可以允許有權(quán)限的人隨時(shí)查閱。
(7)給出相關(guān)意見。由服務(wù)器對(duì)數(shù)據(jù)進(jìn)行分析,根據(jù)醫(yī)學(xué)理論對(duì)使用者提出相關(guān)建議,以實(shí)現(xiàn)更深入的智能化。由以上功能分析可知,手機(jī)端需要實(shí)現(xiàn)的是(2)~(4)步驟,對(duì)應(yīng)的流程圖如圖7.4所示,這幾個(gè)步驟就是Android應(yīng)用的體現(xiàn),所以我們將重點(diǎn)介紹這幾步的實(shí)現(xiàn)。服務(wù)器端采用的是Linux操作系統(tǒng)而非Android操作系統(tǒng),因此,其功能實(shí)現(xiàn)在此不予介紹。圖7.4Android手機(jī)端流程圖7.3.2手機(jī)端界面布局
1.主界面布局
主界面布局文件main.xml的代碼如下:
<?xmlversion=“1.0”encoding=“utf-8”?>
<AbsoluteLayoutxmlns:android=“/apk/res/android”
android:orientation=“vertical”
android:layout_width=“fill_parent”
android:layout_height=“fill_parent”
>
<ImageViewandroid:id="@+id/startpic"
android:background="@drawable/white"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<TextView
android:id="@+id/state"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@drawable/dark" android:background=“@drawable/white”
android:textSize=“20sp”
android:layout_x=“0px”
android:layout_y=“400px”
>
</TextView>
</AbsoluteLayout>
運(yùn)行以后,效果如圖7.5所示。圖7.5醫(yī)療監(jiān)護(hù)系統(tǒng)主界面
2.登錄界面布局
登錄界面主要包括輸入用戶名和密碼、登錄或退出按鈕等內(nèi)容,其布局文件login.xml的代碼如下:
<?xmlversion="1.0"encoding="utf-8"?>
<AbsoluteLayoutxmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="用戶名:"
android:layout_x="0px"
android:layout_y="10px"
>
</TextView>
<EditText
android:id="@+id/userValue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
android:textSize="18sp"
android:layout_x="0px"
android:layout_y="50px"
>
</EditText>
<TextView
android:id="@+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="密碼:"
android:layout_x="0px"
android:layout_y="95px" >
</TextView>
<EditText
android:id="@+id/passwordValue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:password="true"
android:text=""
android:textSize="18sp"
android:layout_x="0px"
android:layout_y="135px" >
</EditText>
<Button
android:id="@+id/enter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="登錄"
android:layout_x="50px"
android:layout_y="185px" >
</Button>
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="取消"
android:layout_x="200px"
android:layout_y="185px"
>
</Button>
<ImageView
android:id=“@+id/picLogin”
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”
android:layout_x=“0px”
android:layout_y=“100px”
>
</ImageView>
</AbsoluteLayout>運(yùn)行之后,登錄頁(yè)面效果如圖7.6所示。圖7.6醫(yī)療監(jiān)護(hù)系統(tǒng)登錄界面
3.監(jiān)控界面布局
監(jiān)控界面主要顯示所監(jiān)控的參數(shù)及其數(shù)值,監(jiān)控展示頁(yè)面布局文件monitor.xml的代碼如下:
<?xmlversion=“1.0”encoding=“utf-8”?>
<AbsoluteLayout
xmlns:android="/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/helloString"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="20sp"
android:layout_x="0px"
android:layout_y="0px"
>
</TextView>
<TextView
android:id="@+id/speed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="心率:"
android:textSize="25sp"
android:layout_x="35px"
android:layout_y="55px"
>
</TextView>
<TextView
android:id="@+id/speedValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="25sp" android:textStyle=“bold”
android:textColor=“@drawable/red”
android:layout_x=“110px”
android:layout_y=“55px”
>
</TextView>
<TextView android:id=“@+id/speedUnit”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“次/分”
android:textSize=“25sp”
android:layout_x=“150px”
android:layout_y=“55px”
>
</TextView>
<TextView
android:id="@+id/oxygen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="血氧:"
android:textSize="25sp"
android:layout_x="35px"
android:layout_y="95px">
</TextView>
<TextView
android:id="@+id/oxygenValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="25sp"
android:textStyle="bold"
android:textColor="@drawable/red"
android:layout_x="110px"
android:layout_y="95px">
</TextView>
<TextView
android:id="@+id/oxygenUnit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="%"
android:textSize="25sp"
android:layout_x="150px"
android:layout_y="95px"
></TextView>
<ImageView
android:id="@+id/picMedic"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_x="0px"
android:layout_y="100px"
>
</ImageView>
</AbsoluteLayout>7.3.3手機(jī)端功能的設(shè)計(jì)與實(shí)現(xiàn)
根據(jù)上面功能分析可知,手機(jī)端需要完成的功能包括:
(1)藍(lán)牙設(shè)備連接。
(2)藍(lán)牙數(shù)據(jù)獲取。
(3)用戶登錄醫(yī)療監(jiān)控系統(tǒng)。
(4)將藍(lán)牙獲取到的數(shù)據(jù)發(fā)送到醫(yī)療監(jiān)控系統(tǒng)服務(wù)器。
1.藍(lán)牙連接
藍(lán)牙連接包括藍(lán)牙設(shè)備連接和藍(lán)牙數(shù)據(jù)獲取,其實(shí)現(xiàn)代碼如下:
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.util.UUID;
importandroid.bluetooth.BluetoothAdapter;
importandroid.bluetooth.BluetoothDevice;importandroid.bluetooth.BluetoothServerSocket;
importandroid.bluetooth.BluetoothSocket;
importandroid.content.Context;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.util.Log;
/***這個(gè)類完成安裝和管理藍(lán)牙和其他設(shè)備連接的所有工作。它有一個(gè)線程負(fù)責(zé)監(jiān)聽進(jìn)來(lái)的連接,
*一個(gè)線程負(fù)責(zé)連接設(shè)備,還有一個(gè)線程完成連接時(shí)的數(shù)據(jù)傳輸
*/
publicclassBluetoothChatService{
//Debug調(diào)試
privatestaticfinalStringTAG="BluetoothMedicService";
privatestaticfinalbooleanD=true; //創(chuàng)建服務(wù)器套接字時(shí)的SDP記錄的名字
privatestaticfinalStringNAME="BluetoothMedic";
//這個(gè)應(yīng)用程序唯一的UUID
privatestaticfinalUUIDMY_UUID=UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
//成員域 privatefinalBluetoothAdaptermAdapter;
privatefinalHandlermHandler;
privateAcceptThreadmAcceptThread;
privateConnectThreadmConnectThread;
privateConnectedThreadmConnectedThread;
privateintmState;
//表明當(dāng)前連接狀態(tài)的常量 publicstaticfinalintSTATE_NONE=0; //我們現(xiàn)在什么都沒(méi)做
publicstaticfinalintSTATE_LISTEN=1; //現(xiàn)在監(jiān)聽進(jìn)來(lái)的連接
publicstaticfinalintSTATE_CONNECTING=2; //現(xiàn)在初始化一個(gè)出去的連接
publicstaticfinalintSTATE_CONNECTED=3; //現(xiàn)在連接到一個(gè)遠(yuǎn)端設(shè)備
/** *構(gòu)造方法。準(zhǔn)備一個(gè)新的BluetoothChat會(huì)話
*@paramcontextUI活動(dòng)上下文
*@paramhandler將消息發(fā)送回UI活動(dòng)的句柄
*/
publicBluetoothChatService(Contextcontext,Handlerhandler){
mAdapter=BluetoothAdapter.getDefaultAdapter();
mState=STATE_NONE;
mHandler=handler; }
/**
*設(shè)置對(duì)話連接的當(dāng)前狀態(tài)
*@paramstate一個(gè)整數(shù)定義當(dāng)前連接狀態(tài)
*/
privatesynchronizedvoidsetState(intstate){
if(D)Log.d(TAG,"setState()"+mState+"->"+state);
mState=state; //給句柄一個(gè)新狀態(tài),這樣UI活動(dòng)可以更新
mHandler.obtainMessage(monitor.MESSAGE_STATE_CHANGE,state,-1).sendToTarget();
}
/**
*返回當(dāng)前的狀態(tài)*/
publicsynchronizedintgetState(){
returnmState;}
/**
*啟動(dòng)聊天服務(wù)。特別之處是以偵聽(服務(wù)器)模式啟動(dòng)AcceptThread以開始一個(gè)會(huì)話*/
publicsynchronizedvoidstart(){
if(D)Log.d(TAG,"start");
//取消任何一個(gè)試圖建立連接的線程 if(mConnectThread!=null){mConnectThread.cancel();mConnectThread=null;}
//取消任何一個(gè)當(dāng)前正在運(yùn)行連接的線程
if(mConnectedThread!=null){
mConnectedThread.cancel();
mConnectedThread=null;
} //啟動(dòng)線程偵聽藍(lán)牙服務(wù)器套接字
if(mAcceptThread==null){
mAcceptThread=newAcceptThread();
mAcceptThread.start();
}
setState(STATE_LISTEN);
}
/** *啟動(dòng)ConnectThread以初始化一個(gè)到遠(yuǎn)端設(shè)備的連接
*@paramdevice要連接的藍(lán)牙設(shè)備
*/
publicsynchronizedvoidconnect(BluetoothDevicedevice){
if(D)Log.d(TAG,"connectto:"+device);
//取消任何一個(gè)試圖建立連接的線程
if(mState==STATE_CONNECTING){ if(mConnectThread!=null){
mConnectThread.cancel();
mConnectThread=null;}
}
//取消任何一個(gè)當(dāng)前正在運(yùn)行連接的線程
if(mConnectedThread!=null){
mConnectedThread.cancel();
mConnectedThread=null;} //啟動(dòng)連接給定設(shè)備的線程
mConnectThread=newConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
/**
*啟動(dòng)ConnectedThread開始對(duì)藍(lán)牙連接的管理 *@paramsocket建立連接處的藍(lán)牙套接字
*@paramdevice已經(jīng)被連接上的藍(lán)牙設(shè)備
*/
publicsynchronizedvoidconnected(BluetoothSocketsocket,BluetoothDevicedevice)
{if(D)Log.d(TAG,"connected");
//取消完成連接的線程 if(mConnectThread!=null){mConnectThread.cancel();mConnectThread=null;}
//取消任何一個(gè)正在運(yùn)行連接的線程
if(mConnectedThread!=null){
mConnectedThread.cancel();
mConnectedThread=null;} //取消接受線程因?yàn)槲覀冎幌脒B接到一個(gè)設(shè)備
if(mAcceptThread!=null){mAcceptThread.cancel();mAcceptThread=null;}
//啟動(dòng)管理連接和完成傳輸?shù)木€程
mConnectedThread=newConnectedThread(socket);
mConnectedThread.start();
//將被連接的設(shè)備的名字發(fā)送回UI活動(dòng) Messagemsg=mHandler.obtainMessage(monitor.MESSAGE_DEVICE_NAME);
Bundlebundle=newBundle();
bundle.putString(monitor.DEVICE_NAME,device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED); }
/**
*終止所有線程
*/
publicsynchronizedvoidstop(){
if(D)Log.d(TAG,"stop");
if(mConnectThread!=null){mConnectThread.cancel();mConnectThread=null;}
if(mConnectedThread!=null){mConnectedThread.cancel();
mConnectedThread=null;}
if(mAcceptThread!=null){mAcceptThread.cancel();mAcceptThread=null;}
setState(STATE_NONE);
}
/**
*以非同步方式寫到ConnectedThread
*@paramout要寫的類型 *@seeConnectedThread#write(byte[])
*/
publicvoidwrite(byte[]out){
//創(chuàng)建臨時(shí)對(duì)象
ConnectedThreadr;
//同步ConnectedThread的一個(gè)拷貝
synchronized(this){
if(mState!=STATE_CONNECTED)return;
r=mConnectedThread }
//完成非同步寫入
r.write(out);
}
/**
*表明連接嘗試失敗并通知UI活動(dòng)
*/
privatevoidconnectionFailed(){
setState(STATE_LISTEN);
//發(fā)送一個(gè)失敗消息回給活動(dòng) Messagemsg=mHandler.obtainMessage(monitor.MESSAGE_TOAST);
Bundlebundle=newBundle();
bundle.putString(monitor.TOAST,"無(wú)法連接");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
/**
*表明丟失連接并通知UI活動(dòng)
*/ privatevoidconnectionLost(){
setState(STATE_LISTEN);
//發(fā)送失敗消息返回給這個(gè)活動(dòng)
Messagemsg=mHandler.obtainMessage(monitor.MESSAGE_TOAST);
Bundlebundle=newBundle();
bundle.putString(monitor.TOAST,"設(shè)備丟失");
msg.setData(bundle);
mHandler.sendMessage(msg); }
/**
*偵聽進(jìn)來(lái)的連接時(shí)運(yùn)行這個(gè)線程。它就像一個(gè)服務(wù)器端的客戶。
*它持續(xù)運(yùn)行直到一個(gè)連接被接受(或者直到一個(gè)連接被取消)
*/
privateclassAcceptThreadextendsThread{
//本地服務(wù)器套接字
privatefinalBluetoothServerSocketmmServerSocket; publicAcceptThread(){
BluetoothServerSockettmp=null;
//創(chuàng)建一個(gè)新的偵聽服務(wù)器套接字
try{
tmp=mAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);
}catch(IOExceptione){
Log.e(TAG,"listen()failed",e);
} mmServerSocket=tmp;
}
publicvoidrun(){
if(D)Log.d(TAG,"BEGINmAcceptThread"+this);
setName("AcceptThread");
BluetoothSocketsocket=null;
//如果我們沒(méi)有被連接就偵聽服務(wù)器套接字 while(mState!=STATE_CONNECTED){
try{
//這是一個(gè)塊調(diào)用,它只會(huì)在成功連接或者出現(xiàn)異常時(shí)返回
socket=mmServerSocket.accept();
}catch(IOExceptione){
Log.e(TAG,"accept()failed",e);
break;
} //如果接受了一個(gè)連接
if(socket!=null){
synchronized(BluetoothChatService.this){
switch(mState){
caseSTATE_LISTEN:
caseSTATE_CONNECTING:
//情況正常。啟動(dòng)連接的線程 connected(socket,socket.getRemoteDevice());
break;
caseSTATE_NONE:
caseSTATE_CONNECTED:
//或者沒(méi)準(zhǔn)備或者已經(jīng)連接。終止新套接字
try{
socket.close(); }catch(IOExceptione){
Log.e(TAG,"Couldnotcloseunwantedsocket",e);
}
break;
}
}
}
}
if(D)Log.i(TAG,"ENDmAcceptThread"); }
publicvoidcancel(){
if(D)Log.d(TAG,"cancel"+this);
try{
mmServerSocket.close();
}catch(IOExceptione){
Log.e(TAG,"close()ofserverfailed",e);
}
}
} /**
*當(dāng)嘗試建立一個(gè)和設(shè)備建立出去的連接時(shí)運(yùn)行這個(gè)線程。
*它直接運(yùn)行過(guò)去;連接或者成功或者失敗。
*/
privateclassConnectThreadextendsThread{
privatefinalBluetoothSocketmmSocket;
privatefinalBluetoothDevicemmDevice; publicConnectThread(BluetoothDevicedevice){
mmDevice=device;
BluetoothSockettmp=null;
//獲取一個(gè)連接到給定藍(lán)牙設(shè)備的藍(lán)牙套接字
try{
tmp=device.createRfcommSocketToServiceRecord(MY_UUID);
}catch(IOExceptione){
Log.e(TAG,"create()failed",e); }
mmSocket=tmp;
}
publicvoidrun(){
Log.i(TAG,"BEGINmConnectThread");
setName("ConnectThread");
//總是取消探索因?yàn)樗鼤?huì)放慢連接
mAdapter.cancelDiscovery();
//建立一個(gè)到藍(lán)牙套接字的連接 try{
//這是一個(gè)塊調(diào)用,只會(huì)在成功連接或者出現(xiàn)異常時(shí)返回
mmSocket.connect();
}catch(IOExceptione){
connectionFailed();
//關(guān)閉套接字
try{
mmSocket.close();
}catch(IOExceptione2){
Log.e(TAG,"unabletoclose()socketduringconnectionfailure",e2);
} //啟動(dòng)服務(wù)重啟偵聽模式
BluetoothChatService.this.start();
return;
}
//重置連接線程因?yàn)槲覀円呀?jīng)做過(guò)了
synchronized(BluetoothChatService.this){
mConnectThread=null;
}
//啟動(dòng)連接的線程
connected(mmSocket,mmDevice); }
publicvoidcancel(){
try{
mmSocket.close();
}catch(IOExceptione){
Log.e(TAG,"close()ofconnectsocketfailed",e);
}
}
} /**
*在連接到一個(gè)遠(yuǎn)端設(shè)備過(guò)程中運(yùn)行這個(gè)線程。它處理所有進(jìn)入和出去的傳輸
*/
privateclassConnectedThreadextendsThread{
privatefinalBluetoothSocketmmSocket;
privatefinalInputStreammmInStream;
privatefinalOutputStreammmOutStream; publicConnectedThread(BluetoothSocketsocket){
Log.d(TAG,"createConnectedThread");
mmSocket=socket;
InputStreamtmpIn=null;
OutputStreamtmpOut=null;
//獲取藍(lán)牙套接字輸入和輸出流 try{
tmpIn=socket.getInputStream();
tmpOut=socket.getOutputStream();
}catch(IOExceptione){
Log.e(TAG,"tempsocketsnotcreated",e);
}
mmInStream=tmpIn;
mmOutStream=tmpOut;
} publicvoidrun(){
Log.i(TAG,“BEGINmConnectedThread”);
byte[]buffer=newbyte[256];
intbytes;
//當(dāng)連接時(shí)持續(xù)偵聽輸入流
while(true){
try{
//從輸入流讀取
bytes=mmInStream.read(buffer); //給UI活動(dòng)發(fā)送獲取的類型
mHandler.obtainMessage(monitor.MESSAGE_READ,bytes,-1,buffer)
.sendToTarget();
}catch(IOExceptione){
Log.e(TAG,"disconnected",e);
connectionLost();
break;
}
}
} /**
*寫入連接的OutStream
*@parambuffer要寫入的類型
*/
publicvoidwrite(byte[]buffer){
try{
mmOutStream.write(buffer);
//共享發(fā)送的消息回UI活動(dòng)
mHandler.obtainMessage(monitor.MESSAGE_WRITE,-1,-1,buffer)
.sendToTarget(); }catch(IOExceptione){
Log.e(TAG,"Exceptionduringwrite",e);
}
}
publicvoidcancel(){
try{
mmSocket.close(); }catch(IOExceptione){
Log.e(TAG,“close()ofconnectsocketfailed”,e);
}
}
}
}
2.?Socket通信
Socket通信實(shí)現(xiàn)手機(jī)與服務(wù)器的通信,其實(shí)現(xiàn)代碼如下:
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
import.Socket;
publicclassSocketService{
privatestaticfinalStringHOST="02"; privatestaticfinalintPORT=1234;
publicStringsendData(StringdataVar1){
Sockets=null;
DataOutputStreamdout=null;
DataInputStreamdin=null;
Stringrecieved=newString(); try{
s=newSocket(HOST,PORT); //連接服務(wù)器
dout=newDataOutputStream(s.getOutputStream()); //得到輸出流
din=newDataInputStream(s.getInputStream()); //得到輸入流
dout.writeUTF(dataVar1); //向服務(wù)器發(fā)送消息
recieved=din.readUTF();
din.close(); dout.close();
//關(guān)閉此Socket連接
s.close();
}catch(Exceptione){
e.printStackTrace(); //打印異常信息
}
returnrecieved;
}
}
3.主頁(yè)面代碼
主頁(yè)面的實(shí)現(xiàn)代碼如下:
importandroid.app.Activity;
importandroid.app.AlertDialog;
importandroid.bluetooth.BluetoothAdapter;
importandroid.content.DialogInterface;
importandroid.content.Intent;
importandroid.os.Bundle;importandroid.view.View;
importandroid.widget.ImageView;
importandroid.widget.TextView;
publicclassmainextendsActivity{
ImageViewstartPic;
TextViewstartState;
protectedstaticfinalintREQUEST_ENABLE_BT=0;
/*當(dāng)首次創(chuàng)建這個(gè)活動(dòng)時(shí)被調(diào)用*/ @Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setTitle(“正在啟動(dòng)中,請(qǐng)稍后”);
startState=(TextView)findViewById(R.id.state);
startState.setText(“點(diǎn)擊進(jìn)入...”);
startPic=(ImageView)findViewById(R.id.startpic);
startPic.setImageDrawable(getResources().
getDrawable(R.drawable.startup));
startPic.setOnClickListener(newImageView.OnClickListener(){
publicvoidonClick(Viewv){
Intentintent=newIntent();
intent.setClass(main.this,login.class);
startActivity(intent);
main.this.finish();
}
}); BluetoothAdaptercwjBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
if(cwjBluetoothAdapter==null){
newAlertDialog.Builder(main.this)
.setTitle(R.string.error)
.setIcon(R.drawable.error)
.setMessage(R.string.no_bluetooth) .setPositiveButton(R.string.certain,
newDialogInterface.OnClickListener()
{
publicvoidonClick(DialogInterfacedialoginterface,inti)
{
//main.this.finish();
}
}
)
.show(
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 質(zhì)量檢驗(yàn)員聘用合同格式
- 2024年度醫(yī)療器械代理注冊(cè)合同規(guī)范范本3篇
- 食品安全合同管理流程
- 2025年度五星級(jí)酒店VIP客戶住宿服務(wù)協(xié)議書3篇
- 能源檢測(cè)薪資結(jié)構(gòu)
- 語(yǔ)言培訓(xùn)中心外教勞動(dòng)合同樣本
- 2025奧菱達(dá)電梯有限企業(yè)電梯部件供應(yīng)及維修服務(wù)協(xié)議3篇
- 施工成本鋼結(jié)構(gòu)安全協(xié)議
- 投資入伙協(xié)議書范本
- 2025年度口腔醫(yī)療市場(chǎng)營(yíng)銷合作協(xié)議書3篇
- 湖南省部分學(xué)校2023-2024學(xué)年高二上學(xué)期期末聯(lián)合考試政治試卷 含解析
- 電大《人力資源管理》期末復(fù)習(xí)綜合練習(xí)題答案(2024年)
- 西師版數(shù)學(xué)(四上題)2023-2024學(xué)年度小學(xué)學(xué)業(yè)質(zhì)量監(jiān)測(cè)(試卷)
- 2022-2023學(xué)年廣東省廣州市白云區(qū)華南師大附屬太和實(shí)驗(yàn)學(xué)校九年級(jí)(上)期末數(shù)學(xué)試卷(含答案)
- 2024年煤礦安全生產(chǎn)知識(shí)競(jìng)賽題庫(kù)及答案(共100題)
- 古代小說(shuō)戲曲專題-形考任務(wù)2-國(guó)開-參考資料
- GA/T 2133.1-2024便攜式微型計(jì)算機(jī)移動(dòng)警務(wù)終端第1部分:技術(shù)要求
- 人教版四年級(jí)上冊(cè)數(shù)學(xué)數(shù)學(xué)復(fù)習(xí)資料
- 個(gè)人營(yíng)業(yè)執(zhí)照注銷委托書范文
- SB/T 10439-2007醬腌菜
- 氨吹脫塔單元設(shè)計(jì)標(biāo)準(zhǔn)規(guī)定樣式(共15頁(yè))
評(píng)論
0/150
提交評(píng)論