Android应用通常都要和远程服务器进行交互。最简单的方式是使用基于HTTP协议来传输信息。在一些场景里HTTP协议是非常有用的,就像从远程服务器下载一个图像或者上传一些二进制数据到服务器。Android应用程序使用GET或POST请求来发送数据。在这篇文章,我们想要分析怎样用HttpURLConnection来和一个远程服务器通信。
我们包含这3个主要主题:
HttpURLConnection con = (HttpURLConnection) ( new URL(url)).openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); con.connect();
我们在第一行得到HttpURLConnection,而在第二行我们设置了方法同时在最后连接到服务器。
一旦我们打开了连接,我们使用OutputStream在它上面写入东西。
con.getOutputStream().write( ("name=" + name).getBytes());
我们已经知道参数是用键-值对来写入。
最后一步是使用InputStream读取返回。
InputStream is = con.getInputStream(); byte[] b = new byte[1024]; while ( is.read(b) != -1) buffer.append(new String(b)); con.disconnect();现在所有东西都非常简单,但我们要记住一件事情:创建一个HTTP连接比较耗时的操作,有时候可能需要很长时间所以我们不能在主线程里运行它,否则我们会得到一个ANR (Application Not Responding)问题。要解决这个问题,我们可以用一个AsyncTask。
private class SendHttpRequestTask extends AsyncTask<String, Void, String>{ @Override protected String doInBackground(String... params) { String url = params[0]; String name = params[1]; String data = sendHttpRequest(url, name); return data; } @Override protected void onPostExecute(String result) { edtResp.setText(result); item.setActionView(null); } }运行APP我们得到了:
![]() |
![]() |
public byte[] downloadImage(String imgName) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { System.out.println("URL ["+url+"] - Name ["+imgName+"]"); HttpURLConnection con = (HttpURLConnection) ( new URL(url)).openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); con.connect(); con.getOutputStream().write( ("name=" + imgName).getBytes()); InputStream is = con.getInputStream(); byte[] b = new byte[1024]; while ( is.read(b) != -1) baos.write(b); con.disconnect(); } catch(Throwable t) { t.printStackTrace(); } return baos.toByteArray(); }这个方法用下面的方式来调用:
private class SendHttpRequestTask extends AsyncTask<String, Void, byte[]> { @Override protected byte[] doInBackground(String... params) { String url = params[0]; String name = params[1]; HttpClient client = new HttpClient(url); byte[] data = client.downloadImage(name); return data; } @Override protected void onPostExecute(byte[] result) { Bitmap img = BitmapFactory.decodeByteArray(result, 0, result.length); imgView.setImageBitmap(img); item.setActionView(null); } }运行我们的App:
这是处理http连接里最复杂的部分。原生的HttpURLConnection不处理这类型的请求。它发生在一个Android App要上传一些二进制数据到服务器。它也可能是一个app上传一个图片。在这种情况下,请求会更加复杂,因为一个“普通”的请求并不足够。我们要创建一个MultipartRequest。
一个MultipartRequest是由各种不同部分组成的请求,就像参数和二进制数据。我们要怎样去处理这些请求呢?
第一部就是打开一个连接告诉服务器我们想传递一些二进制信息:
public void connectForMultipart() throws Exception { con = (HttpURLConnection) ( new URL(url)).openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); con.connect(); os = con.getOutputStream(); }
在第6行和第7行,我们指定了请求的content-type和另外一个叫boundary的字段。这个字段是一个字符串序列来分割不同部分的。
对于我们要加入的每个部分,我们需要指定它否是一个文本部分就像post参数或者它是一个而文件(二进制数据)。
public void addFormPart(String paramName, String value) throws Exception { writeParamData(paramName, value); } private void writeParamData(String paramName, String value) throws Exception { os.write( (delimiter + boundary + " ").getBytes()); os.write( "Content-Type: text/plain ".getBytes()); os.write( ("Content-Disposition: form-data; name="" + paramName + "" ").getBytes());; os.write( (" " + value + " ").getBytes()); }这里
private String delimiter = "--"; private String boundary = "SwA"+Long.toString(System.currentTimeMillis())+"SwA";加入一个文件我们能够这样使用:
public void addFilePart(String paramName, String fileName, byte[] data) throws Exception { os.write( (delimiter + boundary + " ").getBytes()); os.write( ("Content-Disposition: form-data; name="" + paramName + ""; filename="" + fileName + "" " ).getBytes()); os.write( ("Content-Type: application/octet-stream " ).getBytes()); os.write( ("Content-Transfer-Encoding: binary " ).getBytes()); os.write(" ".getBytes()); os.write(data); os.write(" ".getBytes()); }因此在我们的App里就这样:
private class SendHttpRequestTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { String url = params[0]; String param1 = params[1]; String param2 = params[2]; Bitmap b = BitmapFactory.decodeResource(UploadActivity.this.getResources(), R.drawable.logo); ByteArrayOutputStream baos = new ByteArrayOutputStream(); b.compress(CompressFormat.PNG, 0, baos); try { HttpClient client = new HttpClient(url); client.connectForMultipart(); client.addFormPart("param1", param1); client.addFormPart("param2", param2); client.addFilePart("file", "logo.png", baos.toByteArray()); client.finishMultipart(); String data = client.getResponse(); } catch(Throwable t) { t.printStackTrace(); } return null; } @Override protected void onPostExecute(String data) { item.setActionView(null); } }运行它我们就看到:
![]() |
![]() |
2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务