Android使用http协议与服务器通信的实例

网上介绍Android上http通信的文章很多,不过大部分只给出了实现代码的片段,一些注意事项和如何设计一个合理的类用来处理所有的http请求以及返回结果,一般都不会提及。因此,自己对此做了些总结,给出了我的一个解决方案。

首先,需要明确一下http通信流程,Android目前提供两种http通信方式,HttpURLConnection和HttpClient,HttpURLConnection多用于发送或接收流式数据,因此比较适合上传/下载文件,HttpClient相对来讲更大更全能,但是速度相对也要慢一点。在此只介绍HttpClient的通信流程:

1.创建HttpClient对象,改对象可以用来多次发送不同的http请求

2.创建HttpPost或HttpGet对象,设置参数,每发送一次http请求,都需要这样一个对象

3.利用HttpClient的execute方法发送请求并等待结果,该方法会一直阻塞当前线程,直到返回结果或抛出异常。

4.针对结果和异常做相应处理

根据上述流程,发现在设计类的时候,有几点需要考虑到:

1.HttpClient对象可以重复使用,因此可以作为类的静态变量

2.HttpPost/HttpGet对象一般无法重复使用(如果你每次请求的参数都差不多,也可以重复使用),因此可以创建一个方法用来初始化,同时设置一些需要上传到服务器的资源

3.目前Android不再支持在UI线程中发起Http请求,实际上也不该这么做,因为这样会阻塞UI线程。因此还需要一个子线程,用来发起Http请求,即执行execute方法

4.不同的请求对应不同的返回结果,对于如何处理返回结果(一般来说都是解析json&更新UI),需要有一定的自由度。

5.最简单的方法是,每次需要发送http请求时,开一个子线程用于发送请求,子线程中接收到结果或抛出异常时,根据情况给UI线程发送message,最后在UI线程的handler的handleMessage方法中做结果解析和UI更新。这么写虽然简单,但是UI线程和Http请求的耦合度很高,而且代码比较散乱、丑陋。

基于上述几点原因,我设计了一个PostRequest类,用于满足我的http通信需求。我只用到了Post请求,如果你需要Get请求,也可以改写成GetRequest

package com.handspeaker.network;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.util.Log;

/**
 *
 * 用于封装&简化http通信
 *
 */
public class PostRequest implements Runnable {

  private static final int NO_SERVER_ERROR=1000;
  //服务器地址
  public static final String URL = "fill your own url";
  //一些请求类型
  public final static String ADD = "/add";
  public final static String UPDATE = "/update";
  public final static String PING = "/ping";
  //一些参数
  private static int connectionTimeout = 60000;
  private static int socketTimeout = 60000;
  //类静态变量
  private static HttpClient httpClient=new DefaultHttpClient();
  private static ExecutorService executorService=Executors.newCachedThreadPool();
  private static Handler handler = new Handler();
  //变量
  private String strResult;
  private HttpPost httpPost;
  private HttpResponse httpResponse;
  private OnReceiveDataListener onReceiveDataListener;
  private int statusCode;

  /**
   * 构造函数,初始化一些可以重复使用的变量
   */
  public PostRequest() {
    strResult = null;
    httpResponse = null;
    httpPost = new HttpPost();
  }

  /**
   * 注册接收数据监听器
   * @param listener
   */
  public void setOnReceiveDataListener(OnReceiveDataListener listener) {
    onReceiveDataListener = listener;
  }

  /**
   * 根据不同的请求类型来初始化httppost
   *
   * @param requestType
   *      请求类型
   * @param nameValuePairs
   *      需要传递的参数
   */
  public void iniRequest(String requestType, JSONObject jsonObject) {
    httpPost.addHeader("Content-Type", "text/json");
    httpPost.addHeader("charset", "UTF-8");

    httpPost.addHeader("Cache-Control", "no-cache");
    HttpParams httpParameters = httpPost.getParams();
    HttpConnectionParams.setConnectionTimeout(httpParameters,
        connectionTimeout);
    HttpConnectionParams.setSoTimeout(httpParameters, socketTimeout);
    httpPost.setParams(httpParameters);
    try {
      httpPost.setURI(new URI(URL + requestType));
      httpPost.setEntity(new StringEntity(jsonObject.toString(),
          HTTP.UTF_8));
    } catch (URISyntaxException e1) {
      e1.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
  }

  /**
   * 新开一个线程发送http请求
   */
  public void execute() {
    executorService.execute(this);
  }

  /**
   * 检测网络状况
   *
   * @return true is available else false
   */
  public static boolean checkNetState(Activity activity) {
    ConnectivityManager connManager = (ConnectivityManager) activity
        .getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connManager.getActiveNetworkInfo() != null) {
      return connManager.getActiveNetworkInfo().isAvailable();
    }
    return false;
  }

