美文网首页网络
Android 笔记 —— Http 网络探索

Android 笔记 —— Http 网络探索

作者: GinkWang | 来源:发表于2017-05-04 21:14 被阅读51次

Http 请求及相应

请求包结构

请求包

示例:

   POST /meme.php/home/user/login HTTP/1.1
   Host: 114.215.86.90
   Cache-Control: no-cache
   Postman-Token: bd243d6b-da03-902f-0a2c-8e9377f6f6ed
   Content-Type: application/x-www-form-urlencoded
​
   tel=13637829200&password=123456

响应包结构

相应包

示例:

 HTTP/1.1 200 OK
   Date: Sat, 02 Jan 2016 13:20:55 GMT
   Server: Apache/2.4.6 (CentOS) PHP/5.6.14
   X-Powered-By: PHP/5.6.14
   Content-Length: 78
   Keep-Alive: timeout=5, max=100
   Connection: Keep-Alive
   Content-Type: application/json; charset=utf-8
​
   {"status":202,"info":"\u6b64\u7528\u6237\u4e0d\u5b58\u5728\uff01","data":null}

Http 请求方式

  • GET
    请求指定url的数据,请求体为空(例如打开网页)。

  • POST
    请求指定url的数据,同时传递参数(在请求体中)。

  • HEAD
    类似于get请求,只不过返回的响应体为空,用于获取响应头。

  • PUT
    从客户端向服务器传送的数据取代指定的文档的内容。

  • DELETE
    请求服务器删除指定的页面。

  • CONNECT
    HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

  • OPTIONS
    允许客户端查看服务器的性能。

  • TRACE
    回显服务器收到的请求,主要用于测试或诊断。
    ​常用请求方式 GETPOST

GET & POST

  • GET 通常是从服务器获取数据,POST 通常是香服务器传输数据。

  • GET 是把参数数据队列加到表单的 ACTION 属性所指的 URL 中,值和表单内各个字段一一对应,在 URL 中可以看到,实际上就是 URL 拼接方式。POST 是通过 HTTP POST 机制,将表单内各个字段与其内容放置在 HTML HEADER 中一起传送到 ACTION 属性所指向的 URL 中。

  • 服务器通过 Request.QueryString 获取 GET 变量值,通过 Request.Form 获取 POST 提交的值。

  • GET 提交的数据量小,不能大于 1kb。POST 提交的数据量较大,一般被默认为不受限制,但理论上,IIS4 中最大量为 80KB,IIS5 中为 100KB。

  • GET 安全性低,POST 安全性高。

使用 HttpURLConnection 发送 HTTP 请求

以前,Android 上发送 HTTP 请求有两种方式,HttpURLConnection 和 HttpClient。不过由于 HttpClient 存在 API 数量众多,维护困难等缺点,Android 大版本6.0之后,HttpClient 就被完全移除了。现在官方建议使用 HttpURLConnection。

流程
  • 获取 HttpURLConnection 实例
    ​new 一个 URL 对象,并传入要访问的地址,然后调用一下 HttpURLConnection 的 openConnection() 方法即可。
URL lURL = new URL("https://www.baidu.com/");//请求 url
lHttpURLConnection = (HttpURLConnection) lURL.openConnection();
  • 设置 HTTP 请求方法
lHttpURLConnection.setRequestMethod("GET");//请求方法,       HttpURLConnection 默认请求方式即为 GET 请求,所以本句可省略
  • 接下来可自由定制
    如连接超时、读取超时的设置,或服务器希望得到的一些消息头等
lHttpURLConnection.setConnectTimeout(8000);//与服务器建立连接超时设置
lHttpURLConnection.setReadTimeout(8000);//与服务器传递数据的超时设置
  • 然后调用 getInstreamInput() 方法获取服务器返回的输入流
    对返回的输入流进行读取
InputStream lInputStream = lHttpURLConnection.getInputStream();
  • 关闭 HTTP 连接
