1. 程式人生 > >Android HTTP請求方式:HttpURLConnection

Android HTTP請求方式:HttpURLConnection

1.HttpURLConnection的介紹

答:一種多用途、輕量極的HTTP客戶端,使用它來進行HTTP操作可以適用於大多數的應用程式。雖然HttpURLConnection的API提供的比較簡單,但是同時這也使得我們可以更加容易地去使用和擴充套件它。繼承至URLConnection,抽象類,無法直接例項化物件。通過呼叫openCollection()方法獲得物件例項,預設是帶gzip壓縮的;

2.HttpURLConnection的使用步驟

使用HttpURLConnection的步驟如下:

  • 建立一個URL物件:URL url = new URL(http://www.baidu.com);
  • 呼叫URL物件的openConnection( )來獲取HttpURLConnection物件例項:HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  • 設定HTTP請求使用的方法:GET或者POST,或者其他請求方式比如:PUTconn.setRequestMethod("GET");
  • 設定連線超時,讀取超時的毫秒數,以及伺服器希望得到的一些訊息頭conn.setConnectTimeout(6*1000);conn.setReadTimeout(6 * 1000);
  • 呼叫getInputStream()方法獲得伺服器返回的輸入流,然後輸入流進行讀取了InputStream in = conn.getInputStream();
  • 最後呼叫disconnect()方法將HTTP連線關掉conn.disconnect();

PS:除了上面這些外,有時我們還可能需要對響應碼進行判斷,比如200:if(conn.getResponseCode() != 200)然後一些處理 還有,可能有時我們並不需要傳遞什麼引數,而是直接去訪問一個頁面,我們可以直接用:final InputStream in = new URL("url").openStream();然後直接讀流,不過這個方法適合於直接訪問頁面的情況,底層實現其實也是return openConnection().getInputStream(),而且我們還不能設定一些請求頭的東東,所以要不要這樣寫,你自己要掂量掂量!

3.HttpURLConnection使用示例

這裡我們主要針對GET和POST請求寫兩個不同的使用示例,我們可以conn.getInputStream()獲取到的是一個流,所以我們需要寫一個類將流轉化為二進位制陣列!工具類如下:

StreamTool.java:

/**
 * Created by Jay on 2015/9/7 0007.
 */publicclassStreamTool{//從流中讀取資料publicstaticbyte[] read(InputStream inStream)throwsException{ByteArrayOutputStream outStream =newByteArrayOutputStream();byte[] buffer =newbyte[1024];int len =0;while((len = inStream.read(buffer))!=-1){
            outStream.write(buffer,0,len);}
        inStream.close();return outStream.toByteArray();}}

接下來就可以開始擼我們的示例了!

1)HttpURLConnection傳送GET請求程式碼示例

執行效果圖

核心部分程式碼

佈局:activity_main.xml

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/txtMenu"android:layout_width="match_parent"android:layout_height="48dp"android:background="#4EA9E9"android:clickable="true"android:gravity="center"android:text="長按我,載入選單"android:textSize="20sp"/><ImageViewandroid:id="@+id/imgPic"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"/><ScrollViewandroid:id="@+id/scroll"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"><TextViewandroid:id="@+id/txtshow"android:layout_width="wrap_content"android:layout_height="wrap_content"/></ScrollView><WebViewandroid:id="@+id/webView"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>

獲取資料類:GetData.java:

/**
 * Created by Jay on 2015/9/7 0007.
 */publicclassGetData{// 定義一個獲取網路圖片資料的方法:publicstaticbyte[] getImage(String path)throwsException{
        URL url =new URL(path);HttpURLConnection conn =(HttpURLConnection) url.openConnection();// 設定連線超時為5秒
        conn.setConnectTimeout(5000);// 設定請求型別為Get型別
        conn.setRequestMethod("GET");// 判斷請求Url是否成功if(conn.getResponseCode()!=200){thrownewRuntimeException("請求url失敗");}InputStream inStream = conn.getInputStream();byte[] bt =StreamTool.read(inStream);
        inStream.close();return bt;}// 獲取網頁的html原始碼publicstaticString getHtml(String path)throwsException{
        URL url =new URL(path);HttpURLConnection conn =(HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestMethod("GET");if(conn.getResponseCode()==200){InputStreamin= conn.getInputStream();byte[] data =StreamTool.read(in);String html =newString(data,"UTF-8");return html;}returnnull;}}

MainActivity.java

publicclassMainActivityextendsAppCompatActivity{privateTextView txtMenu, txtshow;privateImageView imgPic;privateWebView webView;privateScrollView scroll;privateBitmap bitmap;privateString detail ="";privateboolean flag =false;privatefinalstaticString PIC_URL ="http://ww2.sinaimg.cn/large/7a8aed7bgw1evshgr5z3oj20hs0qo0vq.jpg";privatefinalstaticString HTML_URL ="http://www.baidu.com";// 用於重新整理介面privateHandler handler =newHandler(){publicvoid handleMessage(android.os.Message msg){switch(msg.what){case0x001:
                    hideAllWidget();
                    imgPic.setVisibility(View.VISIBLE);
                    imgPic.setImageBitmap(bitmap);Toast.makeText(MainActivity.this,"圖片載入完畢",Toast.LENGTH_SHORT).show();break;case0x002:
                    hideAllWidget();
                    scroll.setVisibility(View.VISIBLE);
                    txtshow.setText(detail);Toast.makeText(MainActivity.this,"HTML程式碼載入完畢",Toast.LENGTH_SHORT).show();break;case0x003:
                    hideAllWidget();
                    webView.setVisibility(View.VISIBLE);
                    webView.loadDataWithBaseURL("", detail,"text/html","UTF-8","");Toast.makeText(MainActivity.this,"網頁載入完畢",Toast.LENGTH_SHORT).show();break;default:break;}};};@Overrideprotectedvoid onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setViews();}privatevoid setViews(){
        txtMenu =(TextView) findViewById(R.id.txtMenu);
        txtshow =(TextView) findViewById(R.id.txtshow);
        imgPic =(ImageView) findViewById(R.id.imgPic);
        webView =(WebView) findViewById(R.id.webView);
        scroll =(ScrollView) findViewById(R.id.scroll);
        registerForContextMenu(txtMenu);}// 定義一個隱藏所有控制元件的方法:privatevoid hideAllWidget(){
        imgPic.setVisibility(View.GONE);
        scroll.setVisibility(View.GONE);
        webView.setVisibility(View.GONE);}@Override// 重寫上下文選單的建立方法publicvoid onCreateContextMenu(ContextMenu menu,View v,ContextMenu.ContextMenuInfo menuInfo){MenuInflater inflator =newMenuInflater(this);
        inflator.inflate(R.menu.menus, menu);super.onCreateContextMenu(menu, v, menuInfo);}// 上下文選單被點選是觸發該方法@Overridepublicboolean onContextItemSelected(MenuItem item){switch(item.getItemId()){case R.id.one:newThread(){publicvoid run(){try{byte[] data =GetData.getImage(PIC_URL);
                            bitmap =BitmapFactory.decodeByteArray(data,0, data.length);}catch(Exception e){
                            e.printStackTrace();}
                        handler.sendEmptyMessage(0x001);};}.start();break;case R.id.two:newThread(){publicvoid run(){try{
                            detail =GetData.getHtml(HTML_URL);}catch(Exception e){
                            e.printStackTrace();}
                        handler.sendEmptyMessage(0x002);};}.start();break;case R.id.three:if(detail.equals("")){Toast.makeText(MainActivity.this,"先請求HTML先嘛~",Toast.LENGTH_SHORT).show();}else{
                    handler.sendEmptyMessage(0x003);}break;}returntrue;}}

最後別忘了加上聯網許可權:

<uses-permissionandroid:name="android.permission.INTERNET"/>

注意事項

用handler的原因就不用講了吧~另外我們載入html程式碼的使用的是webView的loadDataWithBaseURL而非LoadData,如果用LoadData又要去糾結中文亂碼的問題,so…用loadDataWithBaseURL就可以不用糾結那麼多了另外有些頁面可能需要我們提交一些引數,比如賬號密碼:我們只需把對應引數拼接到url尾部即可,比如:http://192.168.191.1:8080/ComentServer/LoginServlet?passwd=123&name=Jack然後服務端getParamater("passwd")這樣就可以獲得相應的引數了,我們請求時這些東西都會看得清清楚楚,所以說GET方式並不安全!另外還有一點要注意的就是Android從4.0開始就不允許在非UI執行緒中進行UI操作!

