转自:http://www.tuicool.com/articles/ARrQny

本文档要做的事情:

1.介绍两种网络访问客户端:HttpClient和HttpURLConnection

1)HttpClient:

2)HttpURLConnection:

2. HttpClient的使用--(三种参数设定形式)

1).参数以NamValuePair封装,然后再进行封装,封装为Entity,通过Entity给Post提供参数。

2).参数用StringBody和FileBody来封装,然后再将所有Body添加到MultipartEntity

3) .前面设置的参数,是服务器端那边需要的;而在进行网络连接的时候,还需要一些描述连接特征的参数---如连接时间长度,是否有cookies等

3.HttpURLConnection的使用

4.HttpClient和HttpURLConnection使用场景

1.介绍两种网络访问客户端:HttpClient和HttpURLConnection

    作用:执行网络访问,给出访问参数,访问地址,就可以进行访问。具体的实现者有:

AbstractHttpClient , AndroidHttpClient , DefaultHttpClient 。

我通常是使用DefaultHttpClient,相对于HttpURLConnection来说,HttpClient使用起来比较简单,因为它封装的东西比较多:HttpPost,封装了Post的访问方式;HttpGet封装了Get的访问方式;HttpEntity封装了返回的数据,HttpResponse封装了网络访问结果。

     对于DefaultHttpClient来说,它只负责执行就行了,它可以执行HttpPost,或者HttpGet;然后返回一个HttpResponse。请求参数是传递给HttpPost或者HttpGet的。

2)HttpURLConnection:

作用:与HttpClient一样的。与HttpClient不同的是,它没有提供那么多封装,比如,对于以Post的方式访问,它是要你自己进行设置的,而不像HttpClient的使用那样,直接new 一个HttpPost。另外,从 Android官方文档 了解到,HttpURLConnection,给你提供了直接操作流的方法,更倾向于在流这个层次来操作数据,那就是更底层些吧。

An URLConnection for HTTP ( RFC 2616 ) used to send and receive data over the web. Data may be of any type and length. This class may be used to send and receive streaming data whose length is not known in advance.

当然,DefaultHttpClient,也可以提供流对象供用户操作。

      使用过程:

Uses of this class follow a pattern:

1 Obtain a new HttpURLConnection by calling URL.openConnection() and casting the result to HttpURLConnection.

2 Prepare the request. The primary property of a request is its URI. Request headers may also include metadata such as credentials, preferred content types, and session cookies.

3 Optionally upload a request body. Instances must be configured withsetDoOutput(true) if they include a request body. Transmit data by writing to the stream returned by getOutputStream() .

4 Read the response. Response headers typically include metadata such as the response body's content type and length, modified dates and session cookies. The response body may be read from the stream returned by getInputStream() . If the response has no body, that method returns an empty stream.

5 Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect() . Disconnecting releases the resources held by a connection so they may be closed or reused.

     从上述使用描述中,可以知道,用户要根据返回的outputStream向服务器端写数据;而读数据的时候,要根据服务器端返回的inputStream,从这个输入流中读取服务器端返回的数据。所以,传递数据,通过返回的输出流;读数据,要通过返回的输入流。这些都是暴露给用户使用。相对于HttpClient,这要底层些。

2.HttpClient的使用--(三种参数设定形式)

设置请求参数--该参数最终是被服务器端接收的:

1).参数以NamValuePair封装,然后再进行封装,封装为Entity,通过Entity给Post提供参数。

如下:

private List  firstRequestParams() {    BasicNameValuePair mSearch = new BasicNameValuePair("search", "葡");    BasicNameValuePair mSort = new BasicNameValuePair("sort", "1");    BasicNameValuePair mGroupId = new BasicNameValuePair("gid", "9");    List    params = new ArrayList     ();    params.add(mSearch);    params.add(mSort);    params.add(mGroupId);    return params;  }public String post(List        params , int httptimeout) {....final DefaultHttpClient httpclient = new DefaultHttpClient();    final HttpPost httppost = new HttpPost(this.requestURL);....  //给Post方式提供参数,参数最终由服务器接收httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));      final HttpResponse httpresponse = httpclient.execute(httppost);      final HttpEntity httpentity = httpresponse.getEntity();      responseCode = httpresponse.getStatusLine().getStatusCode();....//再将返回的Entity,转换为String(当知道服务器返回的是字符串时)  if (httpentity != null) {        result = EntityUtils.toString(httpentity, "UTF-8");      }....}      

上述方式设置的参数,都是键值对(NameValuePair,具体的实现类是BasicNameValuePair)。传递给服务器的参数,都是键值对的形式,所以能传递给服务器的都是一些int,float,或者几个字符大小的String。--------当传递给服务器的参数,数据量不大时,适合使用这种方式。比如,传递,登陆账号,登陆密码;商品ID;种类ID等信息。

2).参数用StringBody和FileBody来封装,然后再将所有Body添加到MultipartEntity