lHttpURLConnection.disconnect();
示例
  • 布局
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.ginkwang.networktest">
​
   <uses-permission android:name="android.permission.INTERNET"/>
​
   <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">
       <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>
  • 逻辑
public class MainActivity extends AppCompatActivity {
​
   private Button mBtnSendRequest;
   private TextView mTvResponseTxt;
​
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       initView();
   }
​
   private void initView() {
       mBtnSendRequest = (Button) findViewById(R.id.btn_send_request);
       mBtnSendRequest.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               sendRequestWithHttpURLConnection();
           }
       });
​
       mTvResponseTxt = (TextView) findViewById(R.id.tv_response_txt);
   }
​
   private void sendRequestWithHttpURLConnection() {
       //开启线程发起请求
       new Thread(new Runnable() {
           @Override
           public void run() {
               HttpURLConnection lHttpURLConnection = null;
               BufferedReader lBufferedReader = null;
               try {
                   URL lURL = new URL("https://www.baidu.com/");//请求 url
                   lHttpURLConnection = (HttpURLConnection) lURL.openConnection();
                   lHttpURLConnection.setRequestMethod("GET");//请求方法,HttpURLConnection 默认请求方式即为 GET 请求,所以本句可省略
                   lHttpURLConnection.setConnectTimeout(8000);//与服务器建立连接超时设置
                   lHttpURLConnection.setReadTimeout(8000);//与服务器传递数据的超时设置
​
                   InputStream lInputStream = lHttpURLConnection.getInputStream();
                   //读取获取到的输入流
                   lBufferedReader = new BufferedReader(new InputStreamReader(lInputStream));
                   StringBuilder lStringBuilder = new StringBuilder();
                   String line = "";
                   while ((line = lBufferedReader.readLine()) != null) {
                       lStringBuilder.append(line);
                   }
                   showResponse(lStringBuilder.toString());
               } catch (Exception pE) {
                   pE.printStackTrace();
               } finally {
                   if (lBufferedReader != null) {
                       try {
                           lBufferedReader.close();
                       } catch (IOException pE) {
                           pE.printStackTrace();
                       }
                   }
​
                   if (lHttpURLConnection != null) {
                       lHttpURLConnection.disconnect();
                   }
               }
           }
       }).start();
   }
​
   private void showResponse(final String result) {
       runOnUiThread(new Runnable() {
           @Override
           public void run() {
               // 线程切回到主线程,进行 UI 更新操作
               mTvResponseTxt.setText(result);
           }
       });
   }
}
  • 权限声明
<uses-permission android:name="android.permission.INTERNET"/>
  • 效果
效果

HttpURLConnection 参数详解

  • setRequestMethod
    设置请求方法

  • setDoOutPut
    设置是否向 HttpURLConnection 输出,Get 请求用不到 lHttpURLConnection.getOutputStream(),因为参数直接追加在地址后面,因此默认是false。而 Post 请求参数要放在 http 正文内,因此需要设为 true。

  • setDoInPut
    设置是否从 HttpUrlConnection 读入,默认情况下是 true;指示应用程序要从 URL 连接读取数据。

  • setConnectTimeout
    与服务器建立连接超时设置

  • setReadTimeOut
    与服务器传递数据的超时设置

  • setInstanceFollowRedirects
    设置本次连接是否自动重定向

  • setRequestProperty
    设置头信息,如格式等,一般不设置,有默认设置

  • connect
    不必要调用 connect 方法(调用也无妨),实际上只是建立了一个与服务器的 tcp 连接,并没有实际发送 http 请求。无论是 post 还是 get,http请求实际上直到HttpURLConnection 的 getInputStream() 这个函数里面才正式发送出去。

基于 HttpURLConnection 的 HTTP 请求封装

直接上代码

/**
 * 网络请求类
 * Created by Wang-gk on 2017/5/2.
 */
