Problem to login in android studio using KSOAP

2

I am developing a mobile application in Android Studio consuming from a WebServices made in asmx. Only when I run my app and enter the username and password send me an error

  

E / Response: Error: Can not create handler inside thread that has not   called Looper.prepare ()

I leave here my code that I have in my activity

package com.example.onc_lap.oncontrolmobile;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
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.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.StrictMode;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.net.URL;
import java.net.URLConnection;

public class Principal extends AppCompatActivity {
    EditText usuario;
    EditText password;
    private Button ingresar;
    private ProgressDialog pDialog;
    String TAG = "Response";
    public final int dialogo_alert = 0;
    public String msje = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_principal);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        usuario = (EditText) findViewById(R.id.usuario);
        password = (EditText) findViewById(R.id.password);
        ingresar = (Button) findViewById(R.id.ingresar);
        ingresar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String username = usuario.getText().toString();
                String pass = password.getText().toString();
                new webserv().execute();
            } //fin del click view
        });
    }

    class webserv extends AsyncTask<String, String, String> {
        public String NAMESPACE = "http://ONControl_MobileWS/";
        public String METHOD_NAME = "Login";
        public String SOAP_ACTION = "http://ONControl_MobileWS/Login";
        public String SOAP_ADDRESS;
        private SoapObject request;
        private HttpTransportSE transporte;
        private SoapSerializationEnvelope envelope;

        @Override
        protected String doInBackground(String... params) {
           Login();
            return null;
        }

        protected void onPreExecute() {
            Log.i(TAG, "onPreExecute");
            pDialog = new ProgressDialog(Principal.this);
            pDialog.setMessage("Iniciando sesion ...");
            pDialog.setIndeterminate(false);
            pDialog.setMax(10);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        protected void onPostExecute(boolean result) {
                    if (result){
                        Toast.makeText(Principal.this, "Tarea finalizada!",
                                Toast.LENGTH_SHORT).show();
                    }
        }

        public void Login(){
            SOAP_ADDRESS = "http://oncontrol.no-ip.net:9020/ONControl_MobileWS.asmx";
            request = new SoapObject(NAMESPACE, METHOD_NAME);
            PropertyInfo pi= new PropertyInfo();
            envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            transporte = new HttpTransportSE(SOAP_ADDRESS);

            request.addProperty("usuario", usuario.getText().toString());
            request.addProperty("password", password.getText().toString());

            try {
                transporte.call(SOAP_ACTION, envelope);

                SoapPrimitive resultado_xml =(SoapPrimitive)envelope.getResponse();
                String res = resultado_xml.toString();
                Principal.this.msje=res;
                // mostramos la respuesta en un toast
                Toast.makeText(Principal.this.getBaseContext(), res,Toast.LENGTH_SHORT).show();

                if(res.equals("Gracias por Iniciar Sesion")){
                    Principal.this.usuario.getText().toString();
                    Principal.this.usuario.setText("");
                    Principal.this.password.setText("");
                    //envia al otro activity
                    Intent intent=new Intent("android.intent.menu");
                    startActivity(intent);
                    finish();
                }

            } catch (Exception e) {
                Log.e(TAG, "Error: " + e.getMessage());
            }
        }
    }
     //run
}
    
asked by Hugo Rodriguez 13.04.2016 в 19:48
source

2 answers

1

The problem is that you try to update or make changes to the UI from a thread in background, which is only allowed in onPostExecute() .

When you run your doInBackground() of the Asynctask is executed Login() which tries to perform operations such as:

 // mostramos la respuesta en un toast
            Toast.makeText(Principal.this.getBaseContext(), res,Toast.LENGTH_SHORT).show();

            if(res.equals("Gracias por Iniciar Sesion")){
                Principal.this.usuario.getText().toString();
                Principal.this.usuario.setText("");
                Principal.this.password.setText("");
                //envia al otro activity
                Intent intent=new Intent("android.intent.menu");
                startActivity(intent);
                finish();
            }

Try moving these operations to onPostExecute() of your Asynctask , which is where you could easily modify your UI.

  

onPostExecute () will run in the user interface thread.

Therefore your class would have to change to:

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.StrictMode;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


import java.net.URL;
import java.net.URLConnection;

public class Principal extends AppCompatActivity {

    private static String TAG = "Response";
    EditText usuario;
    EditText password;
    private Button ingresar;
    private ProgressDialog pDialog;
    public final int dialogo_alert = 0;
    public String msje = "";
    private String res = "";


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_principal);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        usuario = (EditText) findViewById(R.id.usuario);
        password = (EditText) findViewById(R.id.password);
        ingresar = (Button) findViewById(R.id.ingresar);
        ingresar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String username = usuario.getText().toString();
                String pass = password.getText().toString();
                new webserv().execute();

            } //fin del click view

        });
    }


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


        public String NAMESPACE = "http://ONControl_MobileWS/";
        public String METHOD_NAME = "Login";
        public String SOAP_ACTION = "http://ONControl_MobileWS/Login";
        public String SOAP_ADDRESS;
        private SoapObject request;
        private HttpTransportSE transporte;
        private SoapSerializationEnvelope envelope;

        @Override
        protected String doInBackground(String... params) {
            return Login();
        }


        protected void onPreExecute() {

            Log.i(TAG, "onPreExecute");

            pDialog = new ProgressDialog(Principal.this);
            pDialog.setMessage("Iniciando sesion ...");
            pDialog.setIndeterminate(false);
            pDialog.setMax(10);
            pDialog.setCancelable(false);
            pDialog.show();
        }


        protected void onPostExecute(String result) {

            Principal.this.msje = res;
            // mostramos la respuesta en un toast
            Toast.makeText(Principal.this.getBaseContext(), res, Toast.LENGTH_SHORT).show();

            if (res.equals("Gracias por Iniciar Sesion")) {
                Principal.this.usuario.getText().toString();
                Principal.this.usuario.setText("");
                Principal.this.password.setText("");
                //envia al otro activity
                Intent intent = new Intent("android.intent.menu");
                startActivity(intent);
                finish();
            }
                Toast.makeText(Principal.this, "Tarea finalizada!",
                        Toast.LENGTH_SHORT).show();
        }


        public String Login() {
            SOAP_ADDRESS = "http://oncontrol.no-ip.net:9020/ONControl_MobileWS.asmx";
            request = new SoapObject(NAMESPACE, METHOD_NAME);
            PropertyInfo pi = new PropertyInfo();
            envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            transporte = new HttpTransportSE(SOAP_ADDRESS);

            request.addProperty("usuario", usuario.getText().toString());
            request.addProperty("password", password.getText().toString());

            try {
                transporte.call(SOAP_ACTION, envelope);

                SoapPrimitive resultado_xml = (SoapPrimitive) envelope.getResponse();
                return resultado_xml.toString();

            } catch (Exception e) {
                Log.e(TAG, "Error: " + e.getMessage());
                return ""; retorna una cadena vacía en caso de error...
            }

        }


    }

}
    
answered by 13.04.2016 в 21:07
0

I propose the following, I think it is good to help find faults in the code; but it is also opportune to correct errors in Syntax that can present the code, remember that the programming languages have a set of writing rules that standardize the programs so that any developer in the world can understand it.

It is also true that you should correct less optimal implementations of the resource that is the focus of the problem, below I put your modified class with some observations that will be useful, if you are starting in this development. Keep in mind that when dealing literally with a "language" we should all respect the rules.

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.StrictMode;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.net.URL;
import java.net.URLConnection;

public class Principal extends AppCompatActivity {
    private static String TAG = "Response";
    EditText usuario;
    EditText password;
    private Button ingresar;
    private ProgressDialog pDialog;
    public final int dialogo_alert = 0;
    public String msje = "";
    private String res = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_principal);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        usuario = (EditText) findViewById(R.id.usuario);
        password = (EditText) findViewById(R.id.password);
        ingresar = (Button) findViewById(R.id.ingresar);

        ingresar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String username = usuario.getText().toString();
                String pass = password.getText().toString();
                new Webserv().execute();//Los nombres de clase inician con Mayusculas
            } //fin del click view
        });
    }

    //Si no se van a usar los demas argumentos, no se definen con Void
    class Webserv extends AsyncTask<Void, Void, String> {
        public String NAMESPACE = "http://ONControl_MobileWS/"; // esto puede ser una constante global 
        public String METHOD_NAME = "Login"; // esto puede ser una constante global 
        public String SOAP_ACTION = "http://ONControl_MobileWS/Login"; // esto puede ser una constante global 
        public String SOAP_ADDRESS;
        private SoapObject request;
        private HttpTransportSE transporte;
        private SoapSerializationEnvelope envelope;

        @Override
        protected String doInBackground(Void ...voids) {
            return login();// nombres de metodos inician con minuscula
        }

        protected void onPreExecute() {
            Log.i(TAG, "onPreExecute");
            pDialog = new ProgressDialog(Principal.this);
            pDialog.setMessage("Iniciando sesion ...");
            pDialog.setIndeterminate(false);
            pDialog.setMax(10);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        protected void onPostExecute(String result) {
            //utiliza el patron de diseño de AsyncTask, la respuesta viene en la variable result
            // mostramos la respuesta en un toast
            Toast.makeText(Principal.this.getBaseContext(), result, Toast.LENGTH_SHORT).show();

            if (result.equals("Gracias por Iniciar Sesion")) {
                Principal.this.usuario.getText().toString();
                Principal.this.usuario.setText("");
                Principal.this.password.setText("");
                //envia al otro activity
                Intent intent = new Intent("android.intent.menu");
                startActivity(intent);
                finish();
            }
            //El llamado a un Toast (o era solo a Dialogs?) después de un finish() puede provocar un error "Activity has leaked window that was originally added"
            Toast.makeText(Principal.this, "Tarea finalizada!", Toast.LENGTH_SHORT).show();
        }

        //Para hacerlo de forma correcta el método login debe retornar por si mismo el response en un String
        public String login() {
            SOAP_ADDRESS = "http://oncontrol.no-ip.net:9020/ONControl_MobileWS.asmx";// esto puede ser una constante global e incluso ser un parametro de entrada del AsyncTask
            request = new SoapObject(NAMESPACE, METHOD_NAME);
            PropertyInfo pi = new PropertyInfo();
            envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            transporte = new HttpTransportSE(SOAP_ADDRESS);
            request.addProperty("usuario", usuario.getText().toString());
            request.addProperty("password", password.getText().toString());

            try {
                transporte.call(SOAP_ACTION, envelope);
                SoapPrimitive resultado_xml = (SoapPrimitive) envelope.getResponse();
                return resultado_xml.toString(); //se retorna el resultado aprovechando la definicion del AsyncTask
            } catch (Exception e) {
                Log.e(TAG, "Error: " + e.getMessage());
                return e.getMessage(); // se puede desplegar un mensaje mas definido
            }
        }
    }
}

I have only modified your code by freehand, I have not passed it through any compiler. You will notice that variables such as res and msje are no longer necessary.

    
answered by 15.04.2016 в 07:27