Android使用HttpURLConnection實(shí)現(xiàn)網(wǎng)絡(luò)訪問流程
一、管理網(wǎng)絡(luò)狀態(tài)
使用網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)通信前,需要先獲取網(wǎng)絡(luò)狀態(tài)。
使用ConnectivityManager獲取網(wǎng)絡(luò)狀態(tài)步驟:
1.獲取ConnectivityManager對象
2.獲取當(dāng)前活動(dòng)的網(wǎng)絡(luò)NetworkInfo對象
3.判斷當(dāng)前網(wǎng)絡(luò)狀態(tài)是否為連接狀態(tài)
4.在AndroidMainfest.xml中添加訪問當(dāng)前網(wǎng)絡(luò)狀態(tài)權(quán)限
//使用ConnectivityManager檢查網(wǎng)絡(luò)狀態(tài)步驟 private boolean checkNetworkState() { ConnectivityManager connectivityManager = (ConnectivityManager) this.getSystemService(CONNECTIVITY_SERVICE);//1.通過系統(tǒng)服務(wù)獲取ConnectivityManager類的對象 NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();//2.調(diào)用getActiveNetworkInfo()獲取當(dāng)前活動(dòng)的網(wǎng)絡(luò)NetworkInfo對象 if (networkInfo==null || networkInfo.isConnected()==false) {//3.判斷當(dāng)前網(wǎng)絡(luò)狀態(tài)是否為連接狀態(tài),如果當(dāng)前沒有網(wǎng)絡(luò)是活動(dòng)的,則返回null return false; }else { return true; } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.httpurlexestud"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><!--檢查網(wǎng)絡(luò)狀態(tài)步驟4.添加訪問當(dāng)前網(wǎng)絡(luò)狀態(tài)權(quán)限--> <uses-permission android:name="android.permission.INTERNET"/><!--增加訪問網(wǎng)絡(luò)授權(quán)聲明--> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".WelcomeActivity"></activity> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
二、HTTP協(xié)議
1.HTTP(Hyper Text Transfer Protocol) 即超文本傳輸協(xié)議,是一種詳細(xì)規(guī)定了客戶端和萬維網(wǎng)(www,World Wide Web)服務(wù)器之間互相通信的規(guī)則,通過因特網(wǎng)傳送萬維網(wǎng)文檔的數(shù)據(jù)傳送協(xié)議。
2.HTTP協(xié)議是一種請求/響應(yīng)式的協(xié)議。當(dāng)客戶端與服務(wù)器端建立連接后,向服務(wù)器端發(fā)送的請求,稱作HTTP請求;當(dāng)服務(wù)器端接收到請求后會(huì)做出響應(yīng),稱為HTTP響應(yīng)。
三、HttpURLConnection
HttpURLConnection類位于java.net內(nèi),提供了基于HTTP的網(wǎng)絡(luò)訪問方法。
使用HttpURLConnection訪問HTTP資源的主要操作步驟:
1.利用URL地址實(shí)例化URL類
2.由URL類創(chuàng)建HttpURLConnection對象
3.以GET/POST方式向服務(wù)器發(fā)送請求
4.接收服務(wù)器響應(yīng)
5.關(guān)閉連接
HTTP協(xié)議使用注意事項(xiàng):
1.使用“ .setRequestMethod(" "); ”設(shè)置請求方式
2.使用“ .connect(); ”連接網(wǎng)絡(luò)。請求行、請求頭的設(shè)置必須放在網(wǎng)絡(luò)連接前
3.“ .getInputStream() ”只是得到一個(gè)流對象,并不是數(shù)據(jù)。我們需要從流中讀取數(shù)據(jù),從流中讀取數(shù)據(jù)的操作必須放在子線程
4.“ .getInputStream() ”得到一個(gè)流對象,從這個(gè)流對象中只能讀取一次數(shù)據(jù),第二次讀取時(shí)將會(huì)得到空數(shù)據(jù)
四、GET和POST請求方式
1.GET方式是以實(shí)體的方式得到由請求URL所指向的資源信息,它向服務(wù)器提交的參數(shù)跟在請求URL后面。使用GET方式訪問網(wǎng)絡(luò)URL的長度一般要小于1K
2.POST方式向服務(wù)器發(fā)送請求時(shí)需要在請求后附加實(shí)體,它向服務(wù)器提交的參數(shù)在請求后的實(shí)體中。POST方式對URL的長度沒有限制
3.采用POST方式提交數(shù)據(jù)時(shí),用戶在瀏覽器中看不到向服務(wù)器提交的請求參數(shù),因此POST方式要比GET方式相對安全。
4.GET重點(diǎn)在從服務(wù)器上獲取資源,POST重點(diǎn)在向服務(wù)器發(fā)送數(shù)據(jù)。
5.GET傳輸?shù)臄?shù)據(jù)量小,因?yàn)槭躑RL長度限制,但效率較高;POST沒有此限制,可以傳輸大量數(shù)據(jù),所以上傳文件時(shí)只能用POST方式。
6.GET方式只能支持ASCII字符,向服務(wù)器傳的中文字符可能會(huì)亂碼;POST支持標(biāo)準(zhǔn)字符集,可以正確傳遞中文字符。
注意事項(xiàng):
1.所有內(nèi)容都需要訪問網(wǎng)絡(luò)才能進(jìn)行發(fā)送或者獲取,因此需要配置文件AndroidMainfest.xml文件中添加訪問網(wǎng)絡(luò)的權(quán)限(第一部分里已給出代碼)。
2.實(shí)際開發(fā)中,手機(jī)端與服務(wù)器端進(jìn)行交互的過程中,避免不了要提交中文到服務(wù)器,這時(shí)就會(huì)出現(xiàn)中文亂碼的情況。因此,無論是GET方式還是POST方式提交參數(shù)時(shí)都要對參數(shù)進(jìn)行編碼。需要注意的是,編碼方式必須與服務(wù)器解碼方式一致。同樣,在獲取服務(wù)器返回的中文字符時(shí),也需要用指定格式進(jìn)行解碼。
(1)以GET方式提交數(shù)據(jù)
/*一、GET方式步驟: 1.把用戶名和密碼拼接成以get方式向服務(wù)器發(fā)送請求的URL字符串 2.使用url的openConnection()方法獲得HttpURLConnection對象 3.設(shè)置HttpURLConnection對象的請求方式、超時(shí)等,并調(diào)用connect()建立連接 4.得到響應(yīng)碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務(wù)器返回信息的輸入流,從流中讀取出服務(wù)器返回值,并向handler發(fā)送消息 5.斷開連接*/ String urlStr = "http://192.192.192.192:8080/TestServer/servlet/Login?name="+ URLEncoder.encode(name)+ "&pass="+URLEncoder.encode(pwd);//將用戶名和密碼拼在指定資源路徑后面,并對用戶名和密碼進(jìn)行編碼 try {//使用try-catch-finally捕獲異常 url = new URL(urlStr);//在URL的構(gòu)造方法中傳入要訪問資源的路徑 uc = (HttpURLConnection) url.openConnection();//返回一個(gè)HttpURLConnection對象 uc.setRequestMethod("GET");//設(shè)置GET請求方式 uc.setConnectTimeout(5000);//設(shè)置超時(shí)時(shí)間 uc.connect();//連接 int code = uc.getResponseCode();//得到響應(yīng)碼(獲取HTTP狀態(tài)碼) if (code == HttpURLConnection.HTTP_OK) {//4.得到響應(yīng)碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務(wù)器返回信息的輸入流,從流中讀取出服務(wù)器返回值,并向handler發(fā)送消息 System.out.println(uc.getResponseCode());//控制臺(tái)輸出 InputStream inputStream = uc.getInputStream();//得到響應(yīng)流(通過getInputStream()方法獲取攜帶服務(wù)器返回信息的輸入流) int i = inputStream.read(); System.out.println(i);//控制臺(tái)顯示是0還是1,以ASCII碼形式顯示 //通過Message和handler.sendMessage()將返回結(jié)果傳遞給UI線程 Message message = Message.obtain();//從服務(wù)器返回的數(shù)據(jù),1.獲取可用的Message對象 message.arg1 =i;//2.通過message的arg1傳遞參數(shù) handler.sendMessage(message);//發(fā)送至主界面顯示 }else { System.out.println(uc.getResponseCode());//控制臺(tái)輸出 Message message = Message.obtain(); message.arg1 =2; handler.sendMessage(message); } }catch (Exception e) { e.printStackTrace(); }finally { if (uc != null) { uc.disconnect();//關(guān)閉HTTP連接 } }
(2)以POST方式提交數(shù)據(jù)
/*二、POST方式步驟: 1.通過URL字符串創(chuàng)建URL對象 2.使用url的openConnection()方法獲得HttpURLConnection對象 3.設(shè)置HttpURLConnection對象的請求方式、超時(shí)、請求頭數(shù)據(jù)提交方式等,并調(diào)用connect()建立連接 4.通過getOutputStream()獲得輸出流往服務(wù)器寫數(shù)據(jù) 5.得到響應(yīng)碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務(wù)器返回信息的輸入流,從流中讀取出服務(wù)器返回值,并向handler發(fā)送消息 6.斷開連接*/ String urlStr = "http://192.192.192.192:8080/TestServer/servlet/Login"; try {//使用try-catch-finally捕獲異常 url = new URL(urlStr);//在URL的構(gòu)造方法中傳入要訪問資源的路徑 uc = (HttpURLConnection) url.openConnection();//返回一個(gè)HttpURLConnection對象 uc.setRequestMethod("POST");//設(shè)置POST請求方式 uc.setConnectTimeout(5000);//設(shè)置超時(shí)時(shí)間 String data = "name="+ URLEncoder.encode(name) + "&pass="+URLEncoder.encode(pwd); uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");//設(shè)置請求頭數(shù)據(jù)提交方式,這里以form表單形式提交 uc.setRequestProperty("Content-Length", data.length()+"");//設(shè)置請求頭,設(shè)置提交數(shù)據(jù)的長度 //POST方式,實(shí)際是瀏覽器把數(shù)據(jù)寫給了服務(wù)器 uc.setDoOutput(true);//設(shè)置允許向外寫數(shù)據(jù) uc.connect();//連接 //4.通過getOutputStream()獲得輸出流往服務(wù)器寫數(shù)據(jù) OutputStream outputStream = uc.getOutputStream();//通過getOutputStream()獲得輸出流 outputStream.write(data.getBytes()); int code = uc.getResponseCode();//獲取HTTP狀態(tài)碼 if (code == HttpURLConnection.HTTP_OK) {//5.得到響應(yīng)碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務(wù)器返回信息的輸入流,從流中讀取出服務(wù)器返回值,并向handler發(fā)送消息 System.out.println(uc.getResponseCode());//控制臺(tái)輸出 InputStream inputStream = uc.getInputStream();//得到響應(yīng)流(通過getInputStream()方法獲取攜帶服務(wù)器返回信息的輸入流) int i = inputStream.read(); System.out.println(i);//控制臺(tái)顯示是0還是1,以ASCII碼形式顯示 //通過Message和handler.sendMessage()將返回結(jié)果傳遞給UI線程 Message message = Message.obtain();//從服務(wù)器返回的數(shù)據(jù),1.獲取可用的Message對象 message.arg1 =i;//2.通過message的arg1傳遞參數(shù) handler.sendMessage(message);//發(fā)送至主界面顯示 }else { System.out.println(uc.getResponseCode());//控制臺(tái)輸出 Message message = Message.obtain();//從服務(wù)器返回的數(shù)據(jù),1.獲取可用的Message對象 message.arg1 =2;//2.通過message的arg1傳遞參數(shù) handler.sendMessage(message);//發(fā)送至主界面顯示 } }catch (Exception e) { e.printStackTrace(); }finally { if (uc != null) { uc.disconnect();//關(guān)閉HTTP連接 } }
五、做個(gè)實(shí)驗(yàn)
(一)實(shí)驗(yàn)效果如圖所示
(二)實(shí)驗(yàn)步驟
MainActivity.java文件
1.在MainActivity.java中使用ConnectivityManager獲取網(wǎng)絡(luò)狀態(tài),完成網(wǎng)絡(luò)狀態(tài)判斷方法checkNetworkState()的實(shí)現(xiàn),具體步驟和代碼在第一部分中已經(jīng)給出
2.在 “登錄”按鈕的事件監(jiān)聽方法btnLogin.setOnClickListener()中,新建線程并使用HttpURLConnection訪問服務(wù)器進(jìn)行用戶名和密碼的驗(yàn)證,并將結(jié)果發(fā)送給Handler對象
重寫run()方法中采用GET或POST方法提交數(shù)據(jù),代碼在第四部分已經(jīng)給出
btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String name=edName.getText().toString(); final String pwd=edPwd.getText().toString(); if(checkNetworkState()!=true){//判斷是否聯(lián)網(wǎng) Toast.makeText(MainActivity.this,"網(wǎng)絡(luò)沒有打開,請打開網(wǎng)絡(luò)后再試。",Toast.LENGTH_LONG).show(); }else { if (name.equals("")) { Toast toast = Toast.makeText(MainActivity.this, "輸入用戶名", Toast.LENGTH_LONG); toast.show(); }else if (pwd.equals("")) { Toast toast = Toast.makeText(MainActivity.this, "輸入密碼", Toast.LENGTH_LONG); toast.show(); }else { //新建線程,并通過GET或post方式把用戶名和密碼向服務(wù)器發(fā)送請求并將結(jié)果發(fā)送給Handler對象 new Thread(new Runnable() { @Override public void run() {//重寫run()方法 } }).start(); } } } });
3.在onCreate()方法外部,實(shí)現(xiàn)Handler的handleMessage()方法,根據(jù)服務(wù)器返回結(jié)果判斷是否登錄成功
final Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { //通過msg中傳遞數(shù)據(jù)判斷是否登錄成功,若成功則實(shí)現(xiàn)界面跳轉(zhuǎn)到WelcomeActivity int i = msg.arg1; if (i==49) {//界面跳轉(zhuǎn) Intent intent = new Intent(MainActivity.this, WelcomeActivity.class); startActivity(intent); }else if (i==48) {//Toast提示用戶名或密碼錯(cuò)誤 Toast.makeText(MainActivity.this, "用戶名或密碼錯(cuò)誤!", Toast.LENGTH_LONG).show(); }else {//Toast提示連接失敗 Toast.makeText(MainActivity.this, "網(wǎng)絡(luò)連接失??!", Toast.LENGTH_LONG).show(); } } };
WelcomeActivity.java文件
4.完成DownloadTask類中各個(gè)方法的實(shí)現(xiàn)。doInBackground()方法中使用HttpURLConnection訪問服務(wù)器并下載圖片,下載過程中實(shí)時(shí)發(fā)布下載進(jìn)度,下載完成后返回Bitmap對象
class DownloadTask extends AsyncTask<String, Integer, Bitmap> {//分別代表:執(zhí)行后臺(tái)任務(wù)傳遞的參數(shù)、更新的進(jìn)度值的類型(都是整形) 、返回結(jié)果類型 @Override protected void onPreExecute() {//UI組件初始化設(shè)置 super.onPreExecute(); textView.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE); progressBar.setProgress(0);//設(shè)置進(jìn)度條初始值為0 } @Override protected Bitmap doInBackground(String... strings) { URL url; HttpURLConnection urlConnection = null; Bitmap bitmap = null; pbValue=0;//初始值為0 try { /*url = new URL(strings[0]);//在URL構(gòu)造方法中傳入要訪問資源的路徑*/ url = new URL(urlStr); urlConnection = (HttpURLConnection) url.openConnection();//根據(jù)url發(fā)送一個(gè)http的請求 urlConnection.setRequestMethod("GET");//設(shè)置GET請求方式 urlConnection.setConnectTimeout(5000);//設(shè)置超時(shí)時(shí)間 urlConnection.connect();//連接 if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK /*urlConnection.getResponseCode() == 200*/ ) {//得到響應(yīng)碼,判斷連接是否正常 System.out.println(urlConnection.getResponseCode());//控制臺(tái)輸出 InputStream inputStream = urlConnection.getInputStream();//通過getInputStream()方法獲得攜帶服務(wù)器返回信息的輸入流 System.out.println(inputStream);//控制臺(tái)顯示是0還是1,以ASCII碼形式顯示 int maxSize = urlConnection.getContentLength();//通過urlConnection的getContentLength()獲取下載圖片的總大小 byte[] buffer = new byte[1024*8]; int len = -1; int process =0; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); while((len = inputStream.read(buffer)) != -1) {//通過inputStream.read(buffer)和while循環(huán)讀取數(shù)據(jù),并通過ByteArrayOutputStream將數(shù)據(jù)寫入 process += len; byteArrayOutputStream.write(buffer, 0, len); Thread.sleep(50);//每隔50ms通過publishProgress()發(fā)布進(jìn)度值 pbValue = (int) ((((double)process)/maxSize)*progressBar.getMax());//計(jì)算數(shù)據(jù)下載的完成百分比 publishProgress(pbValue);//發(fā)布進(jìn)度 } /*byteArrayOutputStream.flush();*/ //數(shù)據(jù)讀取完成后通過BitmapFactory.decodeByteArray()將ByteArrayOutputStream對象out中數(shù)據(jù)轉(zhuǎn)換成Bitmap對象并返回 byte[] result = byteArrayOutputStream.toByteArray(); bitmap = BitmapFactory.decodeByteArray(result, 0, maxSize); /*bitmap = BitmapFactory.decodeByteArray(byteArrayOutputStream.toByteArray(), 0, maxSize);*/ } }catch (Exception e) { e.printStackTrace(); }finally { if (urlConnection != null) { urlConnection.disconnect();//關(guān)閉HTTP連接 } return bitmap; } } @Override protected void onProgressUpdate(Integer... values) {//下載過程中更新TextView和進(jìn)度條的進(jìn)度值 super.onProgressUpdate(values); textView.setText("已下載"+ values[0]+"%"); progressBar.setProgress(values[0]); } @Override protected void onPostExecute(Bitmap bitmap) {//下載完成后更新TextView和進(jìn)度條 super.onPostExecute(bitmap); Toast.makeText(WelcomeActivity.this, "加載完畢", Toast.LENGTH_SHORT).show(); textView.setText("恭喜!下載完成!"); progressBar.setVisibility(View.INVISIBLE);//下載完成后進(jìn)度條消失 imageView.setImageBitmap(bitmap); } }
5.在“下載圖片”按鈕的事件監(jiān)聽方法btnGetPic.setOnClickListener ()中,新建DownloadTask類的異步任務(wù)并調(diào)用execute(urlStr)方法執(zhí)行網(wǎng)絡(luò)圖片的下載任務(wù)
btnGetPic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new DownloadTask().execute(urlStr);//創(chuàng)建DownloadTask實(shí)例對象,并調(diào)用其execute()方法 } });
完整代碼請從這里下載
注意事項(xiàng):
1.我上傳的壓縮包中包含兩個(gè)文件,TestServer要導(dǎo)入myeclipse中,HttpUrlExeStud導(dǎo)入Android Studio中
2.TestServer下存在一個(gè)Login文件,其中
if(name!=null && pass!=null && name.equals("JMX") && pass.equals("666"))
包含了我的用戶名和密碼,你可以進(jìn)行更換,建議用戶名設(shè)置為英文
3.TestServer必須運(yùn)行起來,右擊TestServer項(xiàng)目,點(diǎn)擊Run As – 3 MyEclipse Server Application,彈出如下界面則表示成功
4.HttpUrlExeStud下MainActivity.java的GET、POST方法和WelcomeActivity.java分別包含這幾行代碼
String urlStr = "http://192.192.192.192:8080/TestServer/servlet/Login?name="+URLEncoder.encode(name)+"&pass="+URLEncoder.encode(pwd);
String urlStr = "http://192.192.192.192:8080/TestServer/servlet/Login";
final String urlStr="http://192.192.192.192:8080/TestServer/pic/bamboo1.jpg";
其中192.192.192.192是我的ip地址,實(shí)際運(yùn)行時(shí)需要替換成你自己的ip地址??梢酝ㄟ^win+R,鍵入cmd,輸入ipconfig的方式獲取到計(jì)算機(jī)ip信息
到此這篇關(guān)于Android使用HttpURLConnection實(shí)現(xiàn)網(wǎng)絡(luò)訪問流程的文章就介紹到這了,更多相關(guān)Android HttpURLConnection內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Flutter利用Canvas模擬實(shí)現(xiàn)微信紅包領(lǐng)取效果
這篇文章主要為大家詳細(xì)介紹了如何利用Flutter中的Canvas模擬實(shí)現(xiàn)微信紅包領(lǐng)取的效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-03-03Android基于OpenCV實(shí)現(xiàn)霍夫直線檢測
霍夫變換利用點(diǎn)與線之間的對偶性,將圖像空間中直線上離散的像素點(diǎn)通過參數(shù)方程映射為霍夫空間中的曲線,并將霍夫空間中多條曲線的交點(diǎn)作為直線方程的參數(shù)映射為圖像空間中的直線。給定直線的參數(shù)方程,可以利用霍夫變換來檢測圖像中的直線。本文簡單講解Android的實(shí)現(xiàn)2021-06-06Android5.0 旋轉(zhuǎn)菜單實(shí)例詳解
這篇文章主要介紹了 Android5.0 旋轉(zhuǎn)菜單的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2016-12-12微前端架構(gòu)ModuleFederationPlugin源碼解析
這篇文章主要為大家介紹了微前端架構(gòu)ModuleFederationPlugin源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11用Flutter做桌上彈球(繪圖(Canvas&CustomPaint)API)
這篇文章主要介紹了用Flutter做桌上彈球 聊聊繪圖(Canvas&CustomPaint)API,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07100行Android代碼輕松實(shí)現(xiàn)帶動(dòng)畫柱狀圖
這篇文章主要教大家通過100行Android代碼輕松實(shí)現(xiàn)帶動(dòng)畫柱狀圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Android?Jetpack?組件LiveData源碼解析
這篇文章主要為大家介紹了Android?Jetpack?組件LiveData源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03android中圖片翻頁效果簡單的實(shí)現(xiàn)方法
android中圖片翻頁效果簡單的實(shí)現(xiàn)方法,需要的朋友可以參考一下2013-05-05