public class NetworkHandler {
​
   private static final String TAG = "NetworkHandler";
   private static final int TIMEOUT = 15000;//超时设置
​
   /**
     * 请求参数格式转换
     * @param pMap 请求参数
     * @return
     */
   private static String prepareParam(Map<String, Object> pMap) {
       StringBuffer lStringBuffer = new StringBuffer();
       if (pMap.isEmpty()) {
           return "";
       } else {
           for (String key : pMap.keySet()) {
               String value = (String) pMap.get(key);
               if (lStringBuffer.length() < 1) {
                   lStringBuffer.append(key).append("=").append(value);
               } else {
                   lStringBuffer.append("&").append(key).append("=").append(value);
               }
           }
       }
       return lStringBuffer.toString();
   }
​
   /**
     * Get 请求
     * @param pUrl 请求地址
     * @param pParamMap 请求参数
     * @param pListener 接口回调
     */
   public static void doGet(String pUrl, Map<String, Object> pParamMap, NetworkCallbackListener pListener) {
       HttpURLConnection lHttpURLConnection = null;
       BufferedReader lBufferedReader = null;
       if (pParamMap != null && pParamMap.size() > 0) {
           pUrl += prepareParam(pParamMap);
       }
       try {
           URL lURL = new URL(pUrl);
           lHttpURLConnection = (HttpURLConnection) lURL.openConnection();//初始化 HttpURLConnection
           lHttpURLConnection.setRequestMethod("GET");//设置请求方法
           lHttpURLConnection.setDoOutput(false);//设置是否向connection输出, get请求用不到 lHttpURLConnection.getOutputStream(),因为参数直接追加在地址后面,因此默认是false
           lHttpURLConnection.setDoInput(true);// 设置是否从 HttpUrlConnection 读入,默认情况下是 true;指示应用程序要从 URL 连接读取数据。
           lHttpURLConnection.setConnectTimeout(TIMEOUT);//与服务器建立连接超时设置
           lHttpURLConnection.setReadTimeout(TIMEOUT);//与服务器传递数据的超时设置
           lHttpURLConnection.setInstanceFollowRedirects(true);//设置本次连接是否自动重定向
           lHttpURLConnection.setRequestProperty("Content-Type","text/html; charset=UTF-8");//设置头信息,如格式等,一般不设置,有默认设置
           lHttpURLConnection.connect();//不必要调用connect方法(调用也无妨),实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
           InputStream lInputStream = lHttpURLConnection.getInputStream();
           //读取获取到的输入流
           lBufferedReader = new BufferedReader(new InputStreamReader(lInputStream));
           StringBuilder lStringBuilder = new StringBuilder();
           String line = "";
           while ((line = lBufferedReader.readLine()) != null) {
               lStringBuilder.append(line);
           }
           Log.i(TAG, "doGet: output <<< " + lStringBuilder.toString());
           if (pListener != null) {
               pListener.onFinish(lStringBuilder.toString());
           }
       } catch (Exception pE) {
           if (pListener != null) {
               pListener.onError(pE);
           }
       } finally {
           if (lHttpURLConnection != null) {
               lHttpURLConnection.disconnect();
           }
​
           if (lBufferedReader != null) {
               try {
                   lBufferedReader.close();
               } catch (IOException pE) {
                   pE.printStackTrace();
               }
           }
       }
   }
​
   /**
     * Post 请求
     * @param pUrl 请求地址
     * @param pParamMap 请求参数
     * @param pListener 接口回调
     */
   public static void doPost(String pUrl, Map<String, Object> pParamMap, NetworkCallbackListener pListener) {
       HttpURLConnection lHttpURLConnection = null;
       BufferedReader lBufferedReader = null;
       try {
           URL lURL = new URL(pUrl);
           lHttpURLConnection = (HttpURLConnection) lURL.openConnection();//初始化 HttpURLConnection
           lHttpURLConnection.setRequestMethod("POST");//设置请求方法
           lHttpURLConnection.setDoOutput(true);//设置是否向connection输出,因为这个是 post 请求,参数要放在 http 正文内,因此需要设为 true
           lHttpURLConnection.setDoInput(true);// 设置是否从 HttpUrlConnection 读入,默认情况下是 true;指示应用程序要从 URL 连接读取数据。
           lHttpURLConnection.setConnectTimeout(TIMEOUT);//与服务器建立连接超时设置
           lHttpURLConnection.setReadTimeout(TIMEOUT);//与服务器传递数据的超时设置
           lHttpURLConnection.setInstanceFollowRedirects(true);//设置本次连接是否自动重定向
           lHttpURLConnection.setRequestProperty("Content-Type","text/html; charset=UTF-8");//设置头信息,如格式等,一般不设置,有默认设置
           lHttpURLConnection.connect();//不必要调用connect方法(调用也无妨),实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
           InputStream lInputStream = lHttpURLConnection.getInputStream();
           //读取获取到的输入流
           lBufferedReader = new BufferedReader(new InputStreamReader(lInputStream));
           StringBuilder lStringBuilder = new StringBuilder();
           String line = "";
           while ((line = lBufferedReader.readLine()) != null) {
               lStringBuilder.append(line);
           }
           Log.i(TAG, "doPost: output <<< " + lStringBuilder.toString());
           if (pListener != null) {
               pListener.onFinish(lStringBuilder.toString());
           }
       } catch (Exception pE) {
           if (pListener != null) {
               pListener.onError(pE);
           }
       } finally {
           if (lHttpURLConnection != null) {
               lHttpURLConnection.disconnect();
           }
​
           if (lBufferedReader != null) {
               try {
                   lBufferedReader.close();
               } catch (IOException pE) {
                   pE.printStackTrace();
               }
           }
       }
   }
}

其中,网络请求的回调操作也封装在内。主要就是交易完成 onFinish() 和 onError() 两个回调方法,在接口回调类 NetworkCallbackListener 中定义

/**
 * 网络处理接口
 * Created by Wang-gk on 2017/5/4.
 */
public interface NetworkCallbackListener {
    void onFinish(String pResponse);
    void onError(Exception pE);
}

参考

相关文章

  • Android 笔记 —— Http 网络探索

    Http 请求及相应 请求包结构 示例: 响应包结构 示例: Http 请求方式 GET请求指定url的数据,请求...

  • 知识点

    1、JNI2、Http网络访问框架3、Android艺术探索的总结4、简历收集和筛选5.设计模式6.读书笔记7、K...

  • Android Http网络开发神兵利器

    Android Http网络开发神兵利器 Android Http网络开发神兵利器 Http协议HTTP简介主要特...

  • Android开发艺术探索 第15章 Android性能优化 读

    正式开始前,推荐一下Android开发艺术探索的其他笔记 Android开发艺术探索 读书笔记目录下面正文开始。 ...

  • Android 网络编程 目录

    Android 网络编程 目录 Android 网络编程1 Http协议Android 网络编程2 Okhttp缓...

  • Android笔记08:Http网络请求

    在Android中进行Http网络请求主要有HttpClient和HttpURLConnection两种方式,由于...

  • IPC笔记

    一、说明 笔记主要是《Android开发艺术探索》的阅读笔记和自己的理解,笔记中部分内容引自《Android...

  • View事件体系笔记

    一、说明 笔记主要是《Android开发艺术探索》的阅读笔记和自己的理解,笔记中部分内容引自《Android...

  • Activity笔记

    一、说明 笔记主要是《Android开发艺术探索》的阅读笔记和自己的理解,笔记中部分内容引自《Android...

  • 常见问题和性能优化

    一、说明 笔记主要是《Android开发艺术探索》的阅读笔记和自己的理解,笔记中部分内容引自《Android...

网友评论

    本文标题:Android 笔记 —— Http 网络探索

    本文链接:https://www.haomeiwen.com/subject/lrbdtxtx.html