[019] Android平台调用WebService详解 .

2024-06-15 10:08

本文主要是介绍[019] Android平台调用WebService详解 .,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上篇文章已经对Web Service及其相关知识进行了介绍( Android开发之WebService介绍 ),相信有的朋友已经忍耐不住想试试在Android应用中调用Web Service。 本文将通过一个简单的示例讲解和演示Android平台的Web Service开发。

Ksoap2-android简介
      在Android平台调用Web Service需要依赖于第三方类库ksoap2,它是一个SOAP Web service客户端开发包,主要用于资源受限制的Java环境如Applets或J2ME应用程序(CLDC/ CDC/MIDP)。认真读完对ksoap2的介绍你会发现并没有提及它应用于Android平台开发,没错,在Android平台中我们并不会直接使用ksoap2,而是使用ksoap2 android。KSoap2 Android 是Android平台上一个高效、轻量级的SOAP开发包,等同于Android平台上的KSoap2的移植版本。

Ksoap2-android jar包下载
      ksoap2 android当前的最新版本为2.5.4,名为ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar,它的下载地址是:http://code.google.com/p/ksoap2-android/,进入页面后,点击“Downloads”标签页,如下图所示:
     
      在“Downloads”页面的下方,找到如下图所示的紫色的链接,然后在链接上点击右键,找到相关下载项进行下载即可。右键菜单中显示的下载项依据浏览器的不同而有所区别,比如我使用的360浏览器,在键接上点击右键,然后选择“使用360安全浏览器下载”即可弹出下载保存对话框。
     

Android平台调用Web Service示例
     下面将通过一个示例讲解如何在Android平台调用Web Service。既然要调用Web Service,那就要先有Web Service。我们还是选择使用上篇文章中介绍的查询手机号码归属地的Web service,它的WSDL为http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
1)新建Android工程,引入上面下载的ksoap2-android类库
      Android工程的创建就不多说了,主要想说明的是如何向Android工程中添加第三方jar包。当然,添加第3方jar的方式有多种,我个人比较喜欢用下面这种方式,即先将第三方jar包拷贝到工程某个目录下,再将其加入到工程的Build Path中
      例如,我创建的Android工程名为WSClient,在工程名上点击右键,新建一个Folder(目录或文件夹),名为libs,然后将ksoap2-android类库拷贝到libs目录中,如下图所示:
            
      接着,在jar包ksoap2-android-assembly-2.4-jar-with-dependencies.jar上点击右键,依次选择“Build Path”-“Add to Build Path”。再在工程名上点击右键,依次选择“Build Path”-“Config Build Path...”,将看到如下所示界面:
     
选中ksoap2 jar包前面的选项框,点击OK,则完成了ksoap2 jar包的添加(说明:在Android工程中,添加其它jar包的方法完全一样,操作一两遍后,你会发现其实很简单的)。
2)编写布局文件res/layout/main.xml      

[html] view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:paddingTop="5dip"  
  7.     android:paddingLeft="5dip"  
  8.     android:paddingRight="5dip"  
  9.     >  
  10.     <TextView  
  11.         android:layout_width="fill_parent"   
  12.         android:layout_height="wrap_content"   
  13.         android:text="手机号码(段):"  
  14.     />  
  15.     <EditText android:id="@+id/phone_sec"  
  16.         android:layout_width="fill_parent"  
  17.         android:layout_height="wrap_content"  
  18.         android:inputType="textPhonetic"  
  19.         android:singleLine="true"  
  20.         android:hint="例如:1398547"  
  21.     />  
  22.     <Button android:id="@+id/query_btn"  
  23.         android:layout_width="wrap_content"  
  24.         android:layout_height="wrap_content"  
  25.         android:layout_gravity="right"  
  26.         android:text="查询"  
  27.     />  
  28.     <TextView android:id="@+id/result_text"  
  29.         android:layout_width="wrap_content"   
  30.         android:layout_height="wrap_content"   
  31.         android:layout_gravity="center_horizontal|center_vertical"  
  32.     />  
  33. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="5dip"
android:paddingLeft="5dip"
android:paddingRight="5dip"
>
<TextView
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
android:text="手机号码(段):"
/>
<EditText android:id="@+id/phone_sec"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textPhonetic"
android:singleLine="true"
android:hint="例如:1398547"
/>
<Button android:id="@+id/query_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="查询"
/>
<TextView android:id="@+id/result_text"
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:layout_gravity="center_horizontal|center_vertical"
/>
</LinearLayout>

3)编写MainActivity类

