【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="submit"><br/>
    </form>

运行效果

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

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


				
时间: 2024-11-06 10:07:44

【Android实战之旅 006】Android中的HTTP通信的相关文章

【Android自学之旅】 Android开发环境的搭建

搭建参考教程: http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html http://www.cnblogs.com/bjzhanghao/archive/2012/11/14/2769409.html 下载开发工具 Jave SDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html Android

我的Android进阶之旅------&amp;gt;Android中android:windowSoftInputMode的使用方法

面试题:怎样在显示某个Activity时马上弹出软键盘? 答案:在AndroidManifest.xml文件里设置<activity>标签的android:windowSoftInputMode属性能够在显示Activity时马上弹出当前输入法的软键盘(无论是否有获得焦点的空间). 设置为:android:windowSoftInputMode="stateVisible|adjustPan"   代码例如以下: <activity android:name=&quo

我的Android进阶之旅------&amp;gt;android Button上面的英文字符串自己主动大写的问题解决

今天碰到一个关于Button的问题:android Button上面的英文字符串会自己主动变成大写,执行的Android 5.1版本号,例如以下图所看到的: 图1:Button 图2:TextView 这个Button的定义代码例如以下 <Button android:id="@+id/addContacts" android:layout_width="match_parent" android:layout_height="wrap_conten

我的Android进阶之旅------&amp;gt;Android二级ListView列表的实现

实现例如以下图所看到的的二级列表效果 首先是在布局文件里,布局两个ListView,代码例如以下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_he

Android开发之旅:android架构

本篇将站在顶级的高度——架构,来看android.我开篇就说了,这个系列适合0基础的人且我也是从0开始按照这个步骤来 学的,谈架构是不是有点螳臂挡车,自不量力呢?我觉得其实不然,如果一开始就对整个android的架构了然于胸,就不会误入歧途,能够很好地把握全局. 本文的主题如下: 1.架构图直观 2.架构详解3.总结 2.1.Linux Kernel 2.1.Android Runtime 2.3.Libraries 2.4.Application Framework 2.5.Applicati

我的Android进阶之旅------&amp;gt;Android中ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法

开发中经常须要自定义Listview,去继承BaseAdapter,在adapter中依照需求进行编写,问题就出现了,可能会发生点击每个item的时候没有反应,无法获取的焦点. 假设你的自己定义ListViewItem中有Button.ImageButton或者Checkable的子类控件的话,那么默认focus是交给了子控件,而ListView的Item能被选中的基础是它能获取Focus. 所以经常当点击item时变化的是子控件,item本身的点击没有响应. 这时候就能够使用descendan

我的Android进阶之旅------&amp;gt;android中getLocationInWindow 和 getLocationOnScreen的差别

View.getLocationInWindow(int[] location) 一个控件在其父窗体中的坐标位置 View.getLocationOnScreen(int[] location) 一个控件在其整个屏幕上的坐标位置 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center"> getLocationI

我的Android进阶之旅------&amp;gt;Android关于Log的一个简单封装

android.util.Log类,能够方便地用于在编码调试过程中打印日志. 可是在公布后的产品中,假设有太多的日志打印.则会严重地影响性能. 对android.util.Log类做一个简单的封装.当产品要公布的话,将Debug设为false. 代码例如以下. public class LogUtil { /**正式上线時候设为false*/ private final static boolean debug = true; private final static String TAG =

【我的Android进阶之旅】Android调用JNI出错 java.lang.UnsatisfiedLinkError: No implementation found for的解决方法

错误描述 今天使用第三方的so库时候,调用JNI方法时出现了错误.报错如下所示: 11-01 16:39:20.979 4669-4669/com.netease.xtc.cloudmusic E/art: No implementation found for void com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(android.content.Context) (tried Java_com_netease_xt