当前位置: 代码迷 >> Android >> Android之Http通信——3.Android HTTP请求模式:HttpURLConnection
  详细解决方案

Android之Http通信——3.Android HTTP请求模式:HttpURLConnection

热度:353   发布时间:2016-04-28 00:36:44.0
Android之Http通信——3.Android HTTP请求方式:HttpURLConnection

3.Android HTTP请求方式之HttpURLConnection

引言:

好了,前两节我们已经对HTTP协议进行了学习,相信看完前两节的朋友对HTTP协议相比之前
应该更加熟悉吧,好吧,学了要用,相信很多人都知道Android中HTTP的两种最基本的请求方式
他们分别是:HttpURLConnection和HttpClient,当然了解了最基本的两个后,我们实际开发中
可能并不会自己去慢慢写网络请求的代码,毕竟根据不同的web端接口,我们需要组织不同的数据
内容上传,这明显会增加我们的代码量,所以一般我们都会使用第三方的网络框架来请求网络,
常用的有volley,android-async-http,async-http-client,utils,loopj等等,有很多,前面我们也说过
我们会讲解retrofit封装我们的HTTP请求,一些基础的东西还是要会的,面试说不定会问呢,
而且了解底层的东西,看别人的框架的代码也不会一头雾水是吧,嗯,就唠叨这么多,开始本节内容~


两者的区别:

在学习他们两个的具体用法之前,我们先来对比下这两种方式有什么区别:
HttpURLConnection:继承至URLConnection,抽象类,无法直接实例化对象。通过调用openCollection( )方法获得对象实例,默认是带gzip压缩的;
HttpClient则是Apache给我们提供的HTTP访问网络接口,同样也是无法直接创建实例的,而是通过
new DefaultHttpClient( )获得对象实例,默认不带gzip~
另外他们请求connection都是keep alive,而默认的User-Agent不同
前者是:Dalvik/16.0(Linux;U;Android 4.2.0;Lenovo S898T/4.6.13)
后者是:Apach-Http/UNAVAILABLE(java 1.4)
另外,Android API 22版本后HttpClient就被无情的抛弃了~


HttpURLConnection的使用

