zoukankan      html  css  js  c++  java
  • 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下载

  • 相关阅读:
    python中的编码问题
    CVPR2018 Tutorial 之 Visual Recognition and Beyond
    hdu 1376 Octal Fractions
    hdu 1329 Hanoi Tower Troubles Again!
    hdu 1309 Loansome Car Buyer
    hdu 1333 Smith Numbers
    hdu 1288 Hat's Tea
    hdu 1284 钱币兑换问题
    hdu 1275 两车追及或相遇问题
    hdu 1270 小希的数表
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5069536.html
Copyright © 2011-2022 走看看