如下:将各个文件的内容,用FileBody封装;然后,每个文件的描述用Map描述,将Map转换为按照JSON格式编排的String字符串,然后用StringBody封装:

最后将所有Body添加到MultipartEntity中:

private MultipartEntity createPart() {    MultipartEntity entity = new MultipartEntity();    ArrayList   > lmap = new ArrayList         >();        File voiceFile = new File(voiceFilePath);    File imageFile = new File(chiefImagePath);    // 先存声音    entity.addPart("goodsInfoList", new FileBody(voiceFile));    Map          map1 = new HashMap           ();    map1.put("type", "3");    map1.put("con", "0");    lmap.add(map1);    entity.addPart("goodsInfoList", new FileBody(voiceFile));    Map              map2 = new HashMap               ();    map2.put("type", "3");    map2.put("con", "1");    lmap.add(map2);    // 图片    entity.addPart("goodsInfoList", new FileBody(imageFile));    Map                  map3 = new HashMap                   ();    map3.put("type", "2");    map3.put("con", "2");    lmap.add(map3);    entity.addPart("goodsInfoList", new FileBody(imageFile));    Map                      map4 = new HashMap                       ();    map4.put("type", "2");    map4.put("con", "3");    lmap.add(map4);    // 文字    Map                          map5 = new HashMap                           ();    map5.put("type", "1");    map5.put("con", "文字内容,文字描述");    lmap.add(map5);        JSONArray jsonArray = null;    try {      jsonArray = (JSONArray) JsonHelper.toJSON(lmap);    } catch (JSONException e) {      // TODO Auto-generated catch block      e.printStackTrace();    }    try {      entity.addPart("pjson", new StringBody(jsonArray.toString(),          Charset.forName("UTF-8")));      Log.i(TAG, "result: " + jsonArray.toString());    } catch (UnsupportedEncodingException e) {      // TODO Auto-generated catch block      e.printStackTrace();    }    return entity;  }                                                                                        

    这种使用Body的方式来添加封装要传递给服务器的信息,与用NamValuePair封装参数的不同是,这种方式主要是用来传递文件给服务器的,当然,如果你也可以讲int,float,String等类型的值用StringBody来封装,然后传递给服务器。其他方面,与1)中的使用时一致的:

public String post(MultipartEntity userDefineEntity) {....final HttpClient httpclient = new DefaultHttpClient();final HttpPost httppost = new HttpPost(this.requestURL);....//与1)中的相同,也是通过setEntity将要传的参数提供给HttpPost对象  httppost.setEntity(userDefineEntity);      final HttpResponse httpresponse = httpclient.execute(httppost);      final HttpEntity httpentity = httpresponse.getEntity();      responseCode = httpresponse.getStatusLine().getStatusCode();.....}

3).前面设置的参数,是服务器端那边需要的;而在进行网络连接的时候,还需要一些描述连接特征的参数---如连接时间长度,是否有cookies等

这类参数,跟应用是无关的,但是它是控制连接的。比如,客户端要向服务器,所要一个图片,那么客户端要提供一个图片ID,这个ID是一个参数,该参数是跟应用有关的;建立的连接,是否使用cookies;建立一个连接能耗费的时间(timeout,也叫超时设置),比如,设置ConnectionTimeOut为5秒,如果过了5秒,连接还没有建立,那么,就停止本次连接的建立。如下:

public static void setConnectionTimeout ( HttpParams params, int timeout)

Added in API level 1

Sets the timeout until a connection is etablished. A value of zero means the timeout is not used. The default value is zero.

Parameters

timeout Timeout in milliseconds.

这些参数的设置,通过HttpConnectionParams来实现。然后,设置好参数后,将参数传递给HttpClient,而不是HttpPost,传递给HttpPost的参数是要发给服务器的,应用相关的。

如下:

