Как вызвать SOAP веб-сервис на Android
У меня много проблем с поиском полезной информации о том, как вызвать стандартный веб-сервис SOAP/WSDL с Android. Все, что мне удалось найти, это либо очень запутанные документы и ссылки на "kSoap2", а затем немного о синтаксическом анализе всего этого вручную с помощью SAX. Хорошо, это нормально, но сейчас 2008 год, поэтому я решил, что должна быть хорошая библиотека для вызова стандартных веб-сервисов.
Веб-сервис - это просто сервис, созданный в NetBeans. Я хотел бы иметь поддержку IDE для создания классов сантехники. Мне просто нужен самый простой / самый элегантный способ связаться с веб-сервисом на основе WSDL с телефона на базе Android.
26 ответов
Android не предоставляет никакой библиотеки SOAP. Вы можете написать свой собственный или использовать что-то вроде kSOAP 2. Как вы заметили, другие смогли компилировать и использовать kSOAP2 в своих собственных проектах, но мне не пришлось этого делать.
На сегодняшний день Google проявил небольшой интерес к добавлению библиотеки SOAP в Android. Я подозреваю, что они предпочли бы поддерживать текущие тенденции в веб-службах к службам на основе REST и использовать JSON в качестве формата инкапсуляции данных. Или, используя XMPP для обмена сообщениями. Но это только предположение.
Веб-сервисы на основе XML- это немного нетривиальная задача для Android в настоящее время. Не зная NetBeans, я не могу говорить о доступных там инструментах, но я согласен, что должна быть доступна лучшая библиотека. Вполне возможно, что XmlPullParser избавит вас от использования SAX, но я мало что знаю об этом.
org.apache.http.impl.client.DefaultHttpClient
поставляется в Android SDK по умолчанию. Это соединит вас с WSDL.
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("http://www.example.com/" + URL);
HttpResponse response = httpClient.execute(httpGet, localContext);
Это правда, что из-за накладных расходов SOAP - не лучший выбор для обмена данными с мобильными устройствами. Однако вы можете оказаться в ситуации, когда вы не контролируете формат вывода на сервер.
Итак, если вам нужно придерживаться SOAP, здесь есть библиотека kSOAP2, исправленная для Android:
http://code.google.com/p/ksoap2-android/
Для вызова веб-службы с мобильного устройства (особенно на телефоне Android) я использовал очень простой способ сделать это. Я не использовал API-интерфейс клиента веб-службы при попытке вызвать веб-службу. Мой подход заключается в следующем, чтобы позвонить.
- Создайте простое соединение HTTP с помощью стандартного API Java
HttpURLConnection
, - Сформируйте SOAP-запрос. (Вы можете помочь SOAPUI сделать запрос SOAP.)
- Установите флаг doOutPut как true.
- Установите значения заголовка HTTP, такие как длина содержимого, тип содержимого и агент пользователя. Не забудьте установить значение Content-length, так как оно является обязательным.
- Запишите весь SOAP-запрос в выходной поток.
- Вызовите метод, чтобы установить соединение и получить ответ (В моем случае я использовал
getResonseCode
). - Если вы получили код ответа как
- Это означает, что вам удалось вызвать веб-сервис.
- Теперь возьмите поток ввода в том же HTTP-соединении и получите строковый объект. Этот строковый объект является ответом SOAP.
- Если код ответа отличается от 200, тогда возьмите
ErrorInput
поток на том же HTTPobject и получить ошибку, если таковые имеются. - Разберите полученный ответ, используя SAXParser (в моем случае) или DOMParaser или любой другой механизм синтаксического анализа.
Я реализовал эту процедуру для телефона Android, и он успешно работает. Я могу проанализировать ответ, даже если он превышает 700 КБ.
SOAP является неподходящей технологией для использования на Android (или на мобильных устройствах в целом) из-за необходимости обработки / анализа. Услуги REST - это более легкое решение, и это то, что я бы предложил. Android поставляется с SAX-парсером, и его довольно просто использовать. Если вам абсолютно необходимо обрабатывать / анализировать SOAP на мобильном устройстве, то мне вас жаль, лучший совет, который я могу предложить, - просто не использовать SOAP.
Около года назад я читал эту ветку, пытаясь выяснить, как выполнять вызовы SOAP на Android - благодаря предложениям по созданию собственного приложения с использованием HttpClient я создал собственную библиотеку SOAP для Android:
По сути, он позволяет создавать конверты для отправки через простой Java API, а затем автоматически анализировать их в объекты, которые вы определяете через XPath... например:
<Dictionary>
<Id></Id>
<Name></Name>
</Dictionary>
становится:
@XMLObject("//Dictionary")
public class Dictionary {
@XMLField("Id")
private String id;
@XMLField("Name")
private String name;
}
Я использовал его для своего собственного проекта, но я подумал, что это может помочь некоторым другим людям, поэтому я потратил некоторое время на то, чтобы отделить его и задокументировать. Мне бы очень понравилось, если бы некоторые из ваших бедных душ, которые наткнулись на эту ветку, когда гуглили "SOAP Android", могли бы попробовать и получить какую-то выгоду.
НЕ ЗАБЫВАЙТЕ ДОБАВИТЬ ksoap2.jar в свой проект, а также добавьте разрешение ИНТЕРНЕТ в файле AndroidManifest
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class WebserviceActivity extends Activity {
private static final String NAMESPACE = "https://api.authorize.net/soap/v1/";
private static final String URL ="https://apitest.authorize.net/soap/v1/Service.asmx?wsdl";
private static final String SOAP_ACTION = "https://api.authorize.net/soap/v1/AuthenticateTest";
private static final String METHOD_NAME = "AuthenticateTest";
private TextView lblResult;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lblResult = (TextView) findViewById(R.id.tv);
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("name","44vmMAYrhjfhj66fhJN");
request.addProperty("transactionKey","9MDQ7fghjghjh53H48k7e7n");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
//SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
// SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
lblResult.setText(resultsRequestSOAP.toString());
System.out.println("Response::"+resultsRequestSOAP.toString());
} catch (Exception e) {
System.out.println("Error"+e);
}
}
}
У меня был свидание с KSOAP; Я выбрал более простой подход.
Имея файл WSDL, создайте шаблоны запросов SOAP для каждого запроса (например, с помощью пользовательского интерфейса SOAP) и затем подставьте значения, передаваемые в коде. Отправьте эти данные в конечную точку службы с помощью экземпляра DefaultHttpClient и получите поток ответов. Разобрать поток ответов с помощью синтаксического анализатора XML Pull.
Я создал новый клиент SOAP для платформы Android. Он использует сгенерированный интерфейс JAX-WS, но пока это только подтверждение концепции.
Если вы заинтересованы, пожалуйста, попробуйте пример и / или посмотрите источник на AndroidSOAP.
Если вы можете пойти на JSON. Android поставляется с полным пакетом org.json
Вызовите методы ksoap2. Это работает очень хорошо.
Установите детали, как
private static String mNAMESPACE=null;
private static String mURL=null;
public static Context context=null;
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(Request);
envelope.addMapping(mNAMESPACE, "UserCredentials",new UserCredendtials().getClass());
AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport(mURL);
а затем чтобы получить результат сделать
androidHttpTransport.call(SOAP_ACTION, envelope);
result = (SoapPrimitive)envelope.getResponse();
Несколько месяцев назад я работал с веб-службой jax-ws в приложении j2ee. Там мы использовали CXF wsdl2java для генерации заглушки клиента WS из файла WSDL и с этими заглушками клиента мы использовали веб-службы. Несколько недель назад, когда я пытался использовать веб-сервис таким же образом на платформе Android, я не мог, потому что в банке Android есть не все классы, поддерживающие "jax-ws". В то время я не нашел ни одного такого инструмента (если не смог эффективно работать с Google), чтобы он соответствовал моим требованиям -
- Получите заглушку клиента из WSDL.
- И вызвать Службу с некоторым аргументом (объект бизнес-запроса Java).
- Получите ответ Бизнес-объект.
Итак, я разработал свой собственный инструмент генерации клиента Android SOAP. Где вы должны следовать этим шагам:
- Из WSDL получите заглушку WS Client, вставьте ее в свой проект.
- Скажем для какой-то службы "ComplexOperationService", создайте экземпляр службы, получите порт конечной точки и вызовите метод службы и получите ответ от веб-службы:
например:
ComplexOperationService service = new ComplexOperationService( );
ComplexOperation port= service.getComplexOperationPort();
SomeComplexRequest request = --Get some complex request----;
SomeComplexResp resp = port.operate( request );
- Вам не нужно заботиться о классе обслуживания /req/response или любых других классах, а также о методе, поскольку вы знаете, что все они генерируются из WSDL.
- И, конечно, вам не нужно знать о мыльном действии / конверте / пространстве имен и т. Д. Просто вызовите метод, как мы, разработчики, делаем все время.
Я уверен, что вы могли бы сделать небольшой SOAP-клиент с Axis. Инструкция по установке Axis.
Я думаю, что Call SOAP Web Service из приложения Android вам очень поможет.
Если вы можете использовать JSON, есть документ, видео и образец.кода в разделе Разработка служб приложений с помощью серверов PHP и клиентов Android Phone.
Для меня самый простой способ - использовать хороший инструмент для генерации всех необходимых классов. Лично я пользуюсь этим сайтом:
Он поддерживает довольно сложные веб-сервисы и использует ksoap2.
Выполните следующие действия по методу SOAP
Из файла WSDL,
создавать шаблоны запросов SOAP для каждого запроса.
Затем подставьте значения, которые будут переданы в коде.
Отправьте эти данные в конечную точку службы, используя экземпляр DefaultHttpClient.
Получите ответный поток и, наконец,
Разобрать поток ответов с помощью синтаксического анализатора XML Pull.
Я бы предложил проверить очень полезный инструмент, который мне очень помог. Ребята, которые позаботились об этом проекте, тоже очень помогли. www.wsdl2code.com/
Если у вас возникли проблемы с вызовом веб-службы в Android, вы можете использовать приведенный ниже код для вызова веб-службы и получения ответа. Убедитесь, что ваш веб-сервис возвращает ответ в формате таблицы данных. Этот код поможет вам, если вы используете данные из базы данных SQL Server. Если вы используете MYSQL вам нужно изменить одну вещь, просто замените слово NewDataSet из предложения obj2=(SoapObject) obj1.getProperty("NewDataSet");
по DocumentElement
void callWebService(){
private static final String NAMESPACE = "http://tempuri.org/"; // for wsdl it may be package name i.e http://package_name
private static final String URL = "http://localhost/sample/services/MyService?wsdl";
// you can use IP address instead of localhost
private static final String METHOD_NAME = "Function_Name";
private static final String SOAP_ACTION = "urn:" + METHOD_NAME;
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("parm_name", prm_value);// Parameter for Method
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;// **If your Webservice in .net otherwise remove it**
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);// call the eb service
// Method
} catch (Exception e) {
e.printStackTrace();
}
// Next task is to get Response and format that response
SoapObject obj, obj1, obj2, obj3;
obj = (SoapObject) envelope.getResponse();
obj1 = (SoapObject) obj.getProperty("diffgram");
obj2 = (SoapObject) obj1.getProperty("NewDataSet");
for (int i = 0; i < obj2.getPropertyCount(); i++) {
// the method getPropertyCount() and return the number of rows
obj3 = (SoapObject) obj2.getProperty(i);
obj3.getProperty(0).toString();// value of column 1
obj3.getProperty(1).toString();// value of column 2
// like that you will get value from each column
}
}
Если у вас есть какие-либо проблемы по этому поводу, вы можете написать мне..
Это рабочий пример использования SOAP веб-сервисов в Android.
** Примечание::*** НЕ ЗАБУДЬТЕ ДОБАВИТЬ ksoap2.jar в свой проект, а также добавить разрешение ИНТЕРНЕТ в файле AndroidManifest *
public final String WSDL_TARGET_NAMESPACE = "http://tempuri.org/";
public final String METHOD_NAME = "FahrenheitToCelsius";
public final String PROPERTY_NAME = "Fahrenheit";
public final String SOAP_ACTION = "http://tempuri.org/FahrenheitToCelsius";
public final String SOAP_ADDRESS = "http://www.w3schools.com/webservices/tempconvert.asmx";
private class TestAsynk extends AsyncTask<String, Void, String> {
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(getApplicationContext(),
String.format("%.2f", Float.parseFloat(result)),
Toast.LENGTH_SHORT).show();
}
@Override
protected String doInBackground(String... params) {
SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE,
METHOD_NAME);
request.addProperty(PROPERTY_NAME, params[0]);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(
SOAP_ADDRESS);
Object response = null;
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
response = envelope.getResponse();
Log.e("Object response", response.toString());
} catch (Exception e) {
e.printStackTrace();
}
return response.toString();
}
}
Загрузите и добавьте файл библиотеки SOAP вместе с вашим проектом. Имя файла: ksoap2-android-assembly-3.4.0-jar-with-dependencies
Очистите приложение и затем запустите программу
Вот код для вызова службы SOAP
String SOAP_ACTION = "YOUR_ACTION_NAME";
String METHOD_NAME = "YOUR_METHOD_NAME";
String NAMESPACE = "YOUR_NAME_SPACE";
String URL = "YOUR_URL";
SoapPrimitive resultString = null;
try {
SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
addPropertyForSOAP(Request);
SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
soapEnvelope.dotNet = true;
soapEnvelope.setOutputSoapObject(Request);
HttpTransportSE transport = new HttpTransportSE(URL);
transport.call(SOAP_ACTION, soapEnvelope);
resultString = (SoapPrimitive) soapEnvelope.getResponse();
Log.i("SOAP Result", "Result Celsius: " + resultString);
} catch (Exception ex) {
Log.e("SOAP Result", "Error: " + ex.getMessage());
}
if(resultString != null) {
return resultString.toString();
}
else{
return "error";
}
Результаты могут быть JSONObject или JSONArray или String
Для вашего удобства, https://trinitytuts.com/load-data-from-soap-web-service-in-android-application/
Благодарю.
Вы можете выполнить мыльный вызов как сообщение через http с определенными заголовками. Я решил этот вопрос без дополнительных библиотек, таких как ksoap2. Вот живой код получения заказов от службы мыла.
private static HashMap<String,String> mHeaders = new HashMap<>();
static {
mHeaders.put("Accept-Encoding","gzip,deflate");
mHeaders.put("Content-Type", "application/soap+xml");
mHeaders.put("Host", "35.15.85.55:8080");
mHeaders.put("Connection", "Keep-Alive");
mHeaders.put("User-Agent","AndroidApp");
mHeaders.put("Authorization","Basic Q2xpZW50NTkzMzppMjR3s2U="); // optional
}public final static InputStream receiveCurrentShipments(String stringUrlShipments)
{
int status=0;
String xmlstring= "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:ser=\"http://35.15.85.55:8080/ServiceTransfer\">\n" +
" <soap:Header/>\n" +
" <soap:Body>\n" +
" <ser:GetAllOrdersOfShipment>\n" +
" <ser:CodeOfBranch></ser:CodeOfBranch>\n" +
" </ser:GetAllOrdersOfShipment>\n" +
" </soap:Body>\n" +
"</soap:Envelope>";
StringBuffer chaine = new StringBuffer("");
HttpURLConnection connection = null;
try {
URL url = new URL(stringUrlShipments);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Length", xmlstring.getBytes().length + "");
connection.setRequestProperty("SOAPAction", "http://35.15.85.55:8080/ServiceTransfer/GetAllOrdersOfShipment");
for(Map.Entry<String, String> entry : mHeaders.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
connection.setRequestProperty(key,value);
}
connection.setRequestMethod("POST");
connection.setDoInput(true);
OutputStream outputStream = connection.getOutputStream();
outputStream.write(xmlstring.getBytes("UTF-8"));
outputStream.close();
connection.connect();
status = connection.getResponseCode();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
Log.i("HTTP Client", "HTTP status code : " + status);
}
InputStream inputStream = null;
try {
inputStream = connection.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return inputStream;
}
Чтобы вызвать веб-сервис SOAP с Android, попробуйте использовать этот клиент
НЕ ЗАБУДЬТЕ ДОБАВИТЬ ksoap2-android.jar в путь сборки Java
public class WsClient {
private static final String SOAP_ACTION = "somme";
private static final String OPERATION_NAME = "somme";
private static final String WSDL_TARGET_NAMESPACE = "http://example.ws";
private static final String SOAP_ADDRESS = "http://192.168.1.2:8080/axis2/services/Calculatrice?wsdl";
public String caclculerSomme() {
String res = null;
SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE,
OPERATION_NAME);
request.addProperty("a", "5");
request.addProperty("b", "2");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS);
try {
httpTransport.call(SOAP_ACTION, envelope);
String result = envelope.getResponse().toString();
res = result;
System.out.println("############# resull is :" + result);
} catch (Exception exception) {
System.out.println("########### ERRER" + exception.getMessage());
}
return res;
}
}
Добавить мыло Libaray (ksoap2-android-assembly-3.2.0-jar-with-dependencies.jar
):
public static String Fn_Confirm_CollectMoney_Approval (
HashMap < String, String > str1,
HashMap < String, String > str2,
HashMap < String, String > str3) {
Object response = null;
String METHOD_NAME = "CollectMoney";
String NAMESPACE = "http://xxx/yyy/xxx";
String URL = "http://www.w3schools.com/webservices/tempconvert.asmx";
String SOAP_ACTION = "";
try {
SoapObject RequestParent = new SoapObject(NAMESPACE, METHOD_NAME);
SoapObject Request1 = new SoapObject(NAMESPACE, "req");
PropertyInfo pi = new PropertyInfo();
Set mapSet1 = (Set) str1.entrySet();
Iterator mapIterator1 = mapSet1.iterator();
while (mapIterator1.hasNext()) {
Map.Entry mapEntry = (Map.Entry) mapIterator1.next();
String keyValue = (String) mapEntry.getKey();
String value = (String) mapEntry.getValue();
pi = new PropertyInfo();
pi.setNamespace("java:com.xxx");
pi.setName(keyValue);
pi.setValue(value);
Request1.addProperty(pi);
}
mapSet1 = (Set) str3.entrySet();
mapIterator1 = mapSet1.iterator();
while (mapIterator1.hasNext()) {
Map.Entry mapEntry = (Map.Entry) mapIterator1.next();
// getKey Method of HashMap access a key of map
String keyValue = (String) mapEntry.getKey();
// getValue method returns corresponding key's value
String value = (String) mapEntry.getValue();
pi = new PropertyInfo();
pi.setNamespace("java:com.xxx");
pi.setName(keyValue);
pi.setValue(value);
Request1.addProperty(pi);
}
SoapObject HeaderRequest = new SoapObject(NAMESPACE, "XXX");
Set mapSet = (Set) str2.entrySet();
Iterator mapIterator = mapSet.iterator();
while (mapIterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry) mapIterator.next();
// getKey Method of HashMap access a key of map
String keyValue = (String) mapEntry.getKey();
// getValue method returns corresponding key's value
String value = (String) mapEntry.getValue();
pi = new PropertyInfo();
pi.setNamespace("java:com.xxx");
pi.setName(keyValue);
pi.setValue(value);
HeaderRequest.addProperty(pi);
}
Request1.addSoapObject(HeaderRequest);
RequestParent.addSoapObject(Request1);
SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(
SoapEnvelope.VER10);
soapEnvelope.dotNet = false;
soapEnvelope.setOutputSoapObject(RequestParent);
HttpTransportSE transport = new HttpTransportSE(URL, 120000);
transport.debug = true;
transport.call(SOAP_ACTION, soapEnvelope);
response = (Object) soapEnvelope.getResponse();
int cols = ((SoapObject) response).getPropertyCount();
Object objectResponse = (Object) ((SoapObject) response)
.getProperty("Resp");
SoapObject subObject_Resp = (SoapObject) objectResponse;
modelObject = new ResposeXmlModel();
String MsgId = subObject_Resp.getProperty("MsgId").toString();
modelObject.setMsgId(MsgId);
String OrgId = subObject_Resp.getProperty("OrgId").toString();
modelObject.setOrgId(OrgId);
String ResCode = subObject_Resp.getProperty("ResCode").toString();
modelObject.setResCode(ResCode);
String ResDesc = subObject_Resp.getProperty("ResDesc").toString();
modelObject.setResDesc(ResDesc);
String TimeStamp = subObject_Resp.getProperty("TimeStamp")
.toString();
modelObject.setTimestamp(ResDesc);
return response.toString();
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}