2)HttpURLConnection傳送POST請求程式碼示例

有GET自然有POST,我們通過openConnection獲取到的HttpURLConnection預設是進行Get請求的,所以我們使用POST提交資料,應提前設定好相關的引數:conn.setRequestMethod("POST");還有:conn.setDoOutput(true);conn.setDoInput(true);設定允許輸入,輸出還有:conn.setUseCaches(false); POST方法不能快取,要手動設定為false,具體實現看程式碼:

執行效果圖:

核心程式碼

PostUtils.java

publicclassPostUtils{publicstaticString LOGIN_URL ="http://172.16.2.54:8080/HttpTest/ServletForPost";publicstaticStringLoginByPost(String number,String passwd){String msg ="";try{HttpURLConnection conn =(HttpURLConnection)new URL(LOGIN_URL).openConnection();//設定請求方式,請求超時資訊
            conn.setRequestMethod("POST");
            conn.setReadTimeout(5000);
            conn.setConnectTimeout(5000);//設定執行輸入,輸出:
            conn.setDoOutput(true);
            conn.setDoInput(true);//Post方式不能快取,需手動設定為false
            conn.setUseCaches(false);//我們請求的資料:String data ="passwd="+URLEncoder.encode(passwd,"UTF-8")+"&number="+URLEncoder.encode(number,"UTF-8");//這裡可以寫一些請求頭的東東...//獲取輸出流OutputStreamout= conn.getOutputStream();out.write(data.getBytes());out.flush();if(conn.getResponseCode()==200){// 獲取響應的輸入流物件  InputStreamis= conn.getInputStream();// 建立位元組輸出流物件  ByteArrayOutputStream message =newByteArrayOutputStream();// 定義讀取的長度  int len =0;// 定義緩衝區  byte buffer[]=newbyte[1024];// 按照緩衝區的大小,迴圈讀取  while((len =is.read(buffer))!=-1){// 根據讀取的長度寫入到os物件中  
                        message.write(buffer,0, len);}// 釋放資源  is.close();  
                    message.close();// 返回字串  
                    msg =newString(message.toByteArray());return msg;}}catch(Exception e){e.printStackTrace();}return msg;}}

PS:因為電腦沒裝MyEclipse,而且時間關係,就不另外寫demo了,用回之前的Eclipse的那個demo!其實從直接看核心程式碼就夠了~程式碼下載:HttpURLConnection例子.zip

4.Cookie問題的處理

說這個之前,首先我們要理解兩個概念:Session和CookieCookie只是Session機制的一種常用形式,我們也可以使用其他方式來作為客戶端的一個唯一標識,這個由伺服器決定,唯一能夠證明一個客戶端標識就好!除了這種方式外,我們還可以使用URL重寫!方法來實現!所以以後別傻傻的跟別人說:Session不就是Cookie!

下面通過一個例子來幫助大家理解這個Cookie:小豬輸入賬號密碼後登陸下學校的教務系統,然後訪問課表資訊成功,然後如果你用的是Chrome,按F12進入開發模式:來到Resources介面可以看到我們的Cookies:

點選後我們可以看到裡面儲存的內容,由名稱;值;cookie所在的域(domain);cookie所在的目錄(path)Asp.net預設為/即根目錄;過期時間;Cookie大小:

我們可以看到請求頭中有一個Cookie的欄位:

恩呢,現在我們把Cookie清掉(或者等幾分鐘),然後再訪問下述連結:

這時候,頁面竟然自動跳回登陸頁面了!當然一些其他的網站可能會彈出一個對話方塊說"登陸超時"之類的東西!

小結下Http請求登陸的一個簡單流程:一般是登陸的時候:伺服器通過Set-Cookie響應頭,返回一個Cookie,瀏覽器預設儲存這個Cookie,後續訪問相關頁面的時候會帶上這個Cookie,通過Cookie請求頭來完成訪問,如果沒Cookie或者Cookie過期,就提示使用者沒登陸,登陸超時,訪問需要登陸之類的資訊!

