2012-05-10 10 views
0

ここ数日から、私はAndroidのコードを使ってローカルWebサービスを呼び出す作業をしています。私は、 "ksoap2-android-assembly-2.5.7-jar-with-dependencies.jar"のAndroid用ksoap2ライブラリを使用しています。 SOAPで作成されたSOAP Webサービスを呼び出すのに問題があります。基本的なhttp要求を使用してクライアントを認証します。アンドロイドアプリから認証(ログインとパスワード)を使ってウェブサービスに電話する

これは私のコードです:

public String CallSoapConnexion(String login, String mdp) { 
    SoapObject request = new SoapObject(nms, mth); 
    PropertyInfo pi = new PropertyInfo(); 
    pi.setName("login"); 
    pi.setValue(login); 
    pi.setType(String.class); 
    request.addProperty(pi); 
    pi = new PropertyInfo(); 
    pi.setName("mdp"); 
    pi.setValue(mdp); 
    pi.setType(String.class); 
    request.addProperty(pi); 

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
      SoapEnvelope.VER11); 

    envelope.dotNet = true; 

    envelope.setOutputSoapObject(request); 

    HttpTransportSE httpTransport = new HttpTransportSE(urlHttp); 

    List<HeaderProperty> headerList = new ArrayList<HeaderProperty>(); 

    headerList 
      .add(new HeaderProperty("Authorization", "Basic " 
        + org.kobjects.base64.Base64.encode("login:pasword" 
          .getBytes()))); 

    Object response = null; 
    try { 

     httpTransport.call(act, envelope, headerList); 
     response = envelope.getResponse(); 

    } catch (Exception ex) { 

     return ex.toString; 

    } 
    return ex.toString; 
} 

しかし、私は次の例外を取得:

org.xmlpull.v1.XmlPullParserException: expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG <html>@2:7 in [email protected]) 

答えて

1

Ksoap2は私のトラブルの多くを与えた、私はのSAXParserのウィッヒを使用して独自のパーサーを作ってしまっていますXMLを解析する最速の方法です。これが私のやり方です。

クラス内で最初に、WebServicesに必要なすべての定数パラメータが保存されました。それらはすべてパブリックで静的なので、クラスをインスタンス化することなくプロジェクトのどこにでもアクセスできます。それをMyConstants.classという名前にしましょう。

//######################## LOGIN WEB SERVICE CONSTANTS 
/** 
* This string constructs the SOAP Envelope you need to use to Use the DoLogin WebService. 
* Use this string with String.format in the following way. 
* @param sUserName (String) 
* @param sPassword (String) 
* @Example String env = String.format(WebserviceConsumer.LOGIN_ENVELOPE, username, password); 
* */ 
public static final String LOGIN_ENVELOPE = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + 
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" + 
    "<soap:Body>" + 
    "<Login xmlns=\"webServiceNamespace\">" + 
     "<sUsername>%s</sUsername>" + 
     "<sPassword>%s</sPassword>" + 
    "</Login>" + 
    "</soap:Body>" + 
"</soap:Envelope>"; 
public static final String LOGIN_SOAP_ACTION = "webServiceNamespace/Login"; 
public static final String LOGIN_URL = "https://ws.yoururl.com/YourLoginPage.asmx?op=Login"; 
public static final int LOGIN = 100; 

これは私が「行った」パーサーです。それは私が見つけた別のパーサーに基づいているので、完璧かどうかわかりませんが、うまくいきます。

[編集] SAXパーサーは良い方法ではないので、しばらくしてからパーサーを変更しました。高速ですが、効率的ではありません。ガベージコレクタによって収集される必要があるオブジェクトが多数作成されるためです。 XMLPullParserを使用してこのジョブを実行することをおすすめします。使い方はSAXよりも簡単です。 [/ EDIT]

package com.yourproject.parsers; 

import java.io.IOException; 
import java.io.InputStream; 

import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 

import org.xml.sax.Attributes; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 

import android.os.Bundle; 

/**Callback Example 
* @example 
* <?xml version="1.0" encoding="utf-8"?> 
* <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
*  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
*  xmlns:xsd="http://www.w3.org/2001/XMLSchema" > 
*  <soap:Body> 
*   <LoginResponse xmlns="https://ws.yoururl.com/" > 
*    <LoginResult> 
*     <ROOT xmlns="" > 
*      <PassportKey> 
*       <Key>653215989827346254362544623544652321</Key> 
*       <otherLoginInfo>585051</otherLoginInfo> 
*      </PassportKey> 
*     </ROOT> 
*    </LoginResult> 
*   </LoginResponse> 
*  </soap:Body> 
* </soap:Envelope> 
*/ 

