• 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下载

  • 相关阅读:
    DRUPAL 关于 $user 用户权限
    Delphi中代替WebBrowser控件的第三方控件
    最新美行地图Z13升级攻略
    Drupal Form问题汇总
    美行四维图新导航地图可以升级了!!
    Redis 主从配置
    MariaDB 双主复制的配置
    MariaDB 主从复制的配置
    在CentOS下利用Python+selenium获取腾讯首页的今日话题。
    利用Simple-RTMP-Server(SRS)来进行直播
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5069536.html
Copyright © 2020-2023  润新知