Android Http 网络探索

一、Http 请求及相应

1.1 请求包结构

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

1.2 响应包结构

Http 响应包结构

示例:

 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 请求方式

2.1 GET

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

2.2 POST

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

2.3 HEAD

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

2.4 PUT

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

2.5 DELETE

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

2.6 CONNECT

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

2.7 OPTIONS

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

2.8 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。

4.1 流程

4.1.1 获取 HttpURLConnection 实例

new 一个 URL 对象,并传入要访问的地址,然后调用一下 HttpURLConnection 的 openConnection() 方法即可。

URL lURL = new URL("https://www.baidu.com/");//请求 url
lHttpURLConnection = (HttpURLConnection) lURL.openConnection();

4.1.2 设置 HTTP 请求方法

lHttpURLConnection.setRequestMethod("GET");//请求方法,           HttpURLConnection 默认请求方式即为 GET 请求,所以本句可省略

4.1.3 接下来可自由定制

如连接超时、读取超时的设置,或服务器希望得到的一些消息头等

lHttpURLConnection.setConnectTimeout(8000);//与服务器建立连接超时设置
lHttpURLConnection.setReadTimeout(8000);//与服务器传递数据的超时设置

4.1.4 读取返回的输入流

然后调用 getInstreamInput() 方法获取服务器返回的输入流
对返回的输入流进行读取

InputStream lInputStream = lHttpURLConnection.getInputStream();

4.1.5 关闭 HTTP 连接

lHttpURLConnection.disconnect();

4.2 示例

4.2.1 布局

<?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>

4.2.2 代码

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);
            }
        });
    }
}

4.2.3 权限声明

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

4.2.4 效果

Http 请求

4.3 HttpURLConnection 参数详解

4.3.1 setRequestMethod

设置请求方法

4.3.2 setDoOutPut

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

4.3.3 setDoInPut

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

4.3.4 setConnectTimeout

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

4.3.5 setReadTimeOut

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

4.3.6 setInstanceFollowRedirects

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

4.3.7 setRequestProperty

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

4.3.8 connect

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

4.4 基于 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);
}

五、参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值