How to use ksoap2 library

Asked

Viewed 666 times

1

I have the following situation, I have a PHP server:

class Teste {
    function obtemStatus(){ 
        return 'ok'; 
    }
}

$server = new SoapServer(null, array('uri'=>'http://test-uri/'));
$server->setClass('Teste');
$server->handle();

And a PHP client too:

$options = array(
    'location'  => 'http://localhost/android/server/index.php',
    'uri'       => 'http://test-uri/'
);
$client = new SoapClient(null, $options);
echo $client->obtemStatus();

This is working perfectly, but now I want to use this service by Anndroid, I have the following code:

private String NAMESPACE = "urn://http://localhost";
private String METHOD_NAME = "obtemStatus";
private String URL = "localhost/android/client/index.php";
private String SOAP_ACTION = "localhost/android/client/index.php/obtemStatus";

// observação: antes do localhost está o http:// mas tive que tirar para postar aqui
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);

SoapObject soap = new SoapObject(NAMESPACE, METHOD_NAME);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(soap);

HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

try {
    androidHttpTransport.call(SOAP_ACTION, envelope);
} catch (IOException e) {
    e.printStackTrace();
} catch (XmlPullParserException e) {
    e.printStackTrace();
}

}

You’re making the following mistake:

09-22 20:59:27.501    9637-9637/com.anderson.soap D/HyLog﹕ I : /data/font/config/dfactpre.dat, No such file or directory (2)
09-22 20:59:27.661    9637-9637/com.anderson.soap D/AndroidRuntime﹕ Shutting down VM
09-22 20:59:27.661    9637-9637/com.anderson.soap E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.anderson.soap, PID: 9637
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.anderson.soap/com.anderson.soap.MyActivity}: android.os.NetworkOnMainThreadException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2202)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2252)
            at android.app.ActivityThread.access$800(ActivityThread.java:139)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1200)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5103)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606)
     Caused by: android.os.NetworkOnMainThreadException
            at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1148)
            at java.net.InetAddress.lookupHostByName(InetAddress.java:405)
            at java.net.InetAddress.getAllByNameImpl(InetAddress.java:251)
            at java.net.InetAddress.getAllByName(InetAddress.java:229)
            at com.android.okhttp.internal.Dns$1.getAllByName(Dns.java:28)
            at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:216)
            at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:122)
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:292)
            at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197)
            at org.ksoap2.transport.ServiceConnectionSE.openOutputStream(ServiceConnectionSE.java:120)
            at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:176)
            at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:114)
            at com.anderson.soap.MyActivity.onCreate(MyActivity.java:39)
            at android.app.Activity.performCreate(Activity.java:5275)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2166)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2252)
            at android.app.ActivityThread.access$800(ActivityThread.java:139)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1200)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5103)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606)

Does anyone know what it could be?

1 answer

1


Anderson, this error you made is not directly related to your connection code. This error is due to where you are running an internet connection on MainThread.

It is not recommended to perform network operations or I/O (some are allowed, for example Sharedpreferences) in general at MainThread.

To MainThread is responsible for many essential operations (View design, event handling, creation and destruction of Activities, Fragments and other entities, rescue operations Activity, Fragment and hierarchy of Views), so it is not good to interrupt the MainThread.

To learn more about the Main Thread, take a look at A Journey on the Android Main Thread

It is often because of very slow processing in MainThread that one sees Dialog of ANR.

Dialog de ANR

For this it is recommended to start a AsyncTask to perform network and I/O.

To AsyncTask abstract the use of Threads and communication with the MainThread. At the bottom your code will run in a Thread separate (method doInBackground), but in a few moments (onPreExecute and onPostExecute) the code will be executed in the Main Thread.

It is also possible to publish a progress, to update the interface. For this use the method publishProgress within the doInBackground. With that the method onProgressUpdate will be executed in the MainThread.

