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的内容就到这里,主要介绍了两种不同的请求方式的实现,GET和POST,代码是比较简单的,就多多解释了~另外,还有一些复杂的东西,以后有机会再深究…

下节我们来学习的是Apache为我峨嵋你提供的HttpClient,操作会更加简单,敬请期待~

本节代码下载:

Demo下载

时间: 2024-10-07 06:41:48

Android之Http通信——3.Android HTTP请求方式:HttpURLConnection的相关文章

Android之Http通信——4.Android HTTP请求方式:HttpClient

本节引言: 上节讲了HttpURLConnection,本节就到HttpClient了,Apache给我们提供的HttpClient(简单的Http客户端), 不过毕竟不是亲儿子,HttpClient在API 21版本后就给Google弃用了,而我们实际开发中,很多页面都不是通过 一个简单的URL就可以访问的,可能需要登陆或者相关权限才可以访问,这就涉及到了Session,Cookie等的问题了: 当然我们可以用HttpURLConnection来实现,但是有点麻烦,而用HttpClient可以

android线程间通信的四种实现方式

通过Handler机制. private void one() { handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case 123: tv.setText(""+msg.obj); break; } } }; new Thread(){ @Override public void run() {

Android之Http通信——2.详解Http的消息头与响应头

Android之Http通信--2.详解Http的消息头 --转载请注明出处:coder-pig,请勿用于商业用途~ 本节引言: 在上一节中我们对HTTP的一些概念性的东西进行了了解:什么是HTTP协议,1.0版本与1.1版本的区别, SYN和ACK,TCP/IP三次握手,HTTP操作流程,几种不同的请求方式,HTTP的状态吗, 以及HTTP协议的特点,最后还了解了下OSI七层协议与TCP四层模型,相信大家对HTTP已经有了 简单的了解,本节我们来扣HTTP的消息头以及响应头,好了,开始本节内容

Android简单Socket通信demo

一.Android Socket 通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信

Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)

ZERO.前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当,还望指教. 一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是s

Android之Http通信——1.初识Http协议

Android之Http通信--1.初识Http协议 引言: 今天是六一儿童节,先在这里给各位超龄儿童说声节日快乐哈~( ╯□╰ ),小猪也象征性地给群里的小朋友们派了红包-嗯,忙碌的五月最终过去了,做毕设,写论文,拍毕业照,答辩,辞职.各种各样的事,也算忙完了,好吧.小猪如今又在一家新的公司上班了.第三间公司了.你们肯定会认为小猪三心二意是吧,毕竟才差点儿相同毕业就换了那么多家公司,然后可能问我."小猪你什么时候跳第四间公司",哈哈,应该不会了哈,怎么说呢,事实上我还是非常专一的,毕

Android学习笔记之HttpClient实现Http请求....

PS:最近光忙着考试了....破组成原理都看吐了....搞的什么也不想干...写篇博客爽爽吧....貌似明天就考试了...sad... 学习笔记: 1.如何实现Http请求来实现通信.... 2.解决Android 2.3 版本以后无法使用Http请求问题....   这里我使用HttpClient来开发Http程序来完成简单的网络通信....其实使用HttpUrlConnection也可以实现,不过HttpClient可以完成HttpUrlConnection的所有功能,并且还自己增加了其他的

Android—Camera Framework C/S架构服务请求

在前一篇文章Camera Client/Server的binder IPC机制中阐述了Android进程间通信binder IPC机制基础,Android Camera基于这个基础设计了Camera Framework Client/Server架构,文中给出了其类图设计.本文从Android 4.4 版本源码入手,分析Camera App向Camera Service请求服务与返回的过程.服务请求的过程从上到下依次要经过三个大的过程:1. Camera App调用Framework Camer

基于android的Socket通信

一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信.通过建立sock