昨天我们只对Android接收网络数据进行了简单介绍,今天我们完成了Android数据存储网络部分的所有内容。在此我将对这非常重要的内容进行总结。



本篇日志是对Android与WEB应用服务之间进行数据交互的总结,下篇日志是一个经典而又让人十分好奇的Android多线程断点下载应用的总结。下面我们开始Android与网络数据的交互。



一、创建WEB应用服务

使用eclipse3.5创建一个动态WEB应用,使用Struts1处理用户请求。我们此应用添加一个DispatchAction,并为它添加四个方法创建用于处理Android以各种方式提交的请求。



1.创建动态WEB工程

Project name:AndroidWebServer

Target runtime:Apache Tomcat v6.0

Dynamic web module version:2.5

Configuration:Default Configuration for Apache Tomcat v6.0



2.添加DispatchAction

package com.changcheng.web.struts.actions;



import java.io.File;

import java.io.FileOutputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.actions.DispatchAction;

import com.changcheng.web.struts.forms.DataForm;



public class AndroidWebServer extends DispatchAction {



// Andoird以Get方式发送的请求

public ActionForward sendDataByGet(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response)

throws Exception {

String name = request.getParameter("name");

request.setAttribute("message", "Hello " + name);

return mapping.findForward("success");

}



// Andoird以Post方式发送的请求

public ActionForward sendDataByPost(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response)

throws Exception {

String name = request.getParameter("name");

request.setAttribute("message", "Hello " + name);

return mapping.findForward("success");

}



// Andoird以表单方式发送的请求

public ActionForward sendDataByForm(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response)

throws Exception {

DataForm formbean = (DataForm) form;

System.out.println("StrData:" + formbean.getStrData());

// 获取上传的文件

if (formbean.getFileData() != null

&& formbean.getFileData().getFileSize() > 0) {

// 设置保存目录

File dir = new File(request.getSession().getServletContext()

.getRealPath("/images"));

if (!dir.exists())

dir.mkdirs();

// 保存文件

FileOutputStream outStream = new FileOutputStream(new File(dir,

formbean.getFileData().getFileName()));

outStream.write(formbean.getFileData().getFileData());// 保存文件

outStream.close();

}

return null;

}

}



3.向web.xml添加Struts1的ActionServlet

<servlet>

<servlet-name>struts</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/struts-config.xml</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>struts</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>



4.struts-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts-config PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"

"http://struts.apache.org/dtds/struts-config_1_3.dtd">



<struts-config>

<form-beans>

<form-bean name="dataForm" type="com.changcheng.web.struts.forms.DataForm" />

</form-beans>

<action-mappings>

<action path="/server"

type="com.changcheng.web.struts.actions.AndroidWebServer" name="dataForm"

scope="request" parameter="method">

<forward name="success" path="/WEB-INF/pages/success.jsp"/>

</action>

</action-mappings>

</struts-config>





二、创建Android应用

1.创建Android工程

Project name:AndroidWebClient

BuildTarget:Android2.1

Application name:AndroidWEB应用客户端

Package name:com.changcheng.web.client

Create Activity:AndroidWebClient

Min SDK Version:7



2.AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.changcheng.web.client" android:versionCode="1"

android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">

<!-- 单元测试 -->

<uses-library android:name="android.test.runner" />

<activity android:name=".AndroidWebClient" android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>



</application>

<uses-sdk android:minSdkVersion="7" />

<!-- 访问internet权限 -->

<uses-permission android:name="android.permission.INTERNET" />

<!-- 在SDCard中创建与删除文件权限 -->

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

<!-- 往SDCard写入数据权限 -->

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- 单元测试 -->

<instrumentation android:name="android.test.InstrumentationTestRunner"

android:targetPackage="com.changcheng.web.client" android:label="Tests for My App" />

</manifest>

Android应用要访问Internet需要添加权限。



3.ClientService类

package com.changcheng.web.client.service;



import java.io.ByteArrayOutputStream;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.HashMap;

import java.util.Map;

import android.os.Environment;

import android.util.Log;