In addition, the AsyncTask is highly parameterized: AsyncTask<Params, Progress, Result>, so you can specify a type for each value that is used in it. If it is a AsyncTask for processing in Background, the most common is to use AsyncTask<Void, Void, Void>.

For more details take a look at Keeping Your App Responsive and Asynctask.

Using AsyncTask, your code would be:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);

    new AsyncTask<Void, Void, Void>() {
        @Override
        public Void doInBackground(Void... params) {
            // Todo codigo executado nesse metodo sera feito em um Thread
            // Fora da MainThread.
            // Nao atualize elementos de interface (Views) aqui!

            SoapObject soap = new SoapObject(NAMESPACE, METHOD_NAME);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(soap);

            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

            try {
                androidHttpTransport.call(SOAP_ACTION, envelope);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (XmlPullParserException e) {
                e.printStackTrace();
            }

            // Nao ha nenhum resultado no processamento, nao retorno nada.
            // Voce pode retornar algo se achar necessario
            return null;
        }

        @Override
        public void onPostExecute(Void result) {
            // Esse metodo é executado na MainThread!
            // O "result" é o retorno do metodo doInBackground
            // Atualize elementos de interface aqui.
        }
    }.execute();
}

This is the basics of AsyncTask, for more details I recommend seeing some Android tutorials, specifically the Connecting to the Network.

When you have more time, take a look at the Loaders, they do a processing in a Thread but are managed by the life cycle of the Activity automatically, greatly simplifying the work.

  • Thank you very much for your answer, and then I’m going to read up on this Loaders. Now giving another error: 09-23 14:08:51.547 24721-24757/com.anderson.Soap W/System.err java.net.Connectexception: failed to connect to localhost/127.0.0.1 (port 80) after 20000ms: isConnected failed: ECONNREFUSED (Connection refused).. I don’t know why you’re not connecting to localhost, I saw in other topics here of stackoverflow that said to switch to 127.0.0.1:80 and nothing.

  • Are you testing from within the correct emulator? Use the address 10.0.2.2 if applicable. Further details on the addresses: http://developer.android.com/tools/devices/emulator.html#networkaddresses.

  • No, I’m testing it right on my cell. In another reply they talked to use 10.0.2.2:8080, but the error: Sockettimeoutexception: failed to connect to /10.0.2.2 (8080 port) after 20000ms

  • So that’s the mistake, localhost cell phone is itself, if your server is on your machine, you should check its address on the network (assuming the cell phone and the server are on the same network).

  • It’s true, what a mess of mine. ;/ Put my host ip here and passed, but stopped at another error: org.xmlpull.v1.Xmlpullparserexception: Expected a string quoted (position:DOCDECL @1:50 in java.io.Inputstreamreader@65988fc0) I saw on other topics that people talked about using this List<Headerproperty> headers = new Arraylist<Headerproperty>(); but it didn’t help. My server does not have wsdl does this have to be?

  • I think I already know what it might be, I tried to access http://172.16. 6.170/ by the browser and gave permission error. must be this

  • It is really I was with permission problem on the server, it is already solved, now I can see the return, but it is still with error: org.xmlpull.v1.Xmlpullparserexception: Unexpected token (position:TEXT ok@1:3 in java.io.Inputstreamreader@65988e28) That "ok" is the return.

  • I’m not sure about the SOAP protocol, response is just "okay"? Shouldn’t be with the envelope?

  • Does the return look like this: <? xml version="1.0" encoding="UTF-8"? > <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-Uri/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance-" xmlns:SOAP-ENC="http://schemas.lsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:obtemStatusResponse> <Return xsi:type="xsd:string">ok</Return> </ns1:obtemStatusResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

  • Dude, I’m not sure what happened, but it’s working.. Some lessons learned: - Using the Asynctask class - Checking IP - Checking the permission on the server Thanks again! kkk

  • Very good, unfortunately I could not help so much with the SOAP, like I said I never actually wore it. Good job.

Show 6 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.