使用Web Service进行网络编程

Android应用通常都是运行在手机平台上,手机系统的硬件资源是有限的,不管是存储能力还是计算能力都有限,在Android系统上开发、运行一些单用户、小型应用是可能的,

但对于需要进行大量的数据处理、复杂计算的应用,还是只能部署在远程服务器上,Android应用将只是充当这些应用的客户端。

为了让Android应用与远程服务器之间进行交互,可以借助子Java的RMI技术,但这要求远程服务器程序必须采用Java实现;也可以借助于CORBA技术,但这种技术显得过于复杂,除此之外,Web Service是一种不错的选择。

1.Web Service 平台概述

Web Service平台主要涉及的技术有SOAP(Simple Object Access Protocol,简单对象访问协议),WSDL( Web Service Description Language,Web Service描述语言),UDDI(UniversalDescription, Description and Integration,统一描述、发现和整合协议)。

1.1. SOAP (简单对象访问协议)

SOAP (SimpleObject Access Protocol,简单对象访问协议)是一种具有扩展性的;XML消息协议。SOAP允许一个应用程序向另一个应用程序发送XML消息,SOAP消息是从SOAP发送者传至SOAP接收者的单路消息,任何应用程序均可作为发送者或接收者。SOAP仅定义消息结构和消息处理的协议,与底层的传输协议独立。因此,SOAP协议能通过HTTP, JMS 或SMTP协议传输。

SOAP依赖于XML文档来构建,一条SOAP消息就是一份特定的XML文档,SOAP消息包合如下三个主要元素:

Ø必需的<Envelope.../>根元素,SOAP消息对应的XML文档以该元素作为根元素。

Ø可选的<Header../>元素,包含SOAP消息的头信息。

Ø必需的<Body../>元素,包含所有的调用和响应信息。

就目前的SOAP消息的结构来看,<Envelope.../>根元素的通常只能包含两个子元素,第一个子元素是可选的<Header../>元素,第二个子元素是必需的<Body../>元素。

1.2. WSDL(WebService描述语言)

WSDL (WebService Description Language, Web Service描述语言) 使用 XML描述Web Service,包括访问和使用WebService所必需的信息,定义该Web Service的位置、功能及如何通信等描述信息。

一般来说,只要调用者能够获取WebService对应的WSDL,就可以从中了解它所提供的服务及如何调用Web Service。因为一份WSDL文件淸晰地定义了三个方面的内容。

ØWHAT部分:用于定义Web Service所提供的操作(或方法),也就是Web Service能做些什么。由WSDL中的<types. ../>、<message…/>、和<portTyp…/>元素定义。

ØHOW部分:用于定义如何访问Web Service,包括数据格式详情和访问Web Service操作的必要协议。也就是定义了如何访问Web Service。

ØWHERE部分:用于定义Web Service位于何处,如何使用特定协议决定的网络地址(如URL)指定。该部分使用<service.../>元素定义,可在WSDL文件的最后部分看到<service.../>元素。

一份WSDL文档通常可分为两个部分:

Ø第一个部分定义了服务接口,它在WSDL中由<message.../>元素和<portType…/>两个元素组成,其中<message.../>元素定义了操作的交互方式。而<portType…/>元素里则可包含任意数量的<operation.../>元素,每个<operation.../>元素代表一个允许远程调用的操作(即方法)。

ØWSDL的第二个部分定义了服务实现,它在WSDL中由<binding.../>元素和 <service.../>两个元素组成,其中<binding.../>定义使用特定的通信协议、数据编码模型和底层通信协议,将Web Service服务接口定义映射到具体实现。而 <service.../>元素则包含一系列的<portType…/>子元素,< portType.../>子元素将会把绑定机制、服务访问协议和端点地址结合在一起。

1.3. UDDI(统一描述、发现和整合协议)

UDDI (UniversalDescription, Description and Integration,统一描述、发现和整合协议)是一套信息注册规范,它具有如下特点:

Ø基于Web。

Ø分布式。