①使用步骤:

  1. 创建一个URL对象:
    URL url = new URL(http://www.baidu.com);
  2. 调用URL对象的openConnection( )来获取HttpURLConnection对象实例:
    HttpURLConnection conn = (HttpURLConnection) url.openConnection( );
  3. 设置HTTP请求使用的方法:GET或者POST
    conn.setRequestMethod(“GET”);
  4. 设置连接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头
    conn.setConnectTimeout(6*1000);
    conn.setReadTimeout(6 * 1000);
  5. 调用getInputStream( )方法获得服务器返回的输入流,然后输入流进行读取了
    InputStream in = conn.getInputStream( );
  6. 最后调用disconnect( )方法将HTTP连接关掉
    conn.disconnect( );

另外除了上面这些外,有时我们还可能需要对响应码进行判断,比如200:
if(conn.getResponseCode( ) != 200)然后一些处理
还有,可能有时我们并不需要传递什么参数,而是直接去访问一个页面,我们可以直接用:
final InputStream in = new URL(“url”).openStream();
然后直接读流,不过这个方法适合于直接访问页面的情况,底层实现其实也是return openConnection().getInputStream(),而且我们还不能设置一些请求头的东东,用不用可以自己掂量掂量


②代码实例:

在开始每个具体的例子编写前,我们先来编写一个工具类,用于将流转化为二进制数组:

StreamTool.java:

package com.jay.example.utils;import java.io.ByteArrayOutputStream;import java.io.InputStream;public class StreamTool {    //从流中读取数据    public static byte[] read(InputStream inStream) throws Exception{        ByteArrayOutputStream outStream = new ByteArrayOutputStream();        byte[] buffer = new byte[1024];        int len = 0;        while((len = inStream.read(buffer)) != -1)        {            outStream.write(buffer,0,len);        }        inStream.close();        return outStream.toByteArray();    }}

1.发送GET请求:

好了,那么接下来我们就来写个简单的例子来熟悉HttpURLConnection的用法吧:
先看运行的效果,然后我们再看实现代码,运行截图:

运行截图

恩呢,看完运行效果,我们来开始写代码,我们程序的功能是:
定义了一个上下文菜单,通过点击不同的菜单项,做一些不同的网络请求,
加载图片,加载网页代码,根据代码加载网页到WebView中
因为篇幅原因,直接贴核心代码,要仔细研究的可以自行下载代码参考

处理网络请求的类:GetData.java:

package com.jay.example.httpurlconnectiondemo.util;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;public class GetData {    // 定义一个获取网络图片数据的方法:    public static byte[] getImage(String path) throws Exception {        URL url = new URL(path);        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        // 设置连接超时为5秒        conn.setConnectTimeout(5000);        // 设置请求类型为Get类型        conn.setRequestMethod("GET");        // 判断请求Url是否成功        if (conn.getResponseCode() != 200) {            throw new RuntimeException("请求url失败");        }        InputStream inStream = conn.getInputStream();        byte[] bt = StreamTool.read(inStream);        inStream.close();        return bt;    }    // 获取网页的html源代码    public static String getHtml(String path) throws Exception {        URL url = new URL(path);        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        conn.setConnectTimeout(5000);        conn.setRequestMethod("GET");        if (conn.getResponseCode() == 200) {            InputStream in = conn.getInputStream();            byte[] data = StreamTool.read(in);            String html = new String(data, "UTF-8");            return html;        }        return null;    }}

代码很简单,然后是MainActivity.java:

package com.jay.example.httpurlconnectiondemo;import com.jay.example.httpurlconnectiondemo.util.GetData;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.os.Handler;import android.view.ContextMenu;import android.view.ContextMenu.ContextMenuInfo;import android.view.MenuInflater;import android.view.MenuItem;import android.view.View;import android.view.Window;import android.webkit.WebView;import android.widget.ImageView;import android.widget.ScrollView;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity {    private TextView txtMenu, txtshow;    private ImageView imgPic;    private WebView webView;    private ScrollView scroll;    private Bitmap bitmap;    private String detail="";    private boolean flag = false;    private final static String PIC_URL = "http://d.hiphotos.baidu.com/image/pic/item/b03533fa828ba61e0bd9f7ef4534970a304e593e.jpg";    private final static String HTML_URL = "http://www.baidu.com";    // 用于刷新界面    private Handler handler = new Handler() {        public void handleMessage(android.os.Message msg) {            switch (msg.what) {            case 0x001:                hideAllWidget();                imgPic.setVisibility(View.VISIBLE);                imgPic.setImageBitmap(bitmap);                Toast.makeText(MainActivity.this, "图片加载完毕", Toast.LENGTH_SHORT).show();                break;            case 0x002:                hideAllWidget();                scroll.setVisibility(View.VISIBLE);                txtshow.setText(detail);                Toast.makeText(MainActivity.this, "HTML代码加载完毕", Toast.LENGTH_SHORT).show();                break;            case 0x003:                hideAllWidget();                webView.setVisibility(View.VISIBLE);                webView.loadDataWithBaseURL("",detail, "text/html","UTF-8","");                Toast.makeText(MainActivity.this, "网页加载完毕", Toast.LENGTH_SHORT).show();                break;            default:                break;            }        };    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_main);        initView();        setView();    }    private void initView() {        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);    }    private void setView() {        registerForContextMenu(txtMenu);//      webView.getSettings().setDefaultTextEncodingName("UTF-8");    }    // 定义一个隐藏所有控件的方法:    private void hideAllWidget() {        imgPic.setVisibility(View.GONE);        scroll.setVisibility(View.GONE);        webView.setVisibility(View.GONE);    }    @Override    // 重写上下文菜单的创建方法    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {        MenuInflater inflator = new MenuInflater(this);        inflator.inflate(R.menu.menus, menu);        super.onCreateContextMenu(menu, v, menuInfo);    }    // 上下文菜单被点击是触发该方法    @Override    public boolean onContextItemSelected(MenuItem item) {        switch (item.getItemId()) {        case R.id.one:            new Thread() {                public void 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:            new Thread() {                public void 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;        }        return true;    }}

注意事项:

用handler的原因就不用讲了吧~
另外我们加载html代码的使用的是webView的loadDataWithBaseURL而非LoadData,如果用LoadData又要去纠结中文乱码的问题,so…用loadDataWithBaseURL就可以不用纠结那么多了
另外有些页面可能需要我们提交一些参数,比如账号密码:我们只需把对应参数拼接到url尾部即可,比如:
http://192.168.191.1:8080/ComentServer/LoginServlet?passwd=123&name=Jack
然后服务端getParamater(“passwd”)这样就可以获得相应的参数了,我们请求时这些东西都会看得清清楚楚,所以GET方式并不安全


2.发送Post请求

有GET自然有POST,我们通过openConnection获取到的HttpURLConnection默认是进行Get请求的,
所以我们使用POST提交数据,应提前设置好相关的参数:conn.setRequestMethod(“POST”);
还有:conn.setDoOutput(true);conn.setDoInput(true);设置允许输入,输出
还有:conn.setUseCaches(false); POST方法不能缓存,要手动设置为false,具体实现看代码:
核心代码:

PostUtils.java

package com.jay.example.httpurlconnectiondemo.util;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLEncoder;public class PostUtils {    public static String LOGIN_URL = "http://172.16.2.54:8080/HttpTest/ServletForPost";    public static String LoginByPost(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");            //这里可以写一些请求头的东东...            //获取输出流            OutputStream out = conn.getOutputStream();            out.write(data.getBytes());            out.flush();             if (conn.getResponseCode() == 200) {                      // 获取响应的输入流对象                      InputStream is = conn.getInputStream();                      // 创建字节输出流对象                      ByteArrayOutputStream message = new ByteArrayOutputStream();                      // 定义读取的长度                      int len = 0;                      // 定义缓冲区                      byte buffer[] = new byte[1024];                      // 按照缓冲区的大小,循环读取                      while ((len = is.read(buffer)) != -1) {                          // 根据读取的长度写入到os对象中                          message.write(buffer, 0, len);                      }                      // 释放资源                      is.close();                      message.close();                      // 返回字符串                      msg = new String(message.toByteArray());                      return msg;             }        }catch(Exception e){e.printStackTrace();}        return msg;    }}

运行效果图:
HttpURLConnection POST请求


总结:

好的,本节关于HttpURLConnection的内容就到这里,主要介绍了两种不同的请求方式的实现,GET和POST,代码是比较简单的,就多多解释了~另外,还有一些复杂的东西,以后有机会再深究…
下节我们来学习的是Apache为我峨嵋你提供的HttpClient,操作会更加简单,敬请期待~

本节代码下载:

Demo下载

  相关解决方案