  /**
   * 发送http请求的具体执行代码
   */
  @Override
  public void run() {
    httpResponse = null;
    try {
      httpResponse = httpClient.execute(httpPost);
      strResult = EntityUtils.toString(httpResponse.getEntity());
    } catch (ClientProtocolException e1) {
      strResult = null;
      e1.printStackTrace();
    } catch (IOException e1) {
      strResult = null;
      e1.printStackTrace();
    } finally {
      if (httpResponse != null) {
        statusCode = httpResponse.getStatusLine().getStatusCode();
      }
      else
      {
        statusCode=NO_SERVER_ERROR;
      }
      if(onReceiveDataListener!=null)
      {
        //将注册的监听器的onReceiveData方法加入到消息队列中去执行
        handler.post(new Runnable() {
          @Override
          public void run() {
            onReceiveDataListener.onReceiveData(strResult, statusCode);
          }
        });
      }
    }
  }

  /**
   * 用于接收并处理http请求结果的监听器
   *
   */
  public interface OnReceiveDataListener {
    /**
     * the callback function for receiving the result data
     * from post request, and further processing will be done here
     * @param strResult the result in string style.
     * @param StatusCode the status of the post
     */
    public abstract void onReceiveData(String strResult,int StatusCode);
  }

}

代码使用了观察者模式,任何需要接收http请求结果的类,都要实现OnReceiveDataListener接口的抽象方法,同时PostRequest实例调用setOnReceiveDataListener方法,注册该监听器。完整调用步骤如下:

1.创建PostRequest对象,实现onReceiveData接口,编写自己的onReceiveData方法

2.注册监听器

3.调用PostRequest的iniRequest方法,初始化本次request

4.调用PostRequest的execute方法

可能的改进:

1.如果需要多个观察者,可以把只能注册单个监听器改为可以注册多个监听器,维护一个监听器List。