UDDI包括一组允许企业向外注册WebService、以使其他企业发现访问的实现标准。 UDDI的核心组件是UDDI注册中心,它使用XML文件来描述企业及其提供的Web Service, 通过使用UDDI, Web Service提供者可以对外注册Web Service,从而允许其他企业来调用该企业注册的Web Service。Web Service提供者通过UDDI注册中心的Web界面,将它所供的Web Service的信息加入UDDI注册中心,该Web Service就可以被发现和调用。

Web Service使用者也通过UDDI注册中心査找、发现自己所需的服务。当Web Service使用者找到自己所需的服务之后,可以将自己绑定到指定的Web Service提供者,再根据该 Web Service对应的WSDL文档来调用对方的服务。

2. 使用Android启用调用Web Service

Java本身提供了丰富的WebService支持,比如Sun公司制定的JAX-WS 2规范,还有 Apache开源组织所提供的Axis1、Axis2、CXF等,这些技术不仅可以用于非常方便地对外提供Web Service,也可以用于简化Web Service的客户端编程。

对于手机等小型设备而言,它们的计算资源、存储资源都十分有限,因此Android应用不大可能需要对外提供Web Service,Android应用通常只是充当Web Service的客户端,调用远程Web Serice。

Google为Android平台开发WebService客户端提供了 ksoap2-android项目,但这个项目并未直接集成在Android平台中,还需要开发人员自行下载。

2.1为Android应用增加ksoap2-android支持的下步骤。

1)登录http://code.google.eom/p/ksoap2-android/站点,该站站点有介绍下载ksoap2-androi项目的方法。

2)下载 ksoap2-android项目的 ksoap2-android-assembly-3.0.0-RC4.jar-with-dependencies. jar包。

3)将下载的jar包放到android项目的libs目录下即可。

为Android项目添加了ksoap2-android包之后,接下来借助   ksoap2-android项目来调用WebService所暴露出来的操作。

2.2使用ksoap2-android调用Web Service操作的步驟如下:

1)创建HttpTransportSE对象,该对象用于调用WebService操作。

2)创建 SoapSerializationEnvelope对象。

提示:从名称来看SoapSerializationEnvelope代表一个SOAP消息封包;但ksoap2-android项目对 SoapSerializationEnvelope的处理比较特殊,它是HttpTransportSE调用WebService时信息的载体;客户端需要传入的参数,需要通过SoapSerializationEnvelope对象的bodyOut属性传给服务器;服务器响应生成的SOAP消息也通过该对象的body  Out属性来获取。

3)创建SoapObject对象,创建该对象时需要传入所要调用WebService的命名空间、Web Service方法名。

4)如果有参数需要传给Web Service服务器端,调用SoapObject对象的addProperty(Stringname,Object value)方法来设置参数,该方法的name参数指定参数名;value参数指定参数值。

5)调用SoapSerializationEnvelope的setOutputSoapObject()方法,或者直接对bodyOut属性赋值,将前两步创逆的SoapObject对象设为SoapSerializationEnvelope的传出SOAP消息体。

6)调用对象的call()方法,并以SoapSerializationEnvelope作为参数调用远程WebService。

7)调用完成后,访问SoapSerializationEnvelope对象的bodyln属性,该属性返回一个SoapObject对象,该对象就代表了Web Service的返回消息。解析该SoapObject对象,即可获取调用Web Service的返回值。

2.3实例:调用Web Service实现天气预报

在开发天气预报的Android应用之前,首先需要找到一个可以对外提供天气预报的Web Service,通过搜索,发现http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx站点 可以对外提供天气预报的WebService,因此程序将会调用该站点的Web Service来实现天气预报。

为了让应用界面更加美观,可以访问http://www.webxml.com.cn/images/weather.zip下载各种天气图标,可以使用这些天气图标来美化应用。

本程序主要需要调用如下三个Web Seivice操作:

 获取省份。

 根据省份获取城市。

 根据城市获取天气。

为了调用上面的三个WebService应用程序提供如下工具类。

publicclass WebServiceUtil

{

// 定义Web Service的命名空间

staticfinal StringSERVICE_NS ="http://WebXml.com.cn/";

// 定义Web Service提供服务的URL

staticfinal StringSERVICE_URL =

"http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx";

// 调用远程Web Service获取省份列表

publicstatic List<String> getProvinceList()

{

// 调用的方法

final String methodName ="getRegionProvince";

// 创建HttpTransportSE传输对象

final HttpTransportSE ht =new HttpTransportSE(SERVICE_URL);

ht.debug =true;

// 使用SOAP1.1协议创建Envelop对象

final SoapSerializationEnvelope envelope =

new SoapSerializationEnvelope(SoapEnvelope.VER11);

// 实例化SoapObject对象

SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);

envelope.bodyOut = soapObject;

// 设置与.Net提供的Web Service保持较好的兼容性

envelope.dotNet =true;

FutureTask<List<String>> task = new FutureTask<List<String>>(

new Callable<List<String>>()

{

@Override

public List<String> call()

throws Exception

{

// 调用Web Service

ht.call(SERVICE_NS + methodName, envelope);

if (envelope.getResponse() !=null)

{

// 获取服务器响应返回的SOAP消息

SoapObject result = (SoapObject) envelope.bodyIn;

SoapObject detail = (SoapObject) result.getProperty(

methodName + "Result");

// 解析服务器响应的SOAP消息。

returnparseProvinceOrCity(detail);

}

returnnull;

}

});

new Thread(task).start();

try

{

return task.get();

}

catch (Exception e)

{

e.printStackTrace();

}

returnnull;

}

// 根据省份获取城市列表

publicstatic List<String> getCityListByProvince(String province)

{

// 调用的方法

final String methodName ="getSupportCityString";

// 创建HttpTransportSE传输对象

final HttpTransportSE ht =new HttpTransportSE(SERVICE_URL);

ht.debug =true;

// 实例化SoapObject对象

SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);

// 添加一个请求参数

soapObject.addProperty("theRegionCode", province);

// 使用SOAP1.1协议创建Envelop对象

final SoapSerializationEnvelope envelope =

new SoapSerializationEnvelope(SoapEnvelope.VER11);

envelope.bodyOut = soapObject;

// 设置与.Net提供的Web Service保持较好的兼容性

envelope.dotNet =true;

FutureTask<List<String>> task = new FutureTask<List<String>>(

new Callable<List<String>>()

{

@Override

public List<String> call()

throws Exception

{

// 调用Web Service

ht.call(SERVICE_NS + methodName, envelope);

if (envelope.getResponse() !=null)

{

// 获取服务器响应返回的SOAP消息

SoapObject result = (SoapObject) envelope.bodyIn;

SoapObject detail = (SoapObject) result.getProperty(

methodName + "Result");

// 解析服务器响应的SOAP消息。

returnparseProvinceOrCity(detail);

}

returnnull;

}

});

new Thread(task).start();

try

{

return task.get();

}

catch (Exception e)

{

e.printStackTrace();

}

returnnull;

}

privatestatic List<String> parseProvinceOrCity(SoapObject detail)

{

ArrayList<String> result = new ArrayList<String>();

for (int i = 0; i < detail.getPropertyCount(); i++)

{

// 解析出每个省份

result.add(detail.getProperty(i).toString().split(",")[0]);

}

return result;

}

publicstatic SoapObject getWeatherByCity(String cityName)

{

final String methodName ="getWeather";

final HttpTransportSE ht =new HttpTransportSE(SERVICE_URL);

ht.debug =true;

nbsp;      final SoapSerializationEnvelope envelope =

new SoapSerializationEnvelope(SoapEnvelope.VER11);

SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);

soapObject.addProperty("theCityCode", cityName);

envelope.bodyOut = soapObject;

// 设置与.Net提供的Web Service保持较好的兼容性

envelope.dotNet =true;

FutureTask<SoapObject> task = new FutureTask<SoapObject>(

new Callable<SoapObject>()

{

@Override

public SoapObject call()

throws Exception

{

ht.call(SERVICE_NS + methodName, envelope);

SoapObject result = (SoapObject) envelope.bodyIn;

SoapObject detail = (SoapObject) result.getProperty(

methodName + "Result");

return detail;

}

});

new Thread(task).start();

try

{

return task.get();

}

catch (Exception e)

{

e.printStackTrace();

}

returnnull;

}

}

上面的程序调用Web Service的方法还是没有改变,前面两个方法——获取系统支持的省份列表,根据省份获取城市列表——将远程Web Service返回的数据解析成List<String>后返回,这样方便Android应用使用。由于第二个方法需要返回的数据量较多,所以程序直接返回了 SoapObject 对象。

上面的程序中调用WebService时将SoapSerializationEnvelope对象的dotNet属性设为 true——因为上面这个网站是通过.NET来对外提供WebService的,因此需要将 SoapSerializationEnvelope对象的 dotNet 属性设为 true。

有了上面的调用WebService的工具类之后,接下来可以在Activity中使用该工具类来获取天气服务信息。该Activity使用了两个Spinner让用户选择省份、城市,当用户选择指定城市后,系统将会加载该程序的天气信息。

该程序的界面布局代码如下:

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="wrap_content">

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:hint="@string/province"/>

<!-- 让用户选择省份的Spinner -->

<Spinner

android:id="@+id/province"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:hint="@string/city"/>

<!-- 让用户选择城市的Spinner -->

<Spinner

android:id="@+id/city"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

</LinearLayout>

<TextView

android:id="@+id/weatherCurrent"

android:layout_width="fill_parent"

android:layout_height="wrap_content"/>

<!-- 显示今天天气的图片和文本框 -->

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content">

<ImageView

android:id="@+id/todayWhIcon1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<ImageView

android:id="@+id/todayWhIcon2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<TextView

android:id="@+id/weatherToday"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_weight="1"/>

</LinearLayout>

<!-- 显示明天天气的图片和文本框 -->

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content">

<ImageView

android:id="@+id/tomorrowWhIcon1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<ImageView

android:id="@+id/tomorrowWhIcon2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<TextView

android:id="@+id/weatherTomorrow"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_weight="1"/>

</LinearLayout>

<!-- 显示后天天气的图片和文本框 -->

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content">

<ImageView

android:id="@+id/afterdayWhIcon1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<ImageView

android:id="@+id/afterdayWhIcon2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<TextView

android:id="@+id/weatherAfterday"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_weight="1"/>

</LinearLayout>

</LinearLayout>

当程序加载时,程序会调用WebServiceUtil的getProvinceList()方法来获取省份列表,并 使用第一个Spinner加载、显示所有省份:当用户改变选择了省份之后,程序会调用 WebServiceUtil的getCityListByProvince(Stringprovince)方法来获取该省份的全部城市:当用户改变选择城市之后,程序会调用WebServiceUtil的getWeatherByCity(StringcityName)方法 获取该城市的天气。

该Activity的代码如下:

publicclass GetWeatherextends Activity

{

private SpinnerprovinceSpinner;

private SpinnercitySpinner;

private ImageViewtodayWhIcon1;

private ImageViewtodayWhIcon2;

private TextViewtextWeatherToday;

private ImageViewtomorrowWhIcon1;

private ImageViewtomorrowWhIcon2;

private TextViewtextWeatherTomorrow;

private ImageViewafterdayWhIcon1;

private ImageViewafterdayWhIcon2;

private TextViewtextWeatherAfterday;

private TextViewtextWeatherCurrent;

@Override

publicvoid onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

todayWhIcon1 = (ImageView) findViewById(R.id.todayWhIcon1);

todayWhIcon2 = (ImageView) findViewById(R.id.todayWhIcon2);

textWeatherToday = (TextView) findViewById(R.id.weatherToday);

tomorrowWhIcon1 = (ImageView) findViewById(R.id.tomorrowWhIcon1);

tomorrowWhIcon2 = (ImageView) findViewById(R.id.tomorrowWhIcon2);

textWeatherTomorrow = (TextView) findViewById(R.id.weatherTomorrow);

afterdayWhIcon1 = (ImageView) findViewById(R.id.afterdayWhIcon1);

afterdayWhIcon2 = (ImageView) findViewById(R.id.afterdayWhIcon2);

textWeatherAfterday = (TextView) findViewById(R.id.weatherAfterday);

textWeatherCurrent = (TextView) findViewById(R.id.weatherCurrent);

// 获取程序界面中选择省份、城市的Spinner组件

provinceSpinner = (Spinner) findViewById(R.id.province);

citySpinner = (Spinner) findViewById(R.id.city);

// 调用远程Web Service获取省份列表

List<String> provinces = WebServiceUtil.getProvinceList();

ListAdapter adapter = new ListAdapter(this, provinces);

// 使用Spinner显示省份列表

provinceSpinner.setAdapter(adapter);

// 当省份Spinner的选择项被改变时

provinceSpinner.setOnItemSelectedListener(new OnItemSelectedListener()

{

@Override

publicvoid onItemSelected(AdapterView<?> source, View parent,

int position,long id)

{

List<String> cities = WebServiceUtil

.getCityListByProvince(provinceSpinner.getSelectedItem()

.toString());

ListAdapter cityAdapter = new ListAdapter(GetWeather.this,

cities);

// 使用Spinner显示城市列表

citySpinner.setAdapter(cityAdapter);

}

@Override

publicvoid onNothingSelected(AdapterView<?> arg0)

{

}

});

// 当城市Spinner的选择项被改变时

citySpinner.setOnItemSelectedListener(new OnItemSelectedListener()

{

@Override

publicvoid onItemSelected(AdapterView<?> source, View parent,

int position,long id)

{

showWeather(citySpinner.getSelectedItem().toString());

}

@Override

publicvoid onNothingSelected(AdapterView<?> arg0)

{

}

});

}

privatevoid showWeather(String city)

{

String weatherToday = null;

String weatherTomorrow = null;

String weatherAfterday = null;

String weatherCurrent = null;

int iconToday[] =newint[2];

int iconTomorrow[] =newint[2];

int iconAfterday[] =newint[2];

// 获取远程Web Service返回的对象

SoapObject detail = WebServiceUtil.getWeatherByCity(city);

// 获取天气实况

weatherCurrent = detail.getProperty(4).toString();

// 解析今天的天气情况

String date = detail.getProperty(7).toString();

weatherToday = "今天:" + date.split(" ")[0];

weatherToday = weatherToday + "\n天气:" + date.split(" ")[1];

weatherToday = weatherToday + "\n气温:"

+ detail.getProperty(8).toString();

weatherToday = weatherToday + "\n风力:"

+ detail.getProperty(9).toString() + "\n";

iconToday[0] = parseIcon(detail.getProperty(10).toString());

iconToday[1] = parseIcon(detail.getProperty(11).toString());

// 解析明天的天气情况

date = detail.getProperty(12).toString();

weatherTomorrow = "明天:" + date.split(" ")[0];

weatherTomorrow = weatherTomorrow + "\n天气:" + date.split(" ")[1];

weatherTomorrow = weatherTomorrow + "\n气温:"

+ detail.getProperty(13).toString();

weatherTomorrow = weatherTomorrow + "\n风力:"

+ detail.getProperty(14).toString() + "\n";

iconTomorrow[0] = parseIcon(detail.getProperty(15).toString());

iconTomorrow[1] = parseIcon(detail.getProperty(16).toString());

// 解析后天的天气情况

date = detail.getProperty(17).toString();

weatherAfterday = "后天:" + date.split(" ")[0];

weatherAfterday = weatherAfterday + "\n天气:" + date.split(" ")[1];

weatherAfterday = weatherAfterday + "\n气温:"

+ detail.getProperty(18).toString();

weatherAfterday = weatherAfterday + "\n风力:"

+ detail.getProperty(19).toString() + "\n";

iconAfterday[0] = parseIcon(detail.getProperty(20).toString());

iconAfterday[1] = parseIcon(detail.getProperty(21).toString());

// 更新当天的天气实况

textWeatherCurrent.setText(weatherCurrent);

// 更新显示今天天气的图标和文本框

textWeatherToday.setText(weatherToday);

todayWhIcon1.setImageResource(iconToday[0]);

todayWhIcon2.setImageResource(iconToday[1]);

// 更新显示明天天气的图标和文本框

textWeatherTomorrow.setText(weatherTomorrow);

tomorrowWhIcon1.setImageResource(iconTomorrow[0]);

tomorrowWhIcon2.setImageResource(iconTomorrow[1]);

// 更新显示后天天气的图标和文本框

textWeatherAfterday.setText(weatherAfterday);

afterdayWhIcon1.setImageResource(iconAfterday[0]);

afterdayWhIcon2.setImageResource(iconAfterday[1]);

}

// 工具方法,该方法负责把返回的天气图标字符串,转换为程序的图片资源ID。

privateint parseIcon(String strIcon)

{

if (strIcon ==null)

return -1;

if ("0.gif".equals(strIcon))

return R.drawable.a_0;

if ("1.gif".equals(strIcon))

return R.drawable.a_1;

if ("2.gif".equals(strIcon))

return R.drawable.a_2;

if ("3.gif".equals(strIcon))

return R.drawable.a_3;

if ("4.gif".equals(strIcon))

return R.drawable.a_4;

if ("5.gif".equals(strIcon))

return R.drawable.a_5;

if ("6.gif".equals(strIcon))

return R.drawable.a_6;

if ("7.gif".equals(strIcon))

return R.drawable.a_7;

if ("8.gif".equals(strIcon))

return R.drawable.a_8;

if ("9.gif".equals(strIcon))

return R.drawable.a_9;

if ("10.gif".equals(strIcon))

return R.drawable.a_10;

if ("11.gif".equals(strIcon))

return R.drawable.a_11;

if ("12.gif".equals(strIcon))

return R.drawable.a_12;

if ("13.gif".equals(strIcon))

return R.drawable.a_13;

if ("14.gif".equals(strIcon))

return R.drawable.a_14;

if ("15.gif".equals(strIcon))

return R.drawable.a_15;

if ("16.gif".equals(strIcon))

return R.drawable.a_16;

if ("17.gif".equals(strIcon))

return R.drawable.a_17;

if ("18.gif".equals(strIcon))

return R.drawable.a_18;

if ("19.gif".equals(strIcon))

return R.drawable.a_19;

if ("20.gif".equals(strIcon))

return R.drawable.a_20;

if ("21.gif".equals(strIcon))

return R.drawable.a_21;

if ("22.gif".equals(strIcon))

return R.drawable.a_22;

if ("23.gif".equals(strIcon))

return R.drawable.a_23;

if ("24.gif".equals(strIcon))

return R.drawable.a_24;

if ("25.gif".equals(strIcon))

return R.drawable.a_25;

if ("26.gif".equals(strIcon))

return R.drawable.a_26;

if ("27.gif".equals(strIcon))

return R.drawable.a_27;

if ("28.gif".equals(strIcon))

return R.drawable.a_28;

if ("29.gif".equals(strIcon))

return R.drawable.a_29;

if ("30.gif".equals(strIcon))

return R.drawable.a_30;

if ("31.gif".equals(strIcon))

return R.drawable.a_31;

return 0;

}

上面的Activity代码己经不再涉及调用WebService的代码了,只是简单地调用Web Service操作,解析Web Service返回的SOAP消息包,并把SOAP消息包中的数据显示出来。

未完待续..........

Android开发之使用Web Service进行网络编程相关推荐

  1. 软件开发全套视频教程汇总(javaSE,javaEE,linux,android开发,C# ,web前端,大数据云计算,数据挖掘,web前端,php开发,UI设计,C++开发,3D视频)

    软件开发全套视频教程汇总(javaSE,javaEE,linux,android开发,C# ,web前端,大数据云计算,数据挖掘,web前端,php开发,UI设计,C++开发,3D视频) 这是我以前学 ...

  2. Android开发面试:架构设计和网络知识答案精解

    目录 架构设计 编程思想 六大设计原则 重构-Code Smell AOP 设计模式 创建型5个 行为型11个 结构型7个 编程范式 MVC MVP MVVM MVI 模块化 组件化 插件化.热修复 ...

  3. Android开发之如何保证Service不被杀掉(broadcast+system/app)

    Android开发之如何保证Service不被杀掉(broadcast+system/app) 序言 最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运行,不管用户作出什么操作 ...

  4. JSP高校信息管理系统myeclipse开发sql数据库web结构计算机java编程

    一.源码特点   JSP 高校信息管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,,系统主要采用B/S模式开发. JSP高校信息管理系统my ...

  5. JSP众筹管理系统myeclipse开发sql数据库web结构计算机java编程

    一.源码特点   JSP 众筹管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发. JSP众筹管理系统myecli ...

  6. 迅为-i.MX6ULL开发板-QT实战项目DHT11网络编程实战练习(一)

    迅为-i.MX6ULL开发板-QT实战项目DHT11&网络编程实战练习(一) 发布时间:2021-7-2 09:49    发布者:落风 |编辑 文章目录1 项目前准备2 软件流程图3 Lin ...

  7. 【Linux服务器开发系列】详解多线程网络编程丨百分百干货分享丨学到就是赚到

    90分钟搞懂多线程网络编程模型 1. 网络编程关注的问题 2. 网络编程的几种模型reactor,one loop per thread及其变种 3. skynet,redis,nginx,memca ...

  8. JSP婚纱预约管理系统myeclipse开发sql数据库web结构计算机java编程

    一.源码特点      JSP 婚纱预约管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发. JSP婚纱预约管理系 ...

  9. java snmp全面开发解决方案(web service snmp网关、代理snmp网关、网络拓扑发现、SNMP数据采集等)...

    ObjectSNMP是一个面向对象的SNMP开发组件,与关系数据库流行的O-R Mapping技术类似,实现了Object到SNMP MIB的操作映射(简称O-M Mapping),系统提供了Java ...

最新文章

  1. clientdataset 过滤 in_天心大风量亚高效过滤器
  2. 引入 ServletContextListener @Autowired null 解决办法
  3. 使用Python增加csdn的访问量
  4. Java 设计模式——外观模式
  5. 目前电子计算机已经发展到______阶段,《全国高校计算机联合考试广西考区一级笔试试题卷.doc...
  6. 不属于前后端分离的Vue+Django的例子
  7. 产品开发管理之流程和体系(总篇)
  8. impdp使用network_link导入
  9. struts2中struts:iterator标签的使用
  10. python pdf转txt_Python之pdf转txt
  11. 计算机操作系统考试习题
  12. 读懂才会用 : 瞅瞅Redis的epoll模型
  13. 配置catalina.out的日志格式
  14. 服务器linux攻击方法,Linux操作系统中实现DDOS攻击的方法
  15. 插入排序(直接插入排序,折半插入排序,希尔排序)
  16. (附源码)Python二手电脑商城 毕业设计 251713
  17. 电脑公司GHOST WIN7 SP1 2011装机旗舰版
  18. mysql导入表空间太慢_Oracle 11g统计表空间使用率很慢
  19. 又一优雅的 K8s 开源桌面管理工具 - Monokle
  20. 11月1日到11月14日的成果

热门文章

  1. 微信开发JS接口安全域名 网页授权域名 业务域名
  2. mysql 设置 utc_关于时间:MySQL应该将其时区设置为UTC吗?
  3. 彩色空间HSV|RGB|灰度图的理解与OpenCV中的转换【DataWhale琐碎知识点】
  4. 软件技术java开发方向,22年最新
  5. AURIX Development Studio软件介绍
  6. [mysql] ERROR 2002 (HY000): Can‘t connect to local MySQL server...问题解决
  7. 【PC工具】压缩包密码破解工具,暴力破解压缩包密码,zip密码获取
  8. URL Schemes 程序跳转
  9. 计算机应用word单元测试2,(计算机应用基本技能测试二.doc
  10. WEB在线客服系统(websocket+Golang)