[java] view plain copy print ?
  1. package com.liufeng.ws.activity;  
  2.   
  3. import org.ksoap2.SoapEnvelope;  
  4. import org.ksoap2.serialization.SoapObject;  
  5. import org.ksoap2.serialization.SoapSerializationEnvelope;  
  6. import org.ksoap2.transport.HttpTransportSE;  
  7.   
  8. import android.app.Activity;  
  9. import android.os.Bundle;  
  10. import android.view.View;  
  11. import android.view.View.OnClickListener;  
  12. import android.widget.Button;  
  13. import android.widget.EditText;  
  14. import android.widget.TextView;  
  15.   
  16. /** 
  17.  * Android平台调用WebService(手机号码归属地查询) 
  18.  *  
  19.  * @author liufeng 
  20.  * @date 2011-05-18 
  21.  */  
  22. public class MainActivity extends Activity {  
  23.     private EditText phoneSecEditText;  
  24.     private TextView resultView;  
  25.     private Button queryButton;  
  26.   
  27.     @Override  
  28.     public void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.main);  
  31.   
  32.         phoneSecEditText = (EditText) findViewById(R.id.phone_sec);  
  33.         resultView = (TextView) findViewById(R.id.result_text);  
  34.         queryButton = (Button) findViewById(R.id.query_btn);  
  35.   
  36.         queryButton.setOnClickListener(new OnClickListener() {  
  37.             @Override  
  38.             public void onClick(View v) {  
  39.                 // 手机号码(段)   
  40.                 String phoneSec = phoneSecEditText.getText().toString().trim();  
  41.                 // 简单判断用户输入的手机号码(段)是否合法   
  42.                 if ("".equals(phoneSec) || phoneSec.length() < 7) {  
  43.                     // 给出错误提示   
  44.                     phoneSecEditText.setError("您输入的手机号码(段)有误!");  
  45.                     phoneSecEditText.requestFocus();  
  46.                     // 将显示查询结果的TextView清空   
  47.                     resultView.setText("");  
  48.                     return;  
  49.                 }  
  50.                 // 查询手机号码(段)信息   
  51.                 getRemoteInfo(phoneSec);  
  52.             }  
  53.         });  
  54.     }  
  55.   
  56.     /** 
  57.      * 手机号段归属地查询 
  58.      *  
  59.      * @param phoneSec 手机号段 
  60.      */  
  61.     public void getRemoteInfo(String phoneSec) {  
  62.         // 命名空间   
  63.         String nameSpace = "http://WebXml.com.cn/";  
  64.         // 调用的方法名称   
  65.         String methodName = "getMobileCodeInfo";  
  66.         // EndPoint   
  67.         String endPoint = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx";  
  68.         // SOAP Action   
  69.         String soapAction = "http://WebXml.com.cn/getMobileCodeInfo";  
  70.   
  71.         // 指定WebService的命名空间和调用的方法名   
  72.         SoapObject rpc = new SoapObject(nameSpace, methodName);  
  73.   
  74.         // 设置需调用WebService接口需要传入的两个参数mobileCode、userId   
  75.         rpc.addProperty("mobileCode", phoneSec);  
  76.         rpc.addProperty("userId""");  
  77.   
  78.         // 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本   
  79.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);  
  80.   
  81.         envelope.bodyOut = rpc;  
  82.         // 设置是否调用的是dotNet开发的WebService   
  83.         envelope.dotNet = true;  
  84.         // 等价于envelope.bodyOut = rpc;   
  85.         envelope.setOutputSoapObject(rpc);  
  86.   
  87.         HttpTransportSE transport = new HttpTransportSE(endPoint);  
  88.         try {  
  89.             // 调用WebService   
  90.             transport.call(soapAction, envelope);  
  91.         } catch (Exception e) {  
  92.             e.printStackTrace();  
  93.         }  
  94.   
  95.         // 获取返回的数据   
  96.         SoapObject object = (SoapObject) envelope.bodyIn;  
  97.         // 获取返回的结果   
  98.         String result = object.getProperty(0).toString();  
  99.   
  100.         // 将WebService返回的结果显示在TextView中   
  101.         resultView.setText(result);  
  102.     }  
  103. }  
package com.liufeng.ws.activity;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
/**
* Android平台调用WebService(手机号码归属地查询)
* 
* @author liufeng
* @date 2011-05-18
*/
public class MainActivity extends Activity {
private EditText phoneSecEditText;
private TextView resultView;
private Button queryButton;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
phoneSecEditText = (EditText) findViewById(R.id.phone_sec);
resultView = (TextView) findViewById(R.id.result_text);
queryButton = (Button) findViewById(R.id.query_btn);
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;
}
// 查询手机号码(段)信息
getRemoteInfo(phoneSec);
}
});
}
/**
* 手机号段归属地查询
* 
* @param phoneSec 手机号段
*/
public void getRemoteInfo(String phoneSec) {
// 命名空间
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", phoneSec);
rpc.addProperty("userId", "");
// 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);
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 e) {
e.printStackTrace();
}
// 获取返回的数据
SoapObject object = (SoapObject) envelope.bodyIn;
// 获取返回的结果
String result = object.getProperty(0).toString();
// 将WebService返回的结果显示在TextView中
resultView.setText(result);
}
}

