android 网络传输序列化的对象------不需要进行xml/json解析

要做一个优秀的Android应用,使用到网络通信技术是必不可少的,很难想象一款没有网络交互的软件最终能发展得多成功。那么我们来看一下,一般Android应用程序里都是怎么实现网络交互的,这里拿一个Boook对象为例:


如上图所示,首先在手机端生成一个Book对象,里面包含书名、作者、价格等数据。为了要将这些数据发送到服务器端,我们要从Book对象中把数据取出,然后组装成XML格式的字符串。接着通过网络API,把组装好的XML字符串发送到服务器端。服务器端接到了客户端发来的XML字符串,就要对该XML进行解析。然后把解析出的数据重新组装成Book对象,之后服务器端就可以对该对象进行一系列其它的操作了。

当然XML格式的数据量比较大,现在很多Android应用为了节省流量,都改用JSON格式来传输数据了。不过不管是使用XML还是JSON,上图中描述的步骤总是少不了的。

感觉使用这种方式来传输数据,每次封装和解析XML的过程是最繁琐的,那么能不能把这最繁琐的过程绕过去呢?


如上图所示,如果可以调用网络API,直接把Book对象发送到服务器端,那么整个网络交互过程就会变得非常简单,下面我们就来看看如何实现。

新建一个Android工程,命名为ClientTest作为客户端工程。这里第一个要确定的就是待传输的对象,我们新建一个Book类,代码如下:

[java]  view plain copy
  1. package com.test;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. public class Book implements Serializable {  
  6.   
  7.     private String bookName;  
  8.   
  9.     private String author;  
  10.   
  11.     private double price;  
  12.   
  13.     private int pages;  
  14.   
  15.     public String getBookName() {  
  16.         return bookName;  
  17.     }  
  18.   
  19.     public void setBookName(String bookName) {  
  20.         this.bookName = bookName;  
  21.     }  
  22.   
  23.     public String getAuthor() {  
  24.         return author;  
  25.     }  
  26.   
  27.     public void setAuthor(String author) {  
  28.         this.author = author;  
  29.     }  
  30.   
  31.     public double getPrice() {  
  32.         return price;  
  33.     }  
  34.   
  35.     public void setPrice(double price) {  
  36.         this.price = price;  
  37.     }  
  38.   
  39.     public int getPages() {  
  40.         return pages;  
  41.     }  
  42.   
  43.     public void setPages(int pages) {  
  44.         this.pages = pages;  
  45.     }  
  46.   
  47. }  
这个类就是一个简单的POJO,但是要注意一点,它实现了Serializable接口,如果想在网络上传输对象,那么该对象就一定要实现Serializable接口

接下来打开或新建activity_main.xml作为程序的主布局文件,加入如下代码:

[html]  view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#000"  
  6.     tools:context=".MainActivity" >  
  7.   
  8.    <Button   
  9.      android:id="@+id/send"    
  10.      android:layout_width="fill_parent"  
  11.      android:layout_height="wrap_content"  
  12.      android:text="发送"  
  13.      />  
  14.   
  15. </RelativeLayout>  
这个布局里面就是包含了一个按钮,点击这个按钮就去发出网络请求。

接下来打开或新建MainActivity作为程序的主Activity,其中加入如下代码:

[java]  view plain copy
  1. public class MainActivity extends Activity implements OnClickListener {  
  2.   
  3.     private Button send;  
  4.   
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main);  
  9.         send = (Button) findViewById(R.id.send);  
  10.         send.setOnClickListener(this);  
  11.     }  
  12.   
  13.     @Override  
  14.     public void onClick(View v) {  
  15.         Book book = new Book();  
  16.         book.setBookName("Android高级编程");  
  17.         book.setAuthor("Reto Meier");  
  18.         book.setPages(398);  
  19.         book.setPrice(59.00);  
  20.         URL url = null;  
  21.         ObjectOutputStream oos = null;  
  22.         try {  
  23.             url = new URL("http://192.168.1.103:8080/ServerTest/servlet/TestServlet");  
  24.             HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  25.             connection.setDoInput(true);  
  26.             connection.setDoOutput(true);  
  27.             connection.setConnectTimeout(10000);  
  28.             connection.setReadTimeout(10000);  
  29.             connection.setRequestMethod("POST");  
  30.             oos = new ObjectOutputStream(connection.getOutputStream());  
  31.             oos.writeObject(book);  
  32.             InputStreamReader read = new InputStreamReader(connection.getInputStream());  
  33.             BufferedReader br = new BufferedReader(read);  
  34.             String line = "";  
  35.             while ((line = br.readLine()) != null) {  
  36.                 Log.d("TAG""line is " + line);  
  37.             }  
  38.             br.close();  
  39.             connection.disconnect();  
  40.         } catch (Exception e) {  
  41.             e.printStackTrace();  
  42.         } finally {  
  43.   
  44.         }  
  45.     }  
  46.   
  47. }  
我们可以看到,在onClick方法中处理了按扭的点击事件。这里首先new出了一个Book对象作为待传输数据,接着new出了一个URL对象,指明了服务器端的接口地址,然后对HttpURLConnection的一些可选参数进行配置。 接着通过调用ObjectOutputStream的writeObject方法, 将Book对象发送到服务器端,然后等服务器端返回数据,最后关闭流和连接。

注意由于我们使用了网络功能,因此需要在AndroidManifest.xml中加入如下权限:

[html]  view plain copy
  1. <uses-permission android:name="android.permission.INTERNET" />  
好了,目前Android端的代码已经开发完成,我们现在开始来编写服务器端代码。

新建一个名为ServerTest的Web Project,要做的第一件事就在Web Project下建立一个和Android端一样的Book类。这里有个非常重要的点大家一定要注意,服务器端的Book类和Android端的Book类,包名和类名都必须相同,否则会出现类型转换异常。这里由于两个Book类的内容是完全一样的,我就不再重复贴出。

然后新建一个Java Servlet作为网络访问接口,我们重写它的doPost方法,具体代码如下:

[java]  view plain copy
  1. public class TestServlet extends HttpServlet {  
  2.   
  3.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  4.             throws ServletException, IOException {  
  5.         ObjectInputStream ois = null;  
  6.         try {  
  7.             ois = new ObjectInputStream(request.getInputStream());  
  8.             Book book = (Book) ois.readObject();  
  9.             System.out.println("书名是: " + book.getBookName());  
  10.             System.out.println("作者是: " + book.getAuthor());  
  11.             System.out.println("价格是: " + book.getPrice());  
  12.             System.out.println("页数是: " + book.getPages());  
  13.             PrintWriter out = response.getWriter();  
  14.             out.print("success");  
  15.             out.flush();  
  16.             out.close();  
  17.         } catch (Exception e) {  
  18.             e.printStackTrace();  
  19.         } finally {  
  20.             ois.close();  
  21.         }  
  22.     }  
  23.       
  24. }  
可以看到,我们首先通过调用HttpServletRequest的getInputStream方法获取到输入流,然后将这个输入流组装成ObjectInputStream对象。接下来就很简单了,直接调用ObjectInputStream的readObject方法,将网络上传输过来的Book对象获取到,然后打印出Book中携带的数据,最后向客户端返回success。

现在我们来运行一下程序,首先将ServerTest这个项目布置到服务器上,并开启服务器待命。接着在手机上打开ClientTest这个应用程序,如下图所示:

                            

点击发送发出网络请求,可以看到服务器端打印结果如下:


而Android端打印结果如下:


由此我们可以看出,网络上进行对象传输已经成功了!不需要通过繁琐的XML封装和解析,我们也成功将Book中的数据完整地从Android端发送到了服务器端。

package com.vtion.sleb.banca.http;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OptionalDataException;
import java.io.StreamCorruptedException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;

import android.content.Context;
import android.content.res.Resources.NotFoundException;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.db4o.ObjectContainer;
import com.db4o.ext.DatabaseClosedException;
import com.db4o.ext.DatabaseReadOnlyException;
import com.db4o.ext.Db4oIOException;
import com.vtion.sleb.activities.R;
import com.vtion.sleb.banca.model.AdvertItem;
import com.vtion.sleb.banca.utils.SDUtils;
import com.vtion.sleb.entity.FileMsg;

public class FindAdByNameHttpClient extends Thread {
	private static final int REFRESHAD = 0x124;
	private Context context;
	private Handler handler;
	private List<FileMsg> fileMsgList;
	private ObjectContainer db;

	public FindAdByNameHttpClient(Context context, Handler handler, List<FileMsg> fileMsgList, ObjectContainer db) {
		super();
		this.context = context;
		this.handler = handler;
		this.fileMsgList = fileMsgList;
		this.db = db;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		if (!SDUtils.checkSD())
			return;
		try {
			int index = 0;
			for (FileMsg e : fileMsgList) {
				index = fileMsgList.indexOf(e);
				String findAdByNameurl = context.getResources().getString(R.string.SERVER_URL) + "client/findAdByName.do?fileName=" + e.getFileId();
				URL getUrl = new URL(findAdByNameurl);
				HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
				connection.setRequestProperty("Accept-Charset", "utf-8");
				connection.setRequestProperty("contentType", "utf-8");
				connection.setRequestMethod("POST");
				connection.setConnectTimeout(15 * 1000);
				connection.setReadTimeout(15 * 1000);
				connection.connect();
				int responseCode = connection.getResponseCode();
				// 服务器响应OK 状态吗=200
				if (responseCode == 200) {
					ObjectInputStream objectIn = new ObjectInputStream(new BufferedInputStream((connection.getInputStream())));
					FileMsg fileMsg = (FileMsg) objectIn.readObject();
					objectIn.close();
					if (fileMsg == null)
						return;
					byte[] bytes = fileMsg.getImageFile(); // 得到图片的字节数据
					String sdDir = Environment.getExternalStorageDirectory().toString();// 得到根路径
					File fileDir = new File(sdDir + "/SunLifeEverBright/Banca/Advertisement/");
					if (!fileDir.exists()) {
						fileDir.mkdirs();// 创建存放Banca广告的目录
					}
					String filepath = sdDir + "/SunLifeEverBright/Banca/Advertisement/" + fileMsg.getFileName();
					File file = new File(filepath);
					if (!file.exists()) {
						file.createNewFile();
					}
					FileOutputStream fos = new FileOutputStream(file);
					fos.write(bytes);
					fos.flush();
					fos.close();
					AdvertItem item = new AdvertItem();
					item.setFileName(e.getFileName());
					item.setSort(Integer.valueOf(e.getShowNo()));
					if (db != null) {
						db.store(item);
						db.commit();
					}
				}
				if (index == fileMsgList.size() - 1)
					Message.obtain(handler, REFRESHAD, 1, -1).sendToTarget();
			}
		} catch (DatabaseClosedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DatabaseReadOnlyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Db4oIOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (StreamCorruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (OptionalDataException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

package com.vtion.sleb.banca.http;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OptionalDataException;
import java.io.StreamCorruptedException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;

import android.content.Context;
import android.content.res.Resources.NotFoundException;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.db4o.ObjectContainer;
import com.db4o.ext.DatabaseClosedException;
import com.db4o.ext.DatabaseReadOnlyException;
import com.db4o.ext.Db4oIOException;
import com.vtion.sleb.activities.R;
import com.vtion.sleb.banca.model.AdvertItem;
import com.vtion.sleb.banca.utils.SDUtils;
import com.vtion.sleb.entity.FileMsg;

public class FindAdByNameHttpClient extends Thread {
	private static final int REFRESHAD = 0x124;
	private Context context;
	private Handler handler;
	private List<FileMsg> fileMsgList;
	private ObjectContainer db;

	public FindAdByNameHttpClient(Context context, Handler handler, List<FileMsg> fileMsgList, ObjectContainer db) {
		super();
		this.context = context;
		this.handler = handler;
		this.fileMsgList = fileMsgList;
		this.db = db;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		if (!SDUtils.checkSD())
			return;
		try {
			int index = 0;
			for (FileMsg e : fileMsgList) {
				index = fileMsgList.indexOf(e);
				String findAdByNameurl = context.getResources().getString(R.string.SERVER_URL) + "client/findAdByName.do?fileName=" + e.getFileId();
				URL getUrl = new URL(findAdByNameurl);
				HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
				connection.setRequestProperty("Accept-Charset", "utf-8");
				connection.setRequestProperty("contentType", "utf-8");
				connection.setRequestMethod("POST");
				connection.setConnectTimeout(15 * 1000);
				connection.setReadTimeout(15 * 1000);
				connection.connect();
				int responseCode = connection.getResponseCode();
				// 服务器响应OK 状态吗=200
				if (responseCode == 200) {
					ObjectInputStream objectIn = new ObjectInputStream(new BufferedInputStream((connection.getInputStream())));
					FileMsg fileMsg = (FileMsg) objectIn.readObject();
					objectIn.close();
					if (fileMsg == null)
						return;
					byte[] bytes = fileMsg.getImageFile(); // 得到图片的字节数据
					String sdDir = Environment.getExternalStorageDirectory().toString();// 得到根路径
					File fileDir = new File(sdDir + "/SunLifeEverBright/Banca/Advertisement/");
					if (!fileDir.exists()) {
						fileDir.mkdirs();// 创建存放Banca广告的目录
					}
					String filepath = sdDir + "/SunLifeEverBright/Banca/Advertisement/" + fileMsg.getFileName();
					File file = new File(filepath);
					if (!file.exists()) {
						file.createNewFile();
					}
					FileOutputStream fos = new FileOutputStream(file);
					fos.write(bytes);
					fos.flush();
					fos.close();
					AdvertItem item = new AdvertItem();
					item.setFileName(e.getFileName());
					item.setSort(Integer.valueOf(e.getShowNo()));
					if (db != null) {
						db.store(item);
						db.commit();
					}
				}
				if (index == fileMsgList.size() - 1)
					Message.obtain(handler, REFRESHAD, 1, -1).sendToTarget();
			}
		} catch (DatabaseClosedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DatabaseReadOnlyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Db4oIOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (StreamCorruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (OptionalDataException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}


源码下载,请点击这里

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值