转载请注明出处:http://blog.csdn.net/SCTU_vroy/article/details/49366853
本文将详述如何在android(客户端)上与服务端通过Hessian实现网络通信、数据传输。
网上关于这方面的资料并不少,但是良莠不齐,让笔者走了不少弯路。本文将先解析android端源代码(ps:web端代码各位度娘or谷歌),而后分享在android上实现hessian常见的错误和解决方法。请各位大神多多提意见,谢谢~
Step 1:新建android工程,添加权限,导入源码工程中android_hessian的jar包
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
注意:
1)hessian官网提供的jar包适用于web端开发,不适用于android端;
2)code.google提供的hessdroid包亲测是有问题的,大概是因为里面包含一些android不支持的类,
具体可见:http://hsrong.iteye.com/blog/1719996
Step 2:创建接口IHessian,前端与后端必须一致
public interface IHessian {
String sayHello();
void sendModel(HessianModel model);
}
Step 3:创建数据类HessianModel,前端与后端字段名(属性)必须一致,而且包名(命名空间)也必须一致,并且需要实现序列化!(因为Hessian 是一个基于 binary-RPC 实现的远程通讯)
package com.example.androidhessian;
import java.io.Serializable;
/**
* 统一的数据包model
* 字段名必须统一
* 且必须实现序列化
* @author victor shi
* 2015/10/20
*/
public class HessianModel implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private long id;
private String name;
private String date;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
Step 4:回到MainActivity,获取服务端ip,new一个子线程实现hessian请求。这里可能有人会问,为什么不直接在主线程进行网络通信?这个会在后面解答。
1)手机连接wifi热点后,获取服务端地址,记得在AndroidManifest.xml中添加网络权限:
/*
* 获取服务端地址
*/
public static String getHostIP(Context context) {
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
DhcpInfo dhcpInfo = wifi.getDhcpInfo();
StringBuilder sb = new StringBuilder();
// sb.append("网络信息:" + "\n");
// sb.append("本机ip:" + formatIP(dhcpInfo.ipAddress) + "\n");
// sb.append("子网掩码:" + formatIP(dhcpInfo.netmask) + "\n");
// sb.append("网关ip:" + formatIP(dhcpInfo.gateway) + "\n");
sb.append(formatIP(dhcpInfo.serverAddress));
return sb.toString();
}
/*
* ip格式化
*/
private static String formatIP(int ipAddress) {
return (ipAddress & 0xff) + "." + ((ipAddress >> 8) & 0xff) + "."
+ ((ipAddress >> 16) & 0xff) + "." + ((ipAddress >> 24) & 0xff);
}
2)直接po出Activity的代码:
public class MainActivity extends Activity {
private static final String TAG = "Android Hessian Test";
private static final String PORT = "8081"; //端口号
private static final long TIMEOUT = 5000L; //网络请求时长
private Button button;
private TextView tv;
private HessianModel model = null;
private String url = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
initData();
initEvent();
}
private void initView() {
button = (Button) findViewById(R.id.btnHessian);
tv = (TextView) findViewById(R.id.tvMsg);
}
private void initData() {
model = new HessianModel();
model.setDate("2015.10.20");
model.setId(1L);
model.setName("victor");
/*
* 获取服务端ip地址
*/
url = "http://" + NetTools.getHostIP(getApplicationContext()) + ":" + PORT + "/test.hessian";
}
private void initEvent() {
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Hessian 请求
new Thread(runnable).start();
}
});
}
/**
* 处理队列信息
* 操作UI
*/
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv.setText(msg.obj.toString());
}
};
/**
* 开启子线程进行网络通信
* 自Android4.0版本以后,不支持在UI主线程中网络通信,
* 否则会报运行异常android.os.NetworkOnMainTreadException
*/
Runnable runnable = new Runnable() {
@Override
public void run() {
HessianProxyFactory factory = new HessianProxyFactory();
Message msg = Message.obtain();
factory.setDebug(true);
factory.setReadTimeout(TIMEOUT);
try {
IHessian service = (IHessian) factory.create(IHessian.class, url, getClassLoader());
msg.obj = service.sayHello();
handler.sendMessage(msg);
// service.sendModel(model);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
};
}
代码解析:
1)url中端口号PORT后面的字符串“/test.hessian”取决于后台项目的路径;
2)为什么需要new一个子线程来实现hessian通信呢?原因在于自Android4.0版本后,如果直接在主线程进行网络通信,程序运行会抛出运行异常:android.os.NetworkOnMainThreadException。解决方法有几种,可自行搜索,此处采用多线程的方法,也可直接使用AsyncTask异步处理更方便。
到这里,源代码的解析部分就结束了,最后分享一下在android上实现hessian常见的问题和解决方法:
(ps:基本都是运行异常)
问题一:java.lang.NoClassDefFoundError: com/caucho/hessian/client/HessianConnectionException
解决方法:问题出在hessian包的版本,导入本文源码工程libs下的android_hessian.jar包即可解决。
问题二:android.os.NetworkOnMainThreadException
解决方法:如果是android4.0以下版本则不会报错,4.0以上则不允许在主线程中实现网络通信,只能new子线程,在子线程中实现hessian通信。
问题三:com.caucho.hessian.client.HessianConnectionException: 500: java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
解决方法:此异常是出在已经与服务端建立网络连接的基础上,问题还是出在hessian的jar包,即便jar包可以在web端使用,但是里面包含一些android不支持的类。所以还是需要导入正确的jar包,并add to build path,可从本文源码工程中获取,或者打开链接下载:http://hsrong.iteye.com/blog/1719996
还有需要注意的地方就是:
1)传递的对象model包名(or命名空间)需要一致
2)传递的对象model需要序列化
3)传递的对象model结构一致,字段名/属性名
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。