public class ClientService {



private static final String TAG = "ClientService";



// 以get方式发送请求

public static void sendDataToServerByGet() throws Exception {

// 主机地址不可以设置为localhost或127.0.0.1,必须是本机或其他机器所在Internet网或局域网地址。

String path = "http://192.168.0.2:8080/AndroidWebServer/server.do?"

+ "method=sendDataByGet&name=changcheng";

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(6 * 1000);

// 请求成功

if (conn.getResponseCode() == 200) {

// 获取服务器返回的数据

byte[] data = readStream(conn.getInputStream());

Log.i(TAG, new String(data, "UTF-8"));

}

}



// 以Post方式发送请求,面向HTTP协议编程

public static void sendDataTOserverByPost() throws Exception {

String path = "http://192.168.0.2:8080/AndroidWebServer/server.do";

String params = "method=sendDataByPost&name=tingting";// 请求参数

byte[] data = params.getBytes();

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(6 * 1000);

conn.setDoOutput(true);// 发送POST请求必须设置允许输出

conn.setUseCaches(false);// 不使用Cache

conn.setRequestMethod("POST");

conn.setRequestProperty("Connection", "Keep-Alive");// 维持长连接

conn.setRequestProperty("Charset", "UTF-8");

conn.setRequestProperty("Content-Length", String.valueOf(data.length));

conn.setRequestProperty("Content-Type",

"application/x-www-form-urlencoded");

DataOutputStream outStream = new DataOutputStream(conn

.getOutputStream());

outStream.write(data);// 以内容实体方式发送请求参数

outStream.flush();

outStream.close();

// 请求成功

if (conn.getResponseCode() == 200) {

// 获取服务器返回的数据

byte[] html = readStream(conn.getInputStream());

Log.i(TAG, new String(html, "UTF-8"));

}

}



// 以表单方式发送请求

public static void sendDataToServerByForm() throws Exception {

Map<String, String> params = new HashMap<String, String>();

params.put("method", "sendDataByForm");

params.put("strData", "字符串数据");

// 获取SDCard中的good.jpg

File file = new File(Environment.getExternalStorageDirectory(),

"app_Goog_Android_w.png");

FormFile fileData = new FormFile("app_Goog_Android_w.png", new FileInputStream(file),

"fileData", "application/octet-stream");

HttpRequester.post(

"http://192.168.0.2:8080/AndroidWebServer/server.do", params,

fileData);

}



// 获取输入流数据

private static byte[] readStream(InputStream inStream) throws Exception {

byte[] buffer = new byte[1024];

int len = -1;

ByteArrayOutputStream outStream = new ByteArrayOutputStream();

while ((len = inStream.read(buffer)) != -1) {

outStream.write(buffer, 0, len);

}

byte[] data = outStream.toByteArray();

outStream.close();

inStream.close();

return data;

}

}

其中使用到的FormFile类:

package com.changcheng.web.client.service;



import java.io.InputStream;



/**

* 上传文件

*/

public class FormFile {

/* 上传文件的数据 */

private byte[] data;

private InputStream inStream;

/* 文件名称 */

private String filname;

/* 表单字段名称*/

private String formname;

/* 内容类型 */

private String contentType = "application/octet-stream";



public FormFile(String filname, byte[] data, String formname, String contentType) {

this.data = data;

this.filname = filname;

this.formname = formname;

if(contentType!=null) this.contentType = contentType;

}



public FormFile(String filname, InputStream inStream, String formname, String contentType) {

this.filname = filname;

this.formname = formname;

this.inStream = inStream;

if(contentType!=null) this.contentType = contentType;

}



public InputStream getInStream() {

return inStream;

}



public void setInStream(InputStream inStream) {

this.inStream = inStream;

}



public byte[] getData() {

return data;

}



public void setData(byte[] data) {

this.data = data;

}



public String getFilname() {

return filname;

}



public void setFilname(String filname) {

this.filname = filname;

}



public String getFormname() {

return formname;

}



public void setFormname(String formname) {

this.formname = formname;

}



public String getContentType() {

return contentType;

}



public void setContentType(String contentType) {

this.contentType = contentType;

}



}



其中使用到的HttpRequester类:

package com.changcheng.web.client.service;



import java.io.DataOutputStream;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import org.apache.http.HttpResponse;

import org.apache.http.NameValuePair;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.impl.client.DefaultHttpClient;

import org.apache.http.message.BasicNameValuePair;

import org.apache.http.protocol.HTTP;

import org.apache.http.util.EntityUtils;

import android.util.Log;



/**

* http请求发送器

*/

public class HttpRequester {

/**

* 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:

* <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">

<INPUT TYPE="text" NAME="name">

<INPUT TYPE="text" NAME="id">

<input type="file" name="imagefile"/>

<input type="file" name="zip"/>

</FORM>

* @param actionUrl 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)

* @param params 请求参数 key为参数名,value为参数值

* @param file 上传文件

*/

public static String post(String actionUrl, Map<String, String> params, FormFile[] files) {

try {

String BOUNDARY = "---------7d 4a6d158c9"; //数据分隔线

String MULTIPART_FORM_DATA = "multipart/form-data";



URL url = new URL(actionUrl);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(6* 1000);

conn.setDoInput(true);//允许输入

conn.setDoOutput(true);//允许输出

conn.setUseCaches(false);//不使用Cache

conn.setRequestMethod("POST");

conn.setRequestProperty("Connection", "Keep-Alive");

conn.setRequestProperty("Charset", "UTF-8");

conn.setRequestProperty("Content-Type", MULTIPART_FORM_DATA + "; boundary=" + BOUNDARY);



StringBuilder sb = new StringBuilder();

for (Map.Entry<String, String> entry : params.entrySet()) {//构建表单字段内容

sb.append("--");

sb.append(BOUNDARY);

sb.append("\r\n");

sb.append("Content-Disposition: form-data; name=\""+ entry.getKey() + "\"\r\n\r\n");

sb.append(entry.getValue());

sb.append("\r\n");

}

DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());

outStream.write(sb.toString().getBytes());//发送表单字段数据

for(FormFile file : files){//发送文件数据

StringBuilder split = new StringBuilder();

split.append("--");

split.append(BOUNDARY);

split.append("\r\n");

split.append("Content-Disposition: form-data;name=\""+ file.getFormname()+"\";filename=\""+ file.getFilname() + "\"\r\n");

split.append("Content-Type: "+ file.getContentType()+"\r\n\r\n");

outStream.write(split.toString().getBytes());

if(file.getInStream()!=null){

byte[] buffer = new byte[1024];

int len = 0;

while((len = file.getInStream().read(buffer))!=-1){

outStream.write(buffer, 0, len);

}

file.getInStream().close();

}else{

outStream.write(file.getData(), 0, file.getData().length);

}

outStream.write("\r\n".getBytes());

}

byte[] end_data = ("--" + BOUNDARY + "--\r\n").getBytes();//数据结束标志

outStream.write(end_data);

outStream.flush();

int cah = conn.getResponseCode();

if (cah != 200) throw new RuntimeException("请求url失败");

InputStream is = conn.getInputStream();

int ch;

StringBuilder b = new StringBuilder();

while( (ch = is.read()) != -1 ){

b.append((char)ch);

}

Log.i("ItcastHttpPost", b.toString());

outStream.close();

conn.disconnect();

return b.toString();

} catch (Exception e) {

throw new RuntimeException(e);

}

}



/**

* 提交数据到服务器

* @param actionUrl 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)

* @param params 请求参数 key为参数名,value为参数值

* @param file 上传文件

*/

public static String post(String actionUrl, Map<String, String> params, FormFile file) {

return post(actionUrl, params, new FormFile[]{file});

}



/**

* 提交数据到服务器

* @param actionUrl 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)

* @param params 请求参数 key为参数名,value为参数值

*/

public static String post(String actionUrl, Map<String, String> params) {

HttpPost httpPost = new HttpPost(actionUrl);

List<NameValuePair> list = new ArrayList<NameValuePair>();

for (Map.Entry<String, String> entry : params.entrySet()) {//构建表单字段内容

list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));

}

try {

httpPost.setEntity(new UrlEncodedFormEntity(list, HTTP.UTF_8));

HttpResponse httpResponse = new DefaultHttpClient().execute(httpPost);

if(httpResponse.getStatusLine().getStatusCode() == 200){

return EntityUtils.toString(httpResponse.getEntity());

}

} catch (Exception e) {

throw new RuntimeException(e);

}

return null;

}

}

我们最好对HTTP协议有深入的了解,这样在编写简单数据交互应用时直接面向HTTP协议编程可以提高运行速度并减少资源的占用。

我们在最后一个方法中使用到的HttpPost类,是Apache开源组织提供的httpcomponents-client-4.0.1包。httpcomponents-client-4.0.1可以实现浏览器的大部分功能,但如果我们能不使用它就尽量不使用它,因为这会造成对手机硬件资源的占用,从而减慢应用程序的运行速度。



4.测试类

package com.changcheng.web.client.test;



import com.changcheng.web.client.service.ClientService;

import android.test.AndroidTestCase;



public class TestAndroidClientService extends AndroidTestCase {



public void testSendDataToServerByGet() throws Throwable {

ClientService.sendDataToServerByGet();

}



public void testSendDataToServerByPost() throws Throwable {

ClientService.sendDataTOserverByPost();

}



public void testSendDataToServerByForm() throws Throwable {

ClientService.sendDataToServerByForm();

}

}





5.运行

首先启动AndroidWebService应用程序,然后运行测试方法,查看运行结果。

更多相关文章

  1. 深度详解Retrofit2使用(二)实践
  2. 【Android(安卓)Audio】Android(安卓)Audio System 之一:AudioTra
  3. (4.2.9)【android开源工具】Android(安卓)ORMLite 框架的入门用法
  4. Android保存List>数据到SD卡及读取
  5. Android(安卓)数据存数---SQLite数据库
  6. Android中SparseArray性能优化的使用方法
  7. Android实现图片选择器功能
  8. Android数据库使用(LitePal)
  9. [Android]Uri、UriMatcher、ContentUris详解

随机推荐

  1. android SDK manager 无法获取更新版本列
  2. Android Studio3.1.2 build.gradle class
  3. Android简单明了的使用属性动画ObjectAni
  4. Android(安卓)Intent调用 Uri的使用几种
  5. android ndk调用Log.getStackTraceString
  6. Android(安卓)实现仿支付宝的密码均分输
  7. 在AndroidManifest.xml文件中的android:w
  8. android adb 命令发送 keyevent
  9. Android 在某一页禁止home键返回
  10. Android(安卓)RecycerView 中根据图片大