2.如果需求比较简单,并希望调用流程更简洁,iniRequest和execute可以合并

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 浅析Android系统中HTTPS通信的实现

    前言 最近有一个跟HTTPS相关的问题需要解决,因此花时间学习了一下Android平台HTTPS的使用,同时也看了一些HTTPS的原理,这里分享一下学习心得. HTTPS原理 HTTPS(Hyper Text Transfer Protocol Secure),是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的.HTTPS协议是在HTTP协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议.所以,研究HTTPS协议原理,最终就是研

  • Android使用http协议与服务器通信的实例

    网上介绍Android上http通信的文章很多,不过大部分只给出了实现代码的片段,一些注意事项和如何设计一个合理的类用来处理所有的http请求以及返回结果,一般都不会提及.因此,自己对此做了些总结,给出了我的一个解决方案. 首先,需要明确一下http通信流程,Android目前提供两种http通信方式,HttpURLConnection和HttpClient,HttpURLConnection多用于发送或接收流式数据,因此比较适合上传/下载文件,HttpClient相对来讲更大更全能,但是速度相

  • android利用websocket协议与服务器通信

    最近做一个项目,需求中需要服务器主动推送消息到客户端.这样的话一般的http连接就不能使用了.博主问了个朋友,向我推荐websocket协议,特此测试了一下,发现效果很好. android本身没有websocket的库,需要自己下载 ,下载地址. 客户端代码: 界面布局自己写,很简单的两个button package com.example.test; import com.example.test.R; import android.app.Activity; import android.o

  • Android IPC机制ACtivity绑定Service通信代码实例

    Binder通信过程类似于TCP/IP服务连接过程binder四大架构Server(服务器),Client(客户端),ServiceManager(DNS)以及Binder驱动(路由器) 其中Server,Client,ServiceManager运行于用户空间,驱动运行于内核空间.这四个角色的关系和互联网类似:Server是服务器,Client是客户终端,SMgr是域名服务器(DNS),驱动是路由器. book.java package com.example.android_binder_t

  • Android编程之客户端通过socket与服务器通信的方法

    本文实例讲述了Android编程之客户端通过socket与服务器通信的方法.分享给大家供大家参考,具体如下: 下面是一个demo,Android客户端通过socket与服务器通信. 由于Android里面可以完全使用java.io.*包和java.net.*包,那么,实际上,逻辑部分与J2SE没有区别.只是UI代码不一样. Android客户端通过socket与服务器通信分为下面5步: (1)通过IP地址和端口实例化Socket,请求连接服务器: 复制代码 代码如下: socket = new

  • 详解Android 基于TCP和UDP协议的Socket通信

    本来想讲一下基础的网络通信方面的知识点,发现太枯燥乏味了,不过笔试中也经常会问到这方面的问题,所以关于通信方面的知识点,小编会放到面试中去,因为实战中也就面试会用到这方面知识点 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据. 而Socket通信中基于TCP/IP协议的通信则是在双方建立起连接后就可以直接进行数

  • Java利用TCP协议实现客户端与服务器通信(附通信源码)

    进行TCP协议网络程序的编写,关键在于ServerSocket套接字的熟练使用,TCP通信中所有的信息传输都是依托ServerSocket类的输入输出流进行的. 上一篇博客和大家分享了在网络编程中要注意的基础知识,关于IP.TCP.UDP以及端口和套接字的一些概念,想了解的小伙伴可以看我的这篇文章"盘点那些进行网络编程必须要知道的基础知识",那么今天大灰狼就来和大家分享一下如何使用TCP/IP进行网络程序的开发. TCP协议概念 先来了解一下TCP协议的基本概念. 我们知道TCP是可靠

  • Android开发MQTT协议的模型及通信浅析

    目录 前言 什么是MQTT协议 MQTT协议的模型 开发MQTT通信 1. 处理客户端和服务端 (1)服务端开发 (2)客户端开发 2. 客户端开发 Paho的mqtt的BUG 总结 前言 为什么要讲MQTT协议?因为现在越来越多的领域会使用到这个协议,无论是做M2M,还是做Iot,或是想实现推送功能,MQTT都是一个不错的选择. 什么是MQTT协议 MQTT协议又称为消息队列要测传输协议,他是一种基于发布/订阅范式的消息协议,并且它是一种基于TCP/IP协议族的应用层协议. 可以看出的它的特点

  • Android 通过TCP协议上传指定目录文件的方法

    为了方便客户抓取Log,现通过TCP协议连接指定服务器,传输指定内容,定义指定目录,IP,PORT字段接收参数.直接上代码 public static void uploadLog(final String dirPath, final String IP, final int port ) { JSONArray fileList = new JSONArray(); final JSONArray allFiles = getAllFiles(fileList,dirPath); if(al

  • 在Android中使用WebSocket实现消息通信的方法详解

    前言 消息推送功能可以说移动APP不可缺少的功能之一,一般简单的推送我们可以使用第三方推送的SDK,比如极光推送.信鸽推送等,但是对于消息聊天这种及时性有要求的或者三方推送不满足业务需求的,我们就需要使用WebSocket实现消息推送功能. 基本流程 WebSocket是什么,这里就不做介绍了,我们这里使用的开源框架是https://github.com/TakahikoKawasaki/nv-websocket-client 基于开源协议我们封装实现WebSocket的连接.注册.心跳.消息分

  • Android基于Http协议实现文件上传功能的方法

    本文实例讲述了Android基于Http协议实现文件上传功能的方法.分享给大家供大家参考,具体如下: 注意一般使用Http协议上传的文件都比较小,一般是小于2M 这里示例是上传一个小的MP3文件 1.主Activity:MainActivity.java public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private EditText timel

随机推荐