而我們使用HttpClient和HttpURLConnection其實也就是模擬這一個流程,登陸後拿到cookie拿著它去傳送請求:關鍵程式碼如下:獲得Cookie:conn.getHeaderField("Set-Cookie");請求時帶上Cookie:conn.setRequestProperty("Cookie",cookie);

另外,除了這種設定請求頭的方式外,還可以用另一種折衷的方法:URL重寫:就是在原先請求連結的基礎上,加上一個…&sessionid=xxxxx這樣的引數,然後由伺服器來解析判斷!Get可以這麼寫,而Post寫法如下:

這裡我們用的是JSON字串的形式,接到請求時服務端取出session裡的內容,然後做下查詢即可~

5.使用HttpURLConnection傳送PUT請求

Put請求對於很多朋友來說可能有點陌生,畢竟我們平時接觸的比較多的情況都是GET和POST,一開始小豬也不知道,不過後來才發現和POST其實是差不多的,而且我們只需在POST的基礎上改點東西就可以使用了!而HttpClient也給我們提供了一個HttpPut的API,下面貼下小豬自己專案中寫的請求程式碼:

publicstaticStringLoginByPut(Context mContext,String mobile,String password,intfrom,String devid,String version_name,int remember_me){String resp ="";try{HttpURLConnection conn =(HttpURLConnection)new URL(LOGIN_URL).openConnection();
        conn.setRequestMethod("PUT");
        conn.setReadTimeout(5000);
        conn.setConnectTimeout(5000);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setUseCaches(false);String data ="mobile="+ mobile +"&password="+ password +"&from="+from+"&devid="+"devid"+"&version_name="+"version_name"+"&remember_me="+ remember_me;;// 獲取輸出流:OutputStreamWriter writer =newOutputStreamWriter(conn.getOutputStream());
        writer.write(data);
        writer.flush();
        writer.close();// 獲取相應流物件:InputStreamin= conn.getInputStream();BufferedReader reader =newBufferedReader(newInputStreamReader(in));StringBuilder response =newStringBuilder();String line;while((line = reader.readLine())!=null)
            response.append(line);SPUtils.put(mContext,"session", conn.getHeaderField("Set-Cookie"));// 資源釋放:in.close();// 返回字串Log.e("HEHE", response.toString());return response.toString();}catch(Exception e){
        e.printStackTrace();}return"";}

本節小結:

好的,本節關於HttpUrlConnection的使用介紹就到這裡,另外,HTTP這一小節大部分來自於小豬以前寫的一個小合集Android之Http通訊,如果看過這個系列的可以跳過這節,大部分內容都是一樣的!嗯,就說這麼多,謝謝~


相關推薦

Android HTTP請求方式:HttpURLConnection

1.HttpURLConnection的介紹 答:一種多用途、輕量極的HTTP客戶端,使用它來進行HTTP操作可以適用於大多數的應用程式。雖然HttpURLConnection的API提供的比較簡單,但是同時這也使得我們可以更加容易地去使用和擴充套件它。繼承至URLCo

Android基礎入門教程——7.1.4 Android HTTP請求方式-HttpClient

Android基礎入門教程——7.1.4 Android HTTP請求方式:HttpClient 標籤(空格分隔): Android基礎入門教程 本節引言: 在上一節中我們對HttpURLConnection進行了學習,本節到第二種方式:Ht

AndroidHttp通訊——4.Android HTTP請求方式:HttpClient

本節引言: 上節講了HttpURLConnection,本節就到HttpClient了,Apache給我們提供的HttpClient(簡單的Http客戶端),不過畢竟不是親兒子,HttpClient在API 21版本後就給Google棄用了,而我

AndroidHTTP請求方式

大多數網路連線的Android應用程式都將使用HTTP傳送和接收資料 對於Http協議的工作原理,一句話概括的話,就是客戶端向伺服器發出一條HTTP請求,伺服器收到之後會返回一些資料給客戶端,然後客戶端再對這些資料進行解析和處理就可以了。

Android Studio中http請求方式

import android.os.AsyncTask; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View;

