Android调用WebService过程中遇到的一些问题及解决方法
公司之前主要推出的是WindowsMobile设备的终端,我学的.net还可以用的上,可以在上面做一些简单的应用程序开发 ,但现在公司主推Android系统的终端了!我不得不也要学习Android,要不然我就在这呆不下去了...
好了,进入正题,Android的开发环境ADT我就不多说了(不知道的可以Google)。
参考博客:http://blog.csdn.net/lyq8479/article/details/6428288
在Android平台调用Web Service需要依赖于第三方类库ksoap2. 它的下载地址是:http://code.google.com/p/ksoap2-android/
一、准备工作
新Android项目,把刚才下载的ksoap2包放在项目中的libs目录下,刷新项目点击ksoap2包右键,选择Build Path>Add to Build Path 好了。
这时显示的可视化界面效果如图:
如果视图显示一片空白(没有可视化界面)请关闭ADT,移除项目空间下\.metadata\.plugins\org.eclipse.e4.workbench\workbench.xmi文件重新打开eclipse.
右键项目运行-选择Android Application项目,会自己运行模拟器,如果提示“Failed to initialize Monitor Thread: Unable to establish loopback connection”错误。
Google一下发现这个问题很常见,有关闭Adb进程再开启,关闭防火墙,重启电脑或eclipse。我的关闭防火墙OK了(电脑上安的是小a,把它禁止1小时)。重启eclipse就可以在模拟器中运行了。如果Android SDK Manager中有更新请完成这些更新,有时它也会影响。
二、编写布局文件res/layout/main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/phonenumber" /> <EditText android:id="@+id/phone_sec" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1" android:layout_below="@+id/textView1" android:ems="10" android:hint="1234567" android:inputType="number" android:singleLine="true" > <requestFocus /> </EditText> <Button android:id="@+id/btn_query" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/phone_sec" android:layout_below="@+id/phone_sec" android:text="@string/query" /> <TextView android:id="@+id/txt_result" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignRight="@+id/btn_query" android:layout_below="@+id/btn_query"/> </RelativeLayout>
我是第一次使用eclipse开发Android项目,很多小问题都不知道怎么回事,比如自己写了一个Button 照着它自带的TextView写了一个android:text="@string/query",在一直显示有错误,如果把@string/去掉,没有错误还有警告!后来在老朋友的帮助下才明白,如果那样写“query”根当于使用了一个变量但我又没有声明,所以显示错误,需要在/res/values/strings.xml中声明这个变量就行了。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">WSTest</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="phonenumber">phonenumber:</string> <string name="query">query</string> </resources>
三、编写MainActivity类
package com.example.wstest; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.app.ProgressDialog; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.SoapEnvelope; import org.ksoap2.transport.HttpTransportSE; public class MainActivity extends Activity { private EditText phoneSecEditText; private TextView resultView; private Button queryButton; private ProgressDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //自己的代码 phoneSecEditText = (EditText) findViewById(R.id.phone_sec); resultView = (TextView) findViewById(R.id.txt_result); queryButton = (Button) findViewById(R.id.btn_query); dialog = new ProgressDialog(this); dialog .setTitle("提示"); dialog.setMessage("正在查询,请稍后...."); queryButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //手机号 String phonesec = phoneSecEditText.getText().toString().trim(); //判断手机号码是否合法 if("".equals(phonesec)|| phonesec.length()<7) { //给出错误提示 phoneSecEditText.setError("您输入的手机号码有误!"); phoneSecEditText.requestFocus(); //将显示查询结果的TextView清空 resultView.setText(""); return; } //执行查询 new MyAsyncTask().execute(phonesec); } }); } public class MyAsyncTask extends AsyncTask<String, Void, String> { //准备 @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); //show dialog dialog.show(); } //主要执行下载等任务 @Override protected String doInBackground(String... params) { // TODO Auto-generated method stub //命名空间 String nameSpace = "http://WebXml.com.cn/"; //调用的方法名 String methodName ="getMobileCodeInfo"; //EndPoint String endPoint = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"; //SOAP action String soapAction = "http://WebXml.com.cn/getMobileCodeInfo"; //指定WebService的命名空间和调用的方法名 SoapObject rpc = new SoapObject(nameSpace,methodName); //设置需调用WebService接口需要传入的两个参数mobileCode、userId rpc.addProperty("mobileCode", params[0]); rpc.addProperty("userId",""); //生成调用WebService方法的SOAP请求信息,并指定SOAP的版本 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope (SoapEnvelope.VER11); envelope.bodyOut= rpc; //设置是否调用的是dotNet开发的WebService envelope.dotNet = true; //等价于envelope.bodyOut = rpc; //envelope.setOutputSoapObject(rpc); HttpTransportSE transport = new HttpTransportSE(endPoint); try { //调用 Webservice transport.call(soapAction, envelope); } catch(Exception ex) { ex.printStackTrace(); } //获取返回的数据 SoapObject object =(SoapObject) envelope.bodyIn ; //获取结果 String result = object.getProperty(0).toString(); return result; } @Override protected void onPostExecute(String result) { // TODO Auto-generated method stub super.onPostExecute(result); //show getinfo ,close dialog ,clear phonesec resultView.setText(result); dialog.dismiss(); phoneSecEditText.setText(""); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
说明:在运行程序的之前必须添加网络授权,双击打开AndroidMainifast.xml文件,选择Permissions->Add->Users Permissioin,然后在右则的Name中选择“android.permission.INTERNET”。
如果没有添加授权,则出出现下面错误:
四、异步任务
自从Android3.0之后吧,在UI的主线程中,它是不允许你直接访问网络这种耗时的操作,否则就是出现问题,我第一次做Android开发就照着前人步骤写的,怎么也得不到结果,把我都郁闷坏了,后来才知道需要异步来操作。
使用比较简单(应该是封装的比较好吧)的AsyncTask异步任务类来完成此操作,自己新建一个类继承于AsyncTask,重写
onPreExecute,doInBackground,onPostExecute这三个方法。onPreExecute是准备工作,doInBackground主要是执行网络连接操作,onPostExecute主要是把异步得到的结果更新到UI主线程上
具体的调用WebService中的方法我就不多说了,网上多的很大同小异,但是调用.net和java的WebService时还是有一点区别的,调用.net WebService时 需要把envelope.dotNet = true;
还有在调用 call方法时,多数是这样调用.net 第一个参数需要,调用java 第一个参数为null,(这个我没有求证,请自己测试)。
结果图示: