6 Ekim 2011 Perşembe

3. party kütüphane kullanmadan (ksoap2) Android ile soap request işlemleri. Soap request on Android without using any third party library like ksoap2


Uzun bir aradan sonra tekrar merhaba.
(Hello again after a long time)

Büyük bir çoğunluk, android ile webservice'e bağlanmak istediğinde ksoap2'yi kullanıyor. Bunun zaman zaman dezavantajlarıyla karşılaşmış biri olarak size nasıl 3. party kütüphane kullanmadan kendi soap requestiniz ile bir webservice'e bağlanacağınızı açıklayacağım.
(A large majority of the android developers are using ksoap2 library when they want to connect to a webservice. As a man who encountered with disadvantages and advantages of these kind of libraries I will explain you how to send soap request without using any third party library -like soap2- on android)

HelloWorld adında bir webmethodumuz var, String türünde a değişkeni alıyor ve geriye a parametresinin değerine "türkçe karakterlerle doğru çalışıyor:" ibaresini ekleyerek dönüyor. Bilmeyenler .NET ile nasıl webservice yapılacağı konusunu anlatan ilgili örneğe buradan ulaşabilirler.
(There is a webmethod called HelloWorld. It takes a String as a parameter named a and returns with adding an expression which is "türkçe karakterlerle doğru çalışıyor" (which means it works correctly with turkish characters) to the return value. If you don't know how to create a webservice on .NET you can see the example by clicking here.)

[WebMethod]
public string HelloWorld(string a){
       return "türkçe karakterlerle doğru çalışıyor:  " + a;
}



Artık android tarafına geçebiliriz.
(Now we can go to the android side)

private void soapDeneme() {
  String envelope="<?xml version=\"1.0\" encoding=\"iso-8859-9\"?>"+
    "<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:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">"+
    "<soap:Body>"+
    "<HelloWorld xmlns=\"http://tempuri.org/\">"+
    "<a>abcçdefgğhıijklmnoöprsştuüvyz</a>"+
    "</HelloWorld>"+
    "</soap:Body>"+
    "</soap:Envelope>";
  String url = "http://www.mustafaguven.com.tr/androidDenemeWebservice/Service1.asmx";
  String soapAction = "http://tempuri.org/HelloWorld";
  new CallWebService().execute(url,soapAction,envelope); 
 }

Yukarıda en çok dikkat edilmesi gereken şey request'imizi bir AsyncTask içerisinde call etmemiz. Aslında bu 3.0'ın altındaki herhangi bir versiyonda belki problem yaratmayabilir ancak honeycomb ile birlikte android bu tür işlemleri UI thread üzerinde yapmanıza izin vermeyecektir. (NetworkOnMainThreadExceptionDesigning For Responsiveness) Bunun için ya bir handler içerisinde call işlemini gerçekleştirmelisiniz ya da bizim bu örnekte yaptığımız gibi asynctask içerisinde.
(The most noticeable think above is that you must use another thread to call a webservice if the application which you are developing runs on the honeycomb (3.0) because UI thread does not support for this action otherwise it will be throwed out an exception called NetworkOnMainThreadException. for further information: Designing For Responsiveness)

 class CallWebService extends AsyncTask<String, String, String>{

  @Override
  protected String doInBackground(String... parameters) { 
   final DefaultHttpClient httpClient=new DefaultHttpClient(); 
   HttpParams params = httpClient.getParams(); 
   HttpConnectionParams.setConnectionTimeout(params, 10000); 
   HttpConnectionParams.setSoTimeout(params, 15000); 
   HttpProtocolParams.setUseExpectContinue(params, true); 
   HttpPost httppost = new HttpPost(parameters[0]);
   httppost.setHeader("soapaction", parameters[1]);
   httppost.setHeader("Content-Type", "text/xml; charset=iso-8859-9");

   String responseString="";
   try {
    HttpEntity entity = new StringEntity(parameters[2], "iso-8859-9");
    httppost.setEntity(entity);
    ResponseHandler rh=new ResponseHandlerTr();
    responseString=httpClient.execute(httppost, rh);
   }
   catch (Exception e) {
    Log.e("hata", e.getMessage());
   }
   httpClient.getConnectionManager().shutdown();
   return responseString;
  }
 }
(Yukarıda HttpEntity entity = new StringEntity(parameters[2], "iso-8859-9"); bölümünde charset'inizi "iso-8859-9" şeklinde belirtmezseniz webservice tarafında türkçe karakterlerin hepsi düzgün çalışmayacaktır.)
(You need to describe the encoding type as above to display turkish characters correctly)

Gelen response'da encoding yapmak için bu response'u handle etmemiz gerekli bunun için BasicResponseHandler class'ından extend ettiğimiz ResponseHandlerTr class'ını yazıyoruz.
(We are creating ResponseHandlerTr class which extends BasicResponseHandler to handle the response and encode it)

package com.quadro.main.Util;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpResponseException;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.util.EntityUtils;

public class ResponseHandlerTr extends BasicResponseHandler {
 @Override
 public String handleResponse(HttpResponse response) throws HttpResponseException, IOException      {
    StatusLine statusLine = response.getStatusLine();
         if (statusLine.getStatusCode() >= 300) {
             throw new HttpResponseException(statusLine.getStatusCode(),
                     statusLine.getReasonPhrase());
         }

         HttpEntity entity = response.getEntity();
         return entity == null ? null : EntityUtils.toString(entity, "iso-8859-9");
 }
 
}
Webservice'ten gelen cevap:
(The response comes from the webservice)



Anlaşılmayan bir nokta olursa çekinmeden danışabilirsiniz.
(Please feel free to contact me if you have any questions)

13 yorum:

  1. Hocam elinize sağlık. Yanlız class CallWebService extends AsyncTask{} şeklinde tip belirtilmezse default olarak Object kabul ettiğinden doInBackground metodu uyarı vermiyor mu? protected String doInBackground(Object... parameters) {}

    YanıtlaSil
  2. aslında orada "String, String, String" var ancak malum encode problemlerinden ötürü sayfa göstermemiş. uyarı için teşekkürler

    YanıtlaSil
  3. Teşekkür ederim yazınız için, fakat internette aradım aradım durdum sonuca ulaşamadım. Eğer, WebServis Class tipinde bir sonuç döndürüyor ise bunu nasıl (Class'ların teker teker Field'larına bakmadan) Android tarafında Class lara atabilirim?

    YanıtlaSil
    Yanıtlar
    1. bu konuda wsclient++ işinizi görür. incelemenizi tavsiye ederim.

      Sil
  4. http://bimbim.in/post/2010/10/08/Android-Calling-Web-Service-with-complex-types.aspx bu örneği inceleyebilirsiniz.

    YanıtlaSil
  5. Thanks Mustafa!

    Your article helps me so much :)

    Marcel.

    YanıtlaSil
  6. adamın dibisin la mustafa :)

    YanıtlaSil
  7. androidde yeniyim de bu örneğin derleyebileceğim tüm kodunu eyizar_391@hotmail.com adresine gönderebilirmisiniz. şimdiden çok teşekkürler.

    YanıtlaSil
  8. bu yöntemi kullanarak web servis in döndürdüğü sonucu nasıl alabileceğimizi anlatabilir misiniz?

    YanıtlaSil
    Yanıtlar
    1. almaktan kastınız nedir? zaten yukarıdaki örnekte webservisten gelen cevap alınıyor.

      Sil
  9. Güzel paylaşım teşekkürler, özellikler utf-8 yerine iso-8859-9 kullanmam konusunda bilgi sahibi oldum.

    YanıtlaSil
  10. Merhaba, KSOAP2 kullarak bir sıkıntı yaşamadan veriyi alabiliyorum. Ancak uyguladığınız yöntemle nasıl alabilirim? Gönderilecek veri şu şekilde;
    BenimSınıfım
    Dönecek veri ise
    BenimSınıfımArray

    Sınıfların içinde de farklı alanlar var ve dönen sınıfta yine bir List tanımı var.

    YanıtlaSil