js學習總結----ajax中的http請求方式及同步編程和異步編程

功能 依然 interval 需要 發送請求 console dom 屬於 相關 一、請求方式 var xhr = createXHR(); xhr.open("get","/getList?num=12",true); xhr.open("post","/getList

深入淺出:HTTP請求方式

網頁代碼 協議標準 通信速度 狀態碼 ie瀏覽器 實體 blog blank fff HTTP協議(HyperText Transfer Protocol,超文本傳輸協議),HTTP協議位於應用層,由請求和響應構成。是用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議。在

HTTP請求方式中8種請求方法

副作用 可用 獲取 其他 代理服 實現 mod 擴展 tp服務器 HTTP請求的方法: HTTP/1.1協議中共定義了八種方法(有時也叫“動作”),來表明Request-URL指定的資源不同的操作方式 HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法

常用HTTP請求方式

狀態 獲取 align web服務器 發送 上傳文件 行處理 get請求 itl HTTP請求的方法: HTTP/1.1協議中共定義了八種方法(有時也叫“動作”), 來表明Request-URL指定的資源不同的操作方式 1、OPTIONS 返回服務器針對特定資源

AJAX中的HTTP請求方式

HTTP METHOD HTTP常用的幾種請求方式: 1.GET 2.POST 3.PUT 4.DELETE 5.HEAD 這些請求方式不管是哪一種都可以向伺服器請求獲取資料或者傳遞資料,從本質上無區別,只是在行業內被開發人員約定俗成各自不同的用處,並非是一種標準。 方法分

android http請求訪問介面的封裝

轉自 https://www.cnblogs.com/you411305469/p/5212479.html 裡面介紹了實用的兩種 要特別注意,向php請求資料是表單型別的資料 application/x-www-form-urlencoded import android.os

HTTP請求方式GET和POST的區別詳解

HTTP有兩部分組成:請求與響應,下面分別整理。 一.HTTP請求 1.HTTP請求格式: <request line> <headers> <blank line> [<request-body>] 在HTTP請

Linux下用c語言實現發送http請求 方式可以Get或者Post例程參考

sockaddr select sleep online 創建 線程終止 index -s lse [1].[代碼] Linux下用c語言實現發送http請求 方式可以Get或者Post 跳至 [1] ? 1 2 3 4 5 6 7 8 9 10 11 12 1

Linux下用c語言實現傳送http請求 方式可以Get或者Post例程參考

[1].[程式碼] Linux下用c語言實現傳送http請求 方式可以Get或者Post 跳至 [1] ? 1 2

http請求方式和狀態碼的含義

8種請求方式 1、OPTIONS 返回伺服器針對特定資源所支援的HTTP請求方法,也可以利用向web伺服器傳送‘*’的請求來測試伺服器的功能性 2、HEAD 向伺服器索與GET請求相一致的響應,只不過

Http請求方式和響應 協議的格式

HTTP協議 的請求和響應 一、關於HTTP協議 1.HTTP(hypertext transport protocol),即超文字傳輸協議。 這個協議詳細規定了瀏覽器和全球資訊網伺服器之間互相通訊的規則。 2.客戶端與服務端通訊時傳輸的內容我

Android網路請求操作httpurlconnection和httpclient基本使用

1.        網路請求操作中Get請求和Post請求有什麼區別? 1)        Get是向伺服器發索取資料的一種請求,而Post是向伺服器提交資料的一種請求 2)        Get是獲取資訊,而不是修改資訊,類似資料庫查詢功能一樣,資料不會被修改 3)   

Android Http請求失敗解決方法

1、MainActivity.java 檔案中的onCreate方法改成如下: @SuppressLint("NewApi") @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCrea

Flask路由和HTTP請求方式處理

路由 使用route()裝飾器將函式繫結到URL。 @app.route('/') def index(): return 'Index Page' @app.route('/hello') def hello(): return 'H

Android http請求使用介面回撥

Android中不支援在主執行緒發起http請求資料,我們需要把http請求放到子執行緒中處理。為了保證程式碼的執行順序,可以使用介面回撥的方式拿到請求到的資料並進行處理。 定義回撥介面 public interface OnConnectResult