.....    private int timeoutConnection = 30000;    private int timeoutSocket = 5000;  private static CookieStore stored_cookie = null;......public String post(List  params , int httptimeout) {.......//设置控制连接特征方面的参数HttpParams httpParameters = new BasicHttpParams();// Set the timeout in milliseconds until a connection is established.        HttpConnectionParams.setConnectionTimeout(httpParameters, httptimeout);// Set the default socket timeout (SO_TIMEOUT) // in milliseconds which is the timeout for waiting for data.        HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);  final DefaultHttpClient httpclient = new DefaultHttpClient();....  try {    //在执行连接前,将本地的cookies信息传递给httpClient      if(stored_cookie!=null)        httpclient.setCookieStore(stored_cookie);      httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));      final HttpResponse httpresponse = httpclient.execute(httppost);      final HttpEntity httpentity = httpresponse.getEntity();      responseCode = httpresponse.getStatusLine().getStatusCode();      if (httpentity != null) {        result = EntityUtils.toString(httpentity, "UTF-8");      }//获取Cookies信息,服务器用Cookie来标识每个向他请求的客户      stored_cookie = httpclient.getCookieStore();.....

3.HttpURLConnection的使用

HttpURLConnection因为比较低层,但是呢,有些时候,我只需要获得一个图片,只需要获得一个输入流,那么,我就会选择使用HttpURLConnection,因为它使用的步骤少。使用HttpClient的话,必须经过以下步骤:HttpClient新建;HttpPost新建;HttpResponse获取信息,HttpEntity封装返回的信息,再转换成相应的信息。

而HttpURLConnection,只需要opneConnection,然后,然后getInputStream()就可以获得服务器返回的信息了。

比如:只要connecte了,然后就可以获得InputStream。在这种情况下,使用HttpURLConnection是方便的。

/**   *  根据一个网络连接(URL)获取bitmap图像   * @param imageUri   * @return   */  public static Bitmap getusericon(URL imageUri) {    // 显示网络上的图片    URL myFileUrl = imageUri;    Bitmap bitmap = null;    try {      HttpURLConnection conn = (HttpURLConnection) myFileUrl          .openConnection();      conn.setDoInput(true);      conn.connect();      InputStream is = conn.getInputStream();      bitmap = BitmapFactory.decodeStream(is);      is.close();    } catch (IOException e) {      e.printStackTrace();    }    return bitmap;  }

4.HttpClient和HttpURLConnection使用场景

HttpClient封装的比较好;HttpURLConnection没什么封装,比较低层,但是,在某些时候,比如,通过连接获取图片或者获取文件,那么这时候,使用HttpURLConnection要直接。当然HttpClient也可以使用,通过HttpEntity来获取输出流,只是此时的步骤相对HttpURLConnection要多。 

     比如,对于获取服务器文件,并将文件保存起来这个事情,在3中只需一个方法;而在使用HttpClient的时候,是需要两个方法的,如下:

首先是获取Entity:/**   * 使用WebService.requestURL的地址,该地址指向一个图片文件或者声音文件   *    * @return --返回一个HttpEntity,包含的是图片数据或语音数据   *    */  private HttpEntity getEntity() {    HttpClient httpclient = new DefaultHttpClient();    HttpPost httppost = new HttpPost(WebService.this.requestURL);    try {      HttpResponse httpresponse = httpclient.execute(httppost);      HttpEntity entity = httpresponse.getEntity();      WebService.this.responseCode = httpresponse.getStatusLine()          .getStatusCode();      return entity;    } catch (ClientProtocolException e) {      // TODO Auto-generated catch block      e.printStackTrace();      Log.e(TAG, "in getEntity(), ClientProtocolException");      return null;    } catch (IOException e) {      // TODO Auto-generated catch block      e.printStackTrace();      Log.e(TAG, "in getEntity(),IOException");      return null;    }  }

然后,是将Entity的数据写到文件系统中,可以直接使用Entity提供的方法:

/**   * 用户给出要存放的路径,用来存放从服务器下载的文件   *    * @param destFilePath   *            --将文件数据存放在该参数所指定的文件中   * @return 成功,则返回true;否则返回false   */  public boolean getFile(String destFilePath) {    try {      File file = createFile(destFilePath);      HttpEntity entity = getEntity();      if (file == null) {        Log.e(TAG, "用户手机SD卡不可用");        return false;      }      if (entity == null) {        Log.e(TAG, "服务器没有返回数据");        return false;      }      OutputStream out = null;      out = new BufferedOutputStream(new FileOutputStream(file));      //将服务器的数据写到文件系统中            entity.writeTo(out);      out.close();      return true;    } catch (DirectoryCreatedException e) {      // TODO Auto-generated catch block      e.printStackTrace();      Log.e(TAG, "创建文件目录:" + destFilePath + ",失败");      return false;    } catch (FileNotFoundException e) {      // TODO Auto-generated catch block      e.printStackTrace();      Log.e(TAG, "文件:" + destFilePath + ",不存在");      return false;    } catch (IOException e) {      // TODO Auto-generated catch block      e.printStackTrace();      Log.e(TAG, "将来自服务器的 entity写到指定文件中,出现错误");      return false;    }  }

更多相关文章

  1. 转Android(安卓)安全攻防(三): SEAndroid(安卓)Zygote执行用户态许
  2. Android(安卓)RotateAnimation动画不能旋转的问题
  3. android 调用系统命令实现关机
  4. Recovery模式的命令行参数
  5. android在学习——Menu背景图片,背景色的设置
  6. Android(安卓)pcm文件播放方法(AudioTrack)
  7. Android(安卓)Bitmap Api总结和使用方法
  8. 如何去除android上a标签产生的边框
  9. Android(安卓)API 中文 (51) —— ZoomButtonsController

随机推荐

  1. android WebView渲染html
  2. [Kotlin Tutorials 14] Kotlin Coroutine
  3. Android 获取系统短信内容
  4. "error: Error retrieving parent for it
  5. Android 获取手机Mac地址,手机名称
  6. mapView中share place
  7. 单选和多选的listview
  8. [置顶] Android 低功耗蓝牙开发
  9. [置顶] Android与H5交互(混合开发)
  10. 实现Android中TextView的跑马灯效果