/** 
* The loginParser saves the parsed data in a bundle. Once the parsing is done, call the 
* getResutl() function to get a bundle that has the login authentication result. 
* */ 
public class LoginParser extends DefaultHandler { 
    private String foundData = ""; 
    private String authCode = ""; 
    private String otherInfo = ""; 
    private Bundle result; 

    public synchronized void parse(InputStream is) throws ParserConfigurationException, SAXException, IOException{ 
     SAXParserFactory spf = SAXParserFactory.newInstance(); 
     SAXParser sp = spf.newSAXParser(); 
     XMLReader xr = sp.getXMLReader(); 
     xr.setContentHandler(this); 

     xr.parse(new InputSource(is)); 
    } 

    @Override 
    public void characters(char[] ch, int start, int length) throws SAXException { 
     foundData += new String(ch, start, length); 
    } 

    @Override 
    public void startDocument() throws SAXException{ 
     // Nothing to do 
    } 

    @Override 
    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException{ 
     foundData = ""; 
    } 

    @Override 
    public void endElement(String namespaceURI, String localName, String qName) throws SAXException{ 
     if (qName.equals("Key")) { 
      authCode = foundData; 
     } else if (qName.equals("otherLoginInfo")){ 
      otherInfo = foundData; 
     } 
    } 

    @Override 
    public void endDocument() throws SAXException{ 
     // Nothing to do. 
    } 

    public Bundle getResult(){ 
     result = new Bundle(); 
     result.putString("authCode", authCode); 
     result.putString("otherInfo", otherInfo); 
     return result; 
    } 
} 

そしてパーサーを使用するクラス。一度これを持っていれば、好きなプロジェクトのどこでもこれを呼び出すことができます。

package com.yourproject.web; 

import java.io.IOException; 
import java.io.InputStream; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.ResponseHandler; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 
import org.apache.http.params.HttpProtocolParams; 
import org.apache.http.util.EntityUtils; 


import com.yourproject.parsers.LoginParser; 

import android.content.Context; 
import android.os.Bundle; 
import android.util.Log; 

/** 
* Public class used to send a SOAP message to our Webservices. 
* 
* Code from 
* http://mobileorchard.com/android-app-development-calling-web-services/ 
* */ 
public class WebserviceCall{ 
    LoginParser lp; 
    [... other parsers ...] 


    [... other parsers implementation ...] 

    public Bundle CallWebServiceParseAndReturn(String url, String soapAction, String envelope, int callerRequest) throws Exception { 
     HttpClient httpclient = new DefaultHttpClient(); 
     HttpPost httpRequest = null; 
     HttpResponse httpResponse = null; 
     Bundle result = null; 

     httpRequest = new HttpPost(url); 
     if (envelope != null) { 
      httpRequest.setEntity(new StringEntity(envelope)); 
      httpRequest.addHeader("Content-Type", "text/xml; charset=utf-8"); 
     } 

     httpResponse = httpclient.execute(httpRequest); 
     switch (callerRequest) { 
     case MyConstants.LOGIN: 
      lp = new LoginParser(); 
      lp.parse(httpResponse.getEntity().getContent()); 
      result = lp.getResult(); 
      break; 
     case MyConstants.OTHERPARSERS: 
     case default: 
      break; 
     return result; 
    } 
} 

最後に、これをプロジェクトでどのように使用するかの例を示します。

private void callWebserviceLogin(String userName, String password) { 
    try{ 
     Bundle result = null; 
     WebserviceCall wsCall = new WebserviceCall(); 
     String wsEnvelope = String.format(MyConstants.LOGIN_ENVELOPE, userName, password); 
     result = wsCall.CallWebServiceParseAndReturn(MyConstants.LOGIN_URL, MyConstants.LOGIN_SOAP_ACTION, wsEnvelope, MyConstants.LOGIN); 
     authenticationResult = result.getString("authCode"); 
    } catch (Exception e) { 
     authenticationResult = ""; 
     Log.e("Login error", e.getMessage()); 
    } 
} 

あなたは私が持っている封筒の定数を参照する場合は、文字列内の一部の%sのマークがあります。 String.formatを使用すると、最初のもの(マーカーを保持する文字列)の後に渡すパラメータで、各マークを外観順に置き換えます。

私はこれがあなたが期待しているものではないことを知っていますが、これが役立つことを願っています。

関連する問題