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

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. 设置连接超时,读取超时的毫秒数,以及server希望得到的一些消息头
    conn.setConnectTimeout(6*1000);
    conn.setReadTimeout(6 * 1000);
  5. 调用getInputStream( )方法获得server返回的输入流,然后输入流进行读取了
    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;
    }
}

代码非常easy,然后是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就能够不用纠结那么多了
另外有些页面可能须要我们提交一些參数,比方账号password:我们仅仅需把相应參数拼接到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下载

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116578.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 锐捷交换机基础配置命令

    锐捷交换机基础配置命令ip地址:ip地址就像你的名字,在你所在的地方管用。mac地址:就像你的身份证,在所有的地方都管用。enable—-进入特权模式config—-进入全局配置模式hostnameruijie2021—-更改设备名称vlan10—-创建vlan10(vlan-虚拟局域网)name123—-给vlan设置名称interfacevlan10—-进入vlan10ipaddress192.168.10.1255.255.255.0—

  • ZigBee协议栈简介

    ZigBee协议栈简介文章目录Zigbee协议栈简介如何理解Zigbee协议栈如何使用Zigbee协议栈Zigbee协议栈简介  Zigbee协议分为2部分:IEEE802.15.4定义了PHY(物理层)和MAC(介质访问层)技术规范。Zigbee联盟定义了NWK(网络层)、APS(应用程序支持层)、APL(应用层)技术规范。  Zigbee协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并给用户提供API,用户可以直接调用。如何理解Zigbee协议栈  TI推出的ZigBee2007协议栈也

  • Java最新下载安装教程

    Java最新下载安装教程一、网络原理OSI与TCP/IP各层的结构与功能,都有哪些协议TCP建立连接的过程,为什么要三次握手?TCP、UDP协议的区别,各自的应用场景打开浏览器,输入URL地址,访问主页的过程HTTP有哪些方法?HTTP和HTTPS有什么区别?二、Java核心技术HashMap底层数据结构是什么,时间复杂度多少?JDK8中对HashMap做了怎样的优化?HashMap和TreeMap什么区别?ConcurrentHashMap的实现原理包装类的

  • U盘 未知USB设备 设定地址失败 由于该设备有问题Windows 已将其停止(代码 43) 终极解决方案(做过系统装机盘而无法解决的必看)

    U盘 未知USB设备 设定地址失败 由于该设备有问题Windows 已将其停止(代码 43) 终极解决方案(做过系统装机盘而无法解决的必看)U盘由于该设备有问题Windows已将其停止(代码43)终极解决方案我们在使用U盘的时候偶尔会碰到下列情况一般是因为传输数据的过程中,死机或未响应直接断点或拔掉设备导致的,U盘再次插上之后出现设定地址失败。无法再次读取设备的数据。解决方案:首先请确认出现该情况不是因为你摔了U盘或接口处产生断裂这种物理损伤导致的!!!首先请确认出现该情况不是因为你摔了U盘或接口处产生断裂这种物理损…

  • 当面试官问你“你期望的薪酬是多少”时,实际上是在问什么?「建议收藏」

    当面试官问你“你期望的薪酬是多少”时,实际上是在问什么?

  • 回溯法之01背包问题

    回溯法之01背包问题一、问题n皇后问题的解空间树是一颗排列树,而01背包问题的解空间树应该是一颗子集树。再简述下该问题:有n件物品和一个容量为c的背包。第i件物品的价值是v[i],重量是w[i]。求解将哪些物品装入背包可使价值总和最大。所谓01背包,表示每一个物品看成一个整体,要么全部装入,要么都不装入。这里n=5,c=10,w={2,2,6,5,4},v={6,3,5,4,6}。01背…

    2022年10月17日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号