在Android端不再仅仅单机游戏而连接网站服务器获取数据并实现互通一 直以来是我的梦想, 可是网上教程都是Android+JAVAEE或PHP的,无奈这两种服务器技术我都不会,与其说不会还不如说我更喜欢微软的ASP.NET,代码简洁优美规整呀,但为何流行不起来呢,不管别人怎么喜欢JAVA,我就是不喜欢JAVA的代码的啰嗦和把简单的事情复杂化,更不喜欢它配那么多东西,所以还是研究我的C#吧!
1.服务端
首先,用ASP.NET建一个最简单的网站吧,用VS2010或2012都行,版本不要太高呀。就是一个Default.aspx+WebService.aspx页面,Default.aspx上就显示一句话而已这不重要
关键就是WebService.aspx吧,也很简单,就是返回一段字符串,如下代码 WebService.asmx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace SoapDemo
{
/// <summary>
/// WebService 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "呆呆,我好想你呀";
}
[WebMethod]
public string EchoMessage(string msg)
{
return msg;
}
}
}
好了然后发布到IIS吧,关于ASP.NET发布网站方法可参考ASP.NET发布网站到IIS 一文链接,值得一提的是发布启动网站后你很可能遇到不能浏览自己网站的问题,报什么Web.config无法插入default.aspx结点的错误,那是Web.config配置的问题,如下
2.客户端
Android调用WebService一般要用到KSoap库,可以从https://code.google.com/p/wsdl2ksoap/downloads/list进行下载,当然我给出的源码包里也有,不用再另外下载了
将下载的ksoap2-android-assembly-3.6.1-jar-with-dependencies.jar包复制到Eclipse或AndroidStudio工程的libs目录中,同时在Eclipse工程中引用这个jar包,至于怎么给工程添加这个jar包可自行百度,非常简单,Eclipse和AndroidStudio大体一样,都是dk 右键Add to Build Path吧,具体我也忘了,晕!
在安卓工程的 布局UI也很简单,就是一个TextView显示数据接收结果,两个按钮一个是 演示调用不带参数的WebService方法,一个是带参数的WebService方法,如下图:
布局文件activity_main.xml的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="org.daidai.com.demo.MainActivity">
<TextView
android:id="@+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="11111"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnHelloWorld"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="调用HelloWorld"
tools:layout_editor_absoluteX="147dp"
tools:layout_editor_absoluteY="338dp" />
<Button
android:id="@+id/btnMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="调用EchoMessage"
tools:layout_editor_absoluteX="147dp"
tools:layout_editor_absoluteY="338dp" />
</LinearLayout>
再简单不过的线性布局LinearLayyout,相信只要学过点Android的谁都会
1. 要在AndroidManifest.xml中加入权限,<manifest>节点里面加入下面这句话,开启网络权限
<uses-permission android:name="android.permission.INTERNET"/>
2.程序初始化代码
private TextView tvMessage;
final String METHOD_HELLO_WORLD = "HelloWorld";
final String METHOD_ECHO_MESSAGE = "EchoMessage";
//服务器链接
final String WEB_SERVICE_URL = "http://192.168.1.2:8002/WebService.asmx";
final String Namespace = "http://tempuri.org/";
@Override
protected void onCreate(Bundle savedInstanceState) {
//调用WebService的权限设置
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTv();
initBtn();
}
METHOD_HELLO_WORLD 和 METHOD_ECHO_MESSAGE两个字符串常量代表ASP.NET的WebService提供的两个方法名字,值得注意的是访问网址WEB_SERVICE_URL,这个IP地址是哪来的呢,当然是我们发布到网站上的网址了,可是,为什么我浏览网站后地址栏上只显示localhost呀,在android端写localhost肯定是不行的,这是第一个难点,IP地址搞错了webservice当然死活也连不上,不论真机和模拟器都一样,发布后看自己的网站IP地址其实很简单,就是运行里敲个cmd,然后IPConfig命令就行了,如下图: 还有连接WebService网址我写的是:http://192.168.1.2:8002/WebService.asmx,这个网站启动后在自己浏览器上输入是能访问到的,而网上其他教程给出的网址是 http://192.168.1.2:8002/WebService.asmx?wsdl,这个浏览器上也能访问到,但是你照这个网址android会返回访问被拒绝的异常,我照别人的教程也是搞了好久搞不出来,死活访问被拒绝,去掉那个?wsdl就好了,不知道前人大神为什么那么写。
3.活初始化两个按钮的方法,对应调用WebService的方法
private void initBtn()
{
Button btnHelloWorld = (Button)findViewById(R.id.btnHelloWorld);
btnHelloWorld.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map<String, String> values = new HashMap<String, String>();
values.put("msg","这是Android手机发出的信息");
Request(METHOD_HELLO_WORLD);
}
});
Button btnEchoMessage = (Button)findViewById(R.id.btnMessage);
btnEchoMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map<String, String> values = new HashMap<String, String>();
values.put("msg", "这是Android手机发出的信息");
Request(METHOD_ECHO_MESSAGE, values);
}
});
}
在Request(…)方法中,我们主要是想实现将WebService中方法名和调用的参数传入WebService。在这个方法中,主要应用了AsyncTask来处理WebService的调用,因为调用WebService是网络操作,可能会比较耗时,在Android3.0以上,已经不允许在UI线程直接进行网络操作,另外,AsyncTask还可以直接更新UI上的控件。
执行异步任务代码:
public void Request(Object...params)
{
new AsyncTask<Object,Object,String>(){
@Override
protected String doInBackground(Object... params) {
if (params!=null && params.length==2)
{
return CallWebService((String)params[0],
(Map<String,String>) params[1]);
}
else if (params!=null && params.length==1)
{
return CallWebService((String)params[0],null);
}
else
{
return null;
}
}
protected void onPostExecute(String result)
{
if (result!=null)
{
tvMessage.setText("服务器返回的消息:"+result);
}
}
}.execute(params);
}
4. 解析WebService的CallWebService方法
可以看到CallWebService使用了AsyncTask中doInBackground的可变参数列表,如何获取可变参数看得好深奥哦,其实看看代码就懂了,也不是很难,笑!
public String CallWebService(String MethodName, Map<String,String> Params)
{
// 1、指定webservice的命名空间和调用的方法名
SoapObject request = new SoapObject(Namespace, MethodName);
// 2、设置调用方法的参数值,如果没有参数,可以省略,
if (Params!=null)
{
Iterator iter = Params.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry)iter.next();
request.addProperty((String)entry.getKey(), (String)entry.getValue());
}
}
// 3、生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
envelope.bodyOut = request;
//C#提供的WebService
envelope.dotNet = true;
(new MarshalBase64()).register(envelope);
envelope.setOutputSoapObject(request);
HttpTransportSE ht = new HttpTransportSE(WEB_SERVICE_URL);
// 使用call方法调用WebService方法
try
{
ht.call(null, envelope);
}
catch (HttpResponseException e)
{
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
try
{
final SoapPrimitive result = (SoapPrimitive)envelope.getResponse();
if (result!=null)
{
Log.d("----收到的回复----", result.toString());
return result.toString();
}
}
catch (SoapFault e)
{
Log.e("----发生错误-----",e.getMessage());
e.printStackTrace();
}
return null;
}
我们的重点将放在CallWebService()这个方法中。这个方法里面封装了ksoap2类库里面调用WebService的一些对象。
(1) 指定webservice的命名空间和调用的方法名,如:
SoapObject request = new SoapObject(Namespace, MethodName);
SoapObject类的第一个参数表示WebService的命名空间,可以从WSDL文档中找到WebService的命名空间。第二个参数表示要调用的WebService方法名。
(2) 设置调用方法的参数值,如果没有参数,可以省略,当然我们遇到的最多情况还是有参数的,可不能省略,设置方法的参数值的代码如下:
Request.addProperty(“param1”,”value”);
Request.addProperty(“param2”,”value”);
要注意的是,addProperty方法的第1个参数表示调用方法的参数名,该参数值要与服务端的WebService类中的方法参数名一致,并且参数的顺序一致。
3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述,代码为:SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER12);
Envelope.bodyOut = request;
SOAP协议的版本号可以从WebService的WSDL文档,本例中为:http://192.168.1.2:8002/WebService.asmx?wsdl
(4) 创建HttpTransportsSE对象。通过HttpTransportsSE类的构造方法可以指定WebService的WSDL文档的URL:
HttpTransportSE ht=new HttpTransportSE(WEB_SERVICE_URL);
WEB_SERVICE_URL是指WebService的地址,本例为http://192.168.1.2:8002/WebService.asmx
(5)使用call方法调用WebService方法,代码:
ht.call(null,envelope);
Call方法的第一个参数一般为null,第2个参数就是在第3步创建的SoapSerializationEnvelope对象。
(6)使用getResponse方法获得WebService方法的返回结果,代码:
SoapPrimitive result = (SoapPrimitive) envelope.getResponse();
主要工作都完成了,
5、运行代码
要运行文章中的代码,请先将WebService部署在IIS上,要保证Android手机的测试程序和WebService处在同一个局域网中。