Android使用HttpURLConnection實現網絡訪問流程
一、管理網絡狀態(tài)
使用網絡進行數據通信前,需要先獲取網絡狀態(tài)。
使用ConnectivityManager獲取網絡狀態(tài)步驟:
1.獲取ConnectivityManager對象
2.獲取當前活動的網絡NetworkInfo對象
3.判斷當前網絡狀態(tài)是否為連接狀態(tài)
4.在AndroidMainfest.xml中添加訪問當前網絡狀態(tài)權限
//使用ConnectivityManager檢查網絡狀態(tài)步驟
private boolean checkNetworkState() {
ConnectivityManager connectivityManager = (ConnectivityManager) this.getSystemService(CONNECTIVITY_SERVICE);//1.通過系統服務獲取ConnectivityManager類的對象
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();//2.調用getActiveNetworkInfo()獲取當前活動的網絡NetworkInfo對象
if (networkInfo==null || networkInfo.isConnected()==false) {//3.判斷當前網絡狀態(tài)是否為連接狀態(tài),如果當前沒有網絡是活動的,則返回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"/><!--檢查網絡狀態(tài)步驟4.添加訪問當前網絡狀態(tài)權限-->
<uses-permission android:name="android.permission.INTERNET"/><!--增加訪問網絡授權聲明-->
<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協議
1.HTTP(Hyper Text Transfer Protocol) 即超文本傳輸協議,是一種詳細規(guī)定了客戶端和萬維網(www,World Wide Web)服務器之間互相通信的規(guī)則,通過因特網傳送萬維網文檔的數據傳送協議。
2.HTTP協議是一種請求/響應式的協議。當客戶端與服務器端建立連接后,向服務器端發(fā)送的請求,稱作HTTP請求;當服務器端接收到請求后會做出響應,稱為HTTP響應。
三、HttpURLConnection
HttpURLConnection類位于java.net內,提供了基于HTTP的網絡訪問方法。
使用HttpURLConnection訪問HTTP資源的主要操作步驟:
1.利用URL地址實例化URL類
2.由URL類創(chuàng)建HttpURLConnection對象
3.以GET/POST方式向服務器發(fā)送請求
4.接收服務器響應
5.關閉連接
HTTP協議使用注意事項:
1.使用“ .setRequestMethod(" "); ”設置請求方式
2.使用“ .connect(); ”連接網絡。請求行、請求頭的設置必須放在網絡連接前
3.“ .getInputStream() ”只是得到一個流對象,并不是數據。我們需要從流中讀取數據,從流中讀取數據的操作必須放在子線程
4.“ .getInputStream() ”得到一個流對象,從這個流對象中只能讀取一次數據,第二次讀取時將會得到空數據
四、GET和POST請求方式
1.GET方式是以實體的方式得到由請求URL所指向的資源信息,它向服務器提交的參數跟在請求URL后面。使用GET方式訪問網絡URL的長度一般要小于1K
2.POST方式向服務器發(fā)送請求時需要在請求后附加實體,它向服務器提交的參數在請求后的實體中。POST方式對URL的長度沒有限制
3.采用POST方式提交數據時,用戶在瀏覽器中看不到向服務器提交的請求參數,因此POST方式要比GET方式相對安全。
4.GET重點在從服務器上獲取資源,POST重點在向服務器發(fā)送數據。
5.GET傳輸的數據量小,因為受URL長度限制,但效率較高;POST沒有此限制,可以傳輸大量數據,所以上傳文件時只能用POST方式。
6.GET方式只能支持ASCII字符,向服務器傳的中文字符可能會亂碼;POST支持標準字符集,可以正確傳遞中文字符。
注意事項:
1.所有內容都需要訪問網絡才能進行發(fā)送或者獲取,因此需要配置文件AndroidMainfest.xml文件中添加訪問網絡的權限(第一部分里已給出代碼)。
2.實際開發(fā)中,手機端與服務器端進行交互的過程中,避免不了要提交中文到服務器,這時就會出現中文亂碼的情況。因此,無論是GET方式還是POST方式提交參數時都要對參數進行編碼。需要注意的是,編碼方式必須與服務器解碼方式一致。同樣,在獲取服務器返回的中文字符時,也需要用指定格式進行解碼。
(1)以GET方式提交數據
/*一、GET方式步驟:
1.把用戶名和密碼拼接成以get方式向服務器發(fā)送請求的URL字符串
2.使用url的openConnection()方法獲得HttpURLConnection對象
3.設置HttpURLConnection對象的請求方式、超時等,并調用connect()建立連接
4.得到響應碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務器返回信息的輸入流,從流中讀取出服務器返回值,并向handler發(fā)送消息
5.斷開連接*/
String urlStr = "http://192.192.192.192:8080/TestServer/servlet/Login?name="+
URLEncoder.encode(name)+
"&pass="+URLEncoder.encode(pwd);//將用戶名和密碼拼在指定資源路徑后面,并對用戶名和密碼進行編碼
try {//使用try-catch-finally捕獲異常
url = new URL(urlStr);//在URL的構造方法中傳入要訪問資源的路徑
uc = (HttpURLConnection) url.openConnection();//返回一個HttpURLConnection對象
uc.setRequestMethod("GET");//設置GET請求方式
uc.setConnectTimeout(5000);//設置超時時間
uc.connect();//連接
int code = uc.getResponseCode();//得到響應碼(獲取HTTP狀態(tài)碼)
if (code == HttpURLConnection.HTTP_OK) {//4.得到響應碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務器返回信息的輸入流,從流中讀取出服務器返回值,并向handler發(fā)送消息
System.out.println(uc.getResponseCode());//控制臺輸出
InputStream inputStream = uc.getInputStream();//得到響應流(通過getInputStream()方法獲取攜帶服務器返回信息的輸入流)
int i = inputStream.read();
System.out.println(i);//控制臺顯示是0還是1,以ASCII碼形式顯示
//通過Message和handler.sendMessage()將返回結果傳遞給UI線程
Message message = Message.obtain();//從服務器返回的數據,1.獲取可用的Message對象
message.arg1 =i;//2.通過message的arg1傳遞參數
handler.sendMessage(message);//發(fā)送至主界面顯示
}else {
System.out.println(uc.getResponseCode());//控制臺輸出
Message message = Message.obtain();
message.arg1 =2;
handler.sendMessage(message);
}
}catch (Exception e) {
e.printStackTrace();
}finally {
if (uc != null) {
uc.disconnect();//關閉HTTP連接
}
}
(2)以POST方式提交數據
/*二、POST方式步驟:
1.通過URL字符串創(chuàng)建URL對象
2.使用url的openConnection()方法獲得HttpURLConnection對象
3.設置HttpURLConnection對象的請求方式、超時、請求頭數據提交方式等,并調用connect()建立連接
4.通過getOutputStream()獲得輸出流往服務器寫數據
5.得到響應碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務器返回信息的輸入流,從流中讀取出服務器返回值,并向handler發(fā)送消息
6.斷開連接*/
String urlStr = "http://192.192.192.192:8080/TestServer/servlet/Login";
try {//使用try-catch-finally捕獲異常
url = new URL(urlStr);//在URL的構造方法中傳入要訪問資源的路徑
uc = (HttpURLConnection) url.openConnection();//返回一個HttpURLConnection對象
uc.setRequestMethod("POST");//設置POST請求方式
uc.setConnectTimeout(5000);//設置超時時間
String data = "name="+ URLEncoder.encode(name) +
"&pass="+URLEncoder.encode(pwd);
uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");//設置請求頭數據提交方式,這里以form表單形式提交
uc.setRequestProperty("Content-Length", data.length()+"");//設置請求頭,設置提交數據的長度
//POST方式,實際是瀏覽器把數據寫給了服務器
uc.setDoOutput(true);//設置允許向外寫數據
uc.connect();//連接
//4.通過getOutputStream()獲得輸出流往服務器寫數據
OutputStream outputStream = uc.getOutputStream();//通過getOutputStream()獲得輸出流
outputStream.write(data.getBytes());
int code = uc.getResponseCode();//獲取HTTP狀態(tài)碼
if (code == HttpURLConnection.HTTP_OK) {//5.得到響應碼并判斷連接正常后,通過getInputStream()方法獲得攜帶服務器返回信息的輸入流,從流中讀取出服務器返回值,并向handler發(fā)送消息
System.out.println(uc.getResponseCode());//控制臺輸出
InputStream inputStream = uc.getInputStream();//得到響應流(通過getInputStream()方法獲取攜帶服務器返回信息的輸入流)
int i = inputStream.read();
System.out.println(i);//控制臺顯示是0還是1,以ASCII碼形式顯示
//通過Message和handler.sendMessage()將返回結果傳遞給UI線程
Message message = Message.obtain();//從服務器返回的數據,1.獲取可用的Message對象
message.arg1 =i;//2.通過message的arg1傳遞參數
handler.sendMessage(message);//發(fā)送至主界面顯示
}else {
System.out.println(uc.getResponseCode());//控制臺輸出
Message message = Message.obtain();//從服務器返回的數據,1.獲取可用的Message對象
message.arg1 =2;//2.通過message的arg1傳遞參數
handler.sendMessage(message);//發(fā)送至主界面顯示
}
}catch (Exception e) {
e.printStackTrace();
}finally {
if (uc != null) {
uc.disconnect();//關閉HTTP連接
}
}五、做個實驗
(一)實驗效果如圖所示




(二)實驗步驟
MainActivity.java文件
1.在MainActivity.java中使用ConnectivityManager獲取網絡狀態(tài),完成網絡狀態(tài)判斷方法checkNetworkState()的實現,具體步驟和代碼在第一部分中已經給出
2.在 “登錄”按鈕的事件監(jiān)聽方法btnLogin.setOnClickListener()中,新建線程并使用HttpURLConnection訪問服務器進行用戶名和密碼的驗證,并將結果發(fā)送給Handler對象
重寫run()方法中采用GET或POST方法提交數據,代碼在第四部分已經給出
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){//判斷是否聯網
Toast.makeText(MainActivity.this,"網絡沒有打開,請打開網絡后再試。",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方式把用戶名和密碼向服務器發(fā)送請求并將結果發(fā)送給Handler對象
new Thread(new Runnable() {
@Override
public void run() {//重寫run()方法
}
}).start();
}
}
}
});3.在onCreate()方法外部,實現Handler的handleMessage()方法,根據服務器返回結果判斷是否登錄成功
final Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
//通過msg中傳遞數據判斷是否登錄成功,若成功則實現界面跳轉到WelcomeActivity
int i = msg.arg1;
if (i==49) {//界面跳轉
Intent intent = new Intent(MainActivity.this, WelcomeActivity.class);
startActivity(intent);
}else if (i==48) {//Toast提示用戶名或密碼錯誤
Toast.makeText(MainActivity.this, "用戶名或密碼錯誤!", Toast.LENGTH_LONG).show();
}else {//Toast提示連接失敗
Toast.makeText(MainActivity.this, "網絡連接失敗!", Toast.LENGTH_LONG).show();
}
}
};
WelcomeActivity.java文件
4.完成DownloadTask類中各個方法的實現。doInBackground()方法中使用HttpURLConnection訪問服務器并下載圖片,下載過程中實時發(fā)布下載進度,下載完成后返回Bitmap對象
class DownloadTask extends AsyncTask<String, Integer, Bitmap> {//分別代表:執(zhí)行后臺任務傳遞的參數、更新的進度值的類型(都是整形) 、返回結果類型
@Override
protected void onPreExecute() {//UI組件初始化設置
super.onPreExecute();
textView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(0);//設置進度條初始值為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構造方法中傳入要訪問資源的路徑*/
url = new URL(urlStr);
urlConnection = (HttpURLConnection) url.openConnection();//根據url發(fā)送一個http的請求
urlConnection.setRequestMethod("GET");//設置GET請求方式
urlConnection.setConnectTimeout(5000);//設置超時時間
urlConnection.connect();//連接
if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK /*urlConnection.getResponseCode() == 200*/ ) {//得到響應碼,判斷連接是否正常
System.out.println(urlConnection.getResponseCode());//控制臺輸出
InputStream inputStream = urlConnection.getInputStream();//通過getInputStream()方法獲得攜帶服務器返回信息的輸入流
System.out.println(inputStream);//控制臺顯示是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)讀取數據,并通過ByteArrayOutputStream將數據寫入
process += len;
byteArrayOutputStream.write(buffer, 0, len);
Thread.sleep(50);//每隔50ms通過publishProgress()發(fā)布進度值
pbValue = (int) ((((double)process)/maxSize)*progressBar.getMax());//計算數據下載的完成百分比
publishProgress(pbValue);//發(fā)布進度
}
/*byteArrayOutputStream.flush();*/
//數據讀取完成后通過BitmapFactory.decodeByteArray()將ByteArrayOutputStream對象out中數據轉換成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();//關閉HTTP連接
}
return bitmap;
}
}
@Override
protected void onProgressUpdate(Integer... values) {//下載過程中更新TextView和進度條的進度值
super.onProgressUpdate(values);
textView.setText("已下載"+ values[0]+"%");
progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {//下載完成后更新TextView和進度條
super.onPostExecute(bitmap);
Toast.makeText(WelcomeActivity.this, "加載完畢", Toast.LENGTH_SHORT).show();
textView.setText("恭喜!下載完成!");
progressBar.setVisibility(View.INVISIBLE);//下載完成后進度條消失
imageView.setImageBitmap(bitmap);
}
}5.在“下載圖片”按鈕的事件監(jiān)聽方法btnGetPic.setOnClickListener ()中,新建DownloadTask類的異步任務并調用execute(urlStr)方法執(zhí)行網絡圖片的下載任務
btnGetPic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new DownloadTask().execute(urlStr);//創(chuàng)建DownloadTask實例對象,并調用其execute()方法
}
});
完整代碼請從這里下載
注意事項:
1.我上傳的壓縮包中包含兩個文件,TestServer要導入myeclipse中,HttpUrlExeStud導入Android Studio中
2.TestServer下存在一個Login文件,其中
if(name!=null && pass!=null && name.equals("JMX") && pass.equals("666"))包含了我的用戶名和密碼,你可以進行更換,建議用戶名設置為英文
3.TestServer必須運行起來,右擊TestServer項目,點擊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地址,實際運行時需要替換成你自己的ip地址??梢酝ㄟ^win+R,鍵入cmd,輸入ipconfig的方式獲取到計算機ip信息
到此這篇關于Android使用HttpURLConnection實現網絡訪問流程的文章就介紹到這了,更多相關Android HttpURLConnection內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
微前端架構ModuleFederationPlugin源碼解析
這篇文章主要為大家介紹了微前端架構ModuleFederationPlugin源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11
用Flutter做桌上彈球(繪圖(Canvas&CustomPaint)API)
這篇文章主要介紹了用Flutter做桌上彈球 聊聊繪圖(Canvas&CustomPaint)API,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07
Android?Jetpack?組件LiveData源碼解析
這篇文章主要為大家介紹了Android?Jetpack?組件LiveData源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03

