首页 > 代码库 > 【Android实战之旅 006】Android中的HTTP通信

【Android实战之旅 006】Android中的HTTP通信

对于http协议我想很多朋友并不陌生,一次HTTP操作称为一个事务。http中需要掌握的基础知识包括:URL,http三次握手,http请求头信息,http请求的方式,http响应码信息,http协议的特点,TCP/IP四层协议,OSI七层协议,以及http1.0和http1.1区别。这里需要注意的http无连接:限制每一次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接。http无状态:协议对于事务处理没有记忆能力,缺少状态意味着如果后续处理需要前面的信息,则它必须重传。基础知识可以参考:http://blog.csdn.net/davebobo/article/details/52728841

一、HttpURLConnection的介绍及使用

案例一:http访问百度,WebView展示内容

新建http_01项目,首先我们需要进行网络操作,在AndroidManifest.xml中添加permission权限

<uses-permission android:name="android.permission.INTERNET"/>
activity_main.xml中添加WebView组件

 <WebView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/webView"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true" />

由于网络操作是一个耗时操作,我们在线程中执行,创建VisitWeb类继承Thread重写run方法处理网络耗时操作。

package com.davebobo.http_01;

import android.media.tv.TvView;
import android.os.Handler;
import android.webkit.WebView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by DaveBobo on 2016/10/9.
 */
public class VisitWeb extends Thread{

    private  String url;
    private WebView webView;
    private Handler handler;

    public VisitWeb(String url, WebView webView, Handler handler){
        this.url = url;
        this.webView = webView;
        this.handler = handler;
    }

    @Override
    public void run() {
        super.run();
        try {
            URL httpUrl = new URL(url);
            try {
                HttpURLConnection conn = (HttpURLConnection)httpUrl.openConnection();
                conn.setReadTimeout(5000);//设置超时等待
                conn.setRequestMethod("GET");

               final StringBuffer sb = new StringBuffer();//缓存
                //通过网址回传网页流数据
                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String str;
                while ((str = reader.readLine())!=null){
                    sb.append(str);
                }

                handler.post(new Runnable(){
                    @Override
                    public void run() {
                        webView.loadData(sb.toString(),"text/html;charset=utf-8",null);
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}
在MainActivity中查找WebView创建VisitWeb对象调用它的start()方法。

package com.davebobo.http_01;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private Handler handler = new Handler();
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.webView);
        imageView = (ImageView) findViewById(R.id.imageView);
        new VisitWeb("https://www.baidu.com/",webView,handler).start();
        //new DownImage("http://avatar.csdn.net/3/B/3/1_davebobo.jpg",imageView,handler).start();
    }
}
运行模拟器查看效果

技术分享

创建URL对象,通过HttpURLConnection设置请求的方式,得到读入流放到缓存区中,通过webView加载本地的页面信息。

案例二:通过网络请求下载图片到本地

在activity_main.xml中将WebView设置为隐藏,添加 ImageView

<WebView
        android:visibility="gone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/webView"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true" />
    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:id="@+id/imageView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
创建DownImage继承自Thread

package com.davebobo.http_01;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.widget.ImageView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by DaveBobo on 2016/10/9.
 */
public class DownImage extends Thread{

    private  String url;
    private ImageView imageView;
    private Handler handler;

    public DownImage(String url, ImageView imageView, Handler handler){
        this.url = url;
        this.imageView = imageView;
        this.handler = handler;
    }

    @Override
    public void run() {
        super.run();
        try {
            URL httpUrl = new URL(url);
            try {
                HttpURLConnection conn = (HttpURLConnection)httpUrl.openConnection();
                conn.setReadTimeout(5000);
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                InputStream in = conn.getInputStream();
                FileOutputStream out = null;
                File downloadFile = null;

                String fileName = String.valueOf(System.currentTimeMillis());

                //判断SD卡是否存在
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
                    File parent = Environment.getExternalStorageDirectory();//获取SD目录
                    downloadFile = new File(parent,fileName);
                    out = new FileOutputStream(downloadFile);
                }

                byte[] b = new byte[2*1024];
                int len;
                if (out!=null){
                   while ((len = in.read(b))!=-1){
                       out.write(b,0,len);
                   }
                }

                final Bitmap bitmap = BitmapFactory.decodeFile(downloadFile.getAbsolutePath());

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        imageView.setImageBitmap(bitmap);
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}
在MainActivity中初始化ImageView组件并调用start()方法。

package com.davebobo.http_01;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private Handler handler = new Handler();
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.webView);
        imageView = (ImageView) findViewById(R.id.imageView);
        //new VisitWeb("https://www.baidu.com/",webView,handler).start();
        new DownImage("http://avatar.csdn.net/3/B/3/1_davebobo.jpg",imageView,handler).start();
    }
}

运行效果

技术分享

二、通过HttpURLConnection传递post,get参数及乱码处理

1.服务器端

首先我们使用myeclipse创建j2ee WEB项目,项目名称为web

技术分享

 新建MyServlet的servlet程序,重写doGet和doPost方法,为了简单重写一个方法即可。

package com.davebobo.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet extends HttpServlet {

    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doPost(request, response);
    }

    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        PrintWriter out = response.getWriter();
        out.println("name="+name+" age="+age);
        
        System.out.println("name="+name);
        System.out.println("age="+age);
    
    }

}
在index.jsp中添加form表单通过action访问servlet

    <form action="servlet/MyServlet" method="get">
    	name:<input type="text" name="name"><br/>
    	age:<input type="text" name="age"><br/>
    	submit:<input type="submit" value=http://www.mamicode.com/"submit">
>运行效果

技术分享




如果我们此时在后台输入中文,后台会出现什么现象呢?

技术分享技术分享

这是因为index.jsp设置的pageEncoding="ISO-8859-1",提交给后台MyServlet这里需要做转码操作,










【Android实战之旅 006】Android中的HTTP通信