新博客,新手。以下内容都是最近新学习的,算是做个记录,另外对有这方面需求的朋友提供个参考。不对指出,请多指教。
本人,之前只学过java,后来实习,有一部分需求,是多屏互动,需要android 调用wcf 服务。我花了很多时间,在网上搜索资料,现在发现,很多时间都不高效。
废话不多说了,我尽量把结构写的清楚些。 本来想把程序传上来,但是还不太清楚怎么弄,需要的朋友留邮箱吧。程序没啥可能,以后完善之后再说吧。
我在word 上已完成的部分,分两个部分,一个是wcf 创建,另一方是android端调用。下面我用*****最为这部分的开头。因为我要在这部上面添加一些不具体的东西。
总结:
环境:vs2010 android集成版 android 模拟器2.3.3 本机作为服务器
一wcf
1wcf 的服务契约
2服务命名空间
3app.config 图形界面编辑
4baiscHttpBinding 和 wsHttpBinding
二android端
1导入jar包 ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar
2 4个参数
private static final String NAMESPACE ; //服务契约中定义的命名空间 **在wcf创建中找
Private static final String URL ;//地址// **需要注意
private static final String METHOD_NAME;//调用方法名称
private static final String SOAP_ACTION ;//ACTION 标签 **wcf客户端测试 xml 格式中找
3 soap 对象,及调用过程
SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME);// soapobject 对象
rpc.addProperty("stringValue", "ads"); //为调用的服务方法参数赋值
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);//信封注册
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
HttpTransportSE ht = new HttpTransportSE(URL); //定位服务
ht.debug = true;
ht.call(SOAP_ACTION, envelope);//请求
4 在AndroidManifest.xml 文件中加<uses-permission> 标签
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
*******
Android 调用 wcf 服务
一:wcf 创建
生成的wcf 目录结构
1App.config (配置文件)
配置文件,就是一些基本的配置,包括地址和协议类型,对xml 不太理解的,里面的属性也不太清楚,就不要太费神了去看了。
右键点击App.config 文件,有个编辑wcf配置,可以进行可视化操作
2IService
从本质上看,ISerivice 就是一个接口,他定义你的服务将要提供什么方法。但是因为他是不是应用与本地的应用程序中,所以需要定义一些契约。
多余的契约不多说,这里只简单介绍几个。
把没用的都删掉
只留下:
namespace WcfServiceLibrary1
{
[ServiceContract(Name = “aa”,NameSpace=“http://www.jz.GetData”)] //定义服务契约 他主要有两个参数 Name 和 NameSpace 特别注意NameSpace 因为当你用 android 通过 Soap 去访问你的服务时,要用到这个参数
public interface IService1
{
[OperationContract]
string GetData(int value);
}
}
//更多的去访问这个
http://www.cnblogs.com/cpcpc/archive/2011/07/22/2122991.html
3Service
这个文件主要是去实现接口里定义的方法
namespace WcfServiceLibrary1
{
public class Service1 : IService1
{
public string GetData(int value)
{
return "hello" + value;
}
}
}
到这里wcf 创建就已完成,按f5,程序就会运行
我们主要看第一个:wcf 测试客户端
目录为:
我的服务项目
http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex
aa
GetData()
配置文件
看到这个目录结构,了解了,aa是我们在服务契约中定义的服务名字。GetData()定义的方法;
现在双击 GetData这个放法,如下
分为
请求 和 响应
我们在请求里,为我们的方法赋值,然后点调用,就会有返回的值。
然后看他的xml 格式
1envelope 这个标签 规定了他命名空间,他根据你的协议,定义到不同的命名空间
下面来试一试,打开,app.config 找到 <endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary1.IService1">
把binding 属性值改为 basicHttpBinding
<endpoint address ="" binding="basicHttpBinding" contract="WcfServiceLibrary1.IService1">
他们对应着不同的版本。Basic --》v11 ws--》v12 此处记住就好,具体我也没太搞明白,之前通过java调用的时候,他提示版本错误,java好像支持v11。我接下来都用的是basicHttpBinding
2 <Action> 标签内的http://www.jz.GetData/aa/GetData
对应结构为:命名空间/服务名/方法
对应的是Soap 当中的SOAP_ACTION,是传输对象 HttpTransportSE ht对象中的 call 方法的参数之一。
ht.call(SOAP_ACTION, envelope);此块内容之后再说。
3 指明 请求方法的所在的命名空间,也就是我们服务的命名空间。http://www.jz.GetData
他也对应着,soap 中的一个参数。NAMESPACE ; METHOD_NAME 就是GetData;
SoapObject SO = new SoapObject(NAMESPACE, METHOD_NAME);
4<value> 截图中没有标出来。 <Value>标签 是<GetData>的子标签。实际上他就是GetData
方法的形参。 我是通过 3中 SO对象的addProperty(String name,Object value); name 就是对应的参数的名字,value 传入对应的值。 addProperty(“value”,2);
到此为止,wcf端的框架就搭出来了。
二Android端
首先 需要一个包
ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar
还有2.5.4版本的,我两个都下了,当时找的时候很费劲,很多地方都要积分或者是会员啥的,如果我这篇记录贴出来,我会附带jar 包,包括我写的程序。供和一样的新手参考。
废话不多说。直接进入主题。
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
public Button button = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) this.findViewById(R.id.button1);
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
getWeb();
}
});
}
private static final String NAMESPACE = "http://www.jz.getData/";
private static final String URL = "http://10.0.2.2:8732/Design_Time_Addresses/JZservice/Service1/";
private static final String METHOD_NAME = "GetData";
private static final String SOAP_ACTION = "http://www.jz.getData/IService1/GetData";
private SoapObject detail;
public void getWeb() {
try {
System.out.println("进入getWeather方法");
SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME);
rpc.addProperty("stringValue", "ads");
System.out.println("rpc1成功创建" + rpc.toString());
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
HttpTransportSE ht = new HttpTransportSE(URL);
System.out.println("ht");
ht.debug = true;
ht.call(SOAP_ACTION, envelope);
System.out.println("call 成功");
try {
/*detail =(SoapObject) envelope.getResponse();
System.out.println(detail);*/
if ( envelope.getResponse()!=null) {
String string=envelope.bodyIn.toString();
System.out.println(string);
} } catch (Exception e) {
// TODO: handle exception
System.out.println("error");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
够直接吧,直接上代码。当然,我不会这么不负责任。接下来,我会把当中一些地方去讲一下。
1程序结构
Android的oncreat()方法中,调用getweb()方法;就这么简单。东西soap 的东西都在getweb方法中。
2getweb();
private static final String NAMESPACE = "http://www.jz.getData/";
Private static final String URL
= "http://10.0.2.2:8732/Design_Time_Addresses/JZservice/Service1/";
private static final String METHOD_NAME = "GetData";
private static final String SOAP_ACTION = "http://www.jz.getData/IService1/GetData";
private SoapObject detail;
5个参数
NAMESPACE METHOD_NAME 没啥好说的,看了上面wcf创建过程的朋友们都知道了。
SOAP_ACTION 这个参数,我在网上找资料的时候,很多人都写的是(命名空间+方法名) 但是老是出错。后来看了很多东西,最后还是从wcf 客户端调试窗口中看明白的。
建议大家写的时候,多参考wcf 客户端调试窗口的xml格式中的<action>标签里面给了具体的值。
URL 这个东西我很纠结,因为网上的大神们都用实体android机去测试,我对android还不太了解。实体机这部分我还没搞。时间有限,以后我会搞的。废话不说了。
打开配置文件,找到 <endpoint>标签,你会发现它是这样的,
你把他复制到浏览器里访问,也是可以的,但是,你通过本机的sdk访问,会被拒绝;
提示这样一个警告,localhost/127.0.0.1 其实是这样的,在android里面127.0.0.1代表的是模拟器的地址,而10.0.0.2代表的才是电脑的127.0.0.1。所以如果是自己本机做WCF服务器的话,程序里面应该这么设置。
还有一种方法,就是直接用你电脑的ip地址来代替localhost。
参数讲完了,接下来我来讲创建过程。
我在代码里,写了好多输出语句和try catch 结构,主要是为了调试错误。其实也可以用debug来调试,但是try catch 还是不能省略的。 不多说,看步骤
1 定义五个参数 为了看的方便,具体我就不写了,参考上面的
private static final String NAMESPACE ; //服务契约中定义的命名空间
Private static final String URL ;//地址
private static final String METHOD_NAME;//调用方法名称
private static final String SOAP_ACTION ;//ACTION 标签 具体含义我想是为了地位服务中的资源
private SoapObject detail;//获取返回值
2 //创建一个 SoapObject 对像 用到了,服务契约中命名空间 和 调用的方法名
SoapObject so = new SoapObject(NAMESPACE, METHOD_NAME);
3 如果方法需要传参数
需要调用SoapObject 对象的 addProperty(String name ,Object value) 方法 name 对应方法参数的名字,在wcf客户端调试的窗口中的xml格式中可以找到。是调用方法的子标签。
4
我看SOAP的教程中有这么一段话说是:
必需的 SOAP 的 Envelope 元素是 SOAP 消息的根元素。它可把 XML 文档定义为 SOAP 消息。
所以我在这个类,也就是初始化一下请求信息,新手不要去纠结这个问题。
从参数来看,他就是注册了这个soap的版本,是11,我在wcf的创建过程中,也提到了版本问题,一个是wsHttpBinding 对应12 另一个是basicHttpBinding 对应的v11.过去不去的朋友,去看看网络方向的资料。
//获得序列化的Envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
//必需的 SOAP Body 元素可包含打算传送到消息最终端点的实际 SOAP 消息。
envelope.bodyOut = os;//他的值也是一个SoapObject 对象 ,我理解就是信封body部分的内容
// 服务器类型? 传参不成功
envelope.dotNet = true;
//注释掉 不受影响
envelope.setOutputSoapObject(os);
5
//创建传输对象
HttpTransportSE h_trans= new HttpTransportSE(URL);
h_trans.debug = true;
//调用WebService(命名空间+服务名称+方法名称,Envelope对象):
h_trans.call(SOAP_ACTION, envelope);
6接受返回值
if ( envelope.getResponse()!=null) {
String string=envelope.bodyIn.toString();
System.out.println(string);
}
7在AndroidManifest.xml 文件中加<uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
参考
http://www.cnblogs.com/zhaoyx/articles/2633590.html
http://www.cnblogs.com/qingblog/archive/2012/06/26/2563862.html
http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html