讲解:
      注意点1:如代码中的62-69行所示,调用Web Service之前你需要先弄清楚这4个的值分别是什么:命名空间、调用的方法名称、EndPoint和SOAP Action。当在浏览器中访问WSDL时,很容易得知命名空间、调用的方法名称是什么(不明白的请看上篇文章),至于EndPoint通常是将WSDL地址末尾的"?wsdl"去除后剩余的部分;而SOAP Action通常为命名空间 + 调用的方法名称。
      注意点2:75-76行是设置调用WebService接口方法需要传入的参数。(在WSDL中能够看到调用方法需要传入的参数个数及参数名称,在设置参数时最好指明每一个传入参数的名称,如本例中的mobileCode、userId。网上有些资料说在需要传入多个参数时,只要多个参数的顺序与WSDL中参数出现的顺序一致即可,名称并不需要和WSDL中的一致,但实际测试发现,大多数情况下并不可行!
      例如下面图版上显示的WSDL片段,调用该Web Service的checkUserInfo方法就需要传入4个参数,参数名称分别为:in0、in1、in2和in3。
           

      注意点3也许你会对第100行代码产生疑惑,为什么要用object.getProperty("getMobileCodeInfoResult")来取得调用结果?那是因为WSDL中明确告诉了返回结果是String数组,它的名称为getDatabaseInfoResult,WSDL中的描述如下:
           <s:elementminOccurs="0" maxOccurs="1" name="getDatabaseInfoResult" type="tns:ArrayOfString" /> 
     
本例中调用WebService后返回的结果如下所示:
           <?xml version="1.0" encoding="utf-8"?> 
            
<string xmlns="http://WebXml.com.cn/">1398547:贵州 贵阳 贵州移动黔中游卡</string>
咦,这里明明返回的是xml格式的内容,为什么我们不需要通过解析xml来获取我们需要的内容呢?其实如果你仔细看代码中的96-97行并不难发现:
            // 获取返回的数据
            SoapObject object = (SoapObject) envelope.bodyIn;

ksoap2能够将返回的xml转换成SoapObject对象,然后我们就可以通过操作对象的方式来获取需要的数据了。
      注意点4同样还是第100行代码。从有些WSDL中我们并不能得知返回结果的名称(如本例中的getMobileCodeInfoResult),那又该如何调用呢?其实上面已经暗示了这个问题:当通过第97行代码获取返回结果并将其转换成SoapObject对象后,如果你并不知道通过该对象的哪个属性来取值,你完全可以调用对象的toString()方法来查看返回的内容,例如将本例中的第100行代码替换成:
            // 获取返回的结果
             String result = object.toString();

这样得到的返回结果为:
     
注意看括号{}里面的内容是一个键-值对形式,以等号=分隔,我们正是通过=号左边的“getMobileCodeInfoResult”来获取右边的查询结果。
      其实在不知道返回结果名称时(如本例的100行,我们并不知道返回结果中有属性getMobileCodeInfoResult),有一种更为简便的方法,直接通过索引下标来获取属性值,也就是将第100行代码替换为:
            String result = object.getProperty(0).toString();
      注意点5:本例中只返回了一个值,但有些WebService会返回多个值该怎么获取?获取方法与本例完全一样,只是需要注意的是如果是返回多个值,通过第100代码object.getProperty(0);得到的可能仍然是一个SoapObject。不断地调用getProperty()方法;总能得到你想要的全部结果。
      注意点6:在调用某些WebService时,可能会报一些异常,但你又发现除了调用的WebService不同之外,其它地方的写法和我的完全一样,这又该如何解决呢?尝试改变第79代码中SOAP的版本号,可以分别尝试使用SoapEnvelope.VER10、SoapEnvelope.VER11、SoapEnvelope.VER12这样三个值。另外,在调用某些WebService时,可能在第91行代码中,调用WebService时并不需要传入soapAction,将其置为null即可。
4)在AndroidManifest.xml中配置添加访问网络的权限(千万别忘记!!!)      

[html] view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="com.liufeng.ws.activity"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  7.         <activity android:name=".MainActivity" android:label="@string/app_name">  
  8.             <intent-filter>  
  9.                 <action android:name="android.intent.action.MAIN" />  
  10.                 <category android:name="android.intent.category.LAUNCHER" />  
  11.             </intent-filter>  
  12.         </activity>  
  13.     </application>  
  14.   
  15.     <uses-sdk android:minSdkVersion="4" />  
  16.     <!-- 访问网络的权限 -->  
  17.     <uses-permission android:name="android.permission.INTERNET" />   
  18. </manifest>   
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.liufeng.ws.activity"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
<!-- 访问网络的权限 -->
<uses-permission android:name="android.permission.INTERNET" /> 
</manifest> 

5)运行结果
     

这篇关于[019] Android平台调用WebService详解 .的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1063149

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)