1

I am creating a simple app for login using Android and PHP but I get an error, can anyone help me? I am trying to make a relation between the Android as the client side and PHP/MySQL as the server side but still have not get the response successfully.

AndroidLogin.java

package com.sencide;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class AndroidLogin extends Activity implements OnClickListener {


     Button ok,back,exit;
     TextView result;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

     // Login button clicked
        ok = (Button)findViewById(R.id.btn_login);
        ok.setOnClickListener(this);

        result = (TextView)findViewById(R.id.lbl_result);



    }



    public void postLoginData() {
        // Create a new HttpClient and Post Header
        HttpClient httpclient = new DefaultHttpClient();
         Log.e("Responce-->","after httpclient");
        /* login.php returns true if username and password is equal to saranga */
        HttpPost httppost = new HttpPost("http://10.0.2.2/login.php");
        Log.e("Responce-->","after httppost");
        try {
            // Add user name and password
         EditText uname = (EditText)findViewById(R.id.txt_username);
         String username = uname.getText().toString();

         EditText pword = (EditText)findViewById(R.id.txt_password);
         String password = pword.getText().toString();

            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("username", username));
            nameValuePairs.add(new BasicNameValuePair("password", password));
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            Log.e("Responce-->","after using the list name pair");

            // Execute HTTP Post Request
            Log.w("SENCIDE", "Execute HTTP Post Request");
            HttpResponse response = httpclient.execute(httppost);
            Log.e("Responce-->","after execute the http response");
          //  String str = inputStreamToString(response.getEntity().getContent()).toString();
            String str = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
            //Log.w("SENCIDE", str);

            Log.e("Responce-->",""+str);

            if(str.toString().equalsIgnoreCase("true"))
            {
             Log.w("SENCIDE", "TRUE");
             result.setText("Login successful");  
            }else
            {
             Log.w("SENCIDE", "FALSE");
             result.setText(str);            
            }

        } catch (ClientProtocolException e) {
         e.printStackTrace();
        } catch (IOException e) {
         e.printStackTrace();
        }
    } 



    private StringBuilder inputStreamToString(InputStream is) {
        String line = "";
        StringBuilder total = new StringBuilder();
        // Wrap a BufferedReader around the InputStream
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        // Read response until the end
        try {
         while ((line = rd.readLine()) != null) {
           total.append(line);
         }
        } catch (IOException e) {
         e.printStackTrace();
        }
        // Return full string
        return total;
       }

        /* login.php returns true if username and password is equal to test1 */


    @Override
    public void onClick(View view) {
        // TODO Auto-generated method stub
        final String resultText;
        if(str.toString().equalsIgnoreCase("true")) {
            resultText = "Login successful";
        }else {
            resultText = str;
        }

        if(view == ok){
             Thread t = new Thread(){


                    public void run(){
                        postLoginData();

                        result.post(new Runnable() {
                            public void run() {
                                result.setText(resultText);
                            }
                        });
                    }
                };
                t.start();

          }
    }





}

log cat

   04-04 19:04:20.504: E/Responce-->(457): after httpclient
04-04 19:04:20.517: E/Responce-->(457): after httppost
04-04 19:04:20.544: E/Responce-->(457): after using the list name pair
04-04 19:04:20.544: W/SENCIDE(457): Execute HTTP Post Request
04-04 19:04:20.824: E/Responce-->(457): after execute the http response
04-04 19:04:20.834: E/Responce-->(457): true
04-04 19:04:20.834: W/SENCIDE(457): TRUE
04-04 19:04:20.844: W/dalvikvm(457): threadid=9: thread exiting with uncaught exception (group=0x40015560)
04-04 19:04:20.912: E/AndroidRuntime(457): FATAL EXCEPTION: Thread-10
04-04 19:04:20.912: E/AndroidRuntime(457): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.view.ViewRoot.checkThread(ViewRoot.java:2932)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.view.ViewRoot.requestLayout(ViewRoot.java:629)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.view.View.requestLayout(View.java:8267)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.view.View.requestLayout(View.java:8267)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.view.View.requestLayout(View.java:8267)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.view.View.requestLayout(View.java:8267)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.view.View.requestLayout(View.java:8267)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.widget.TextView.checkForRelayout(TextView.java:5521)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.widget.TextView.setText(TextView.java:2724)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.widget.TextView.setText(TextView.java:2592)
04-04 19:04:20.912: E/AndroidRuntime(457):  at android.widget.TextView.setText(TextView.java:2567)
04-04 19:04:20.912: E/AndroidRuntime(457):  at com.sencide.AndroidLogin$1.run(AndroidLogin.java:136)
04-04 19:04:23.464: I/Process(457): Sending signal. PID: 457 SIG: 9

php code

<?php
$host="localhost"; // Host name
$username="root"; // Mysql username
$password="root"; // Mysql password
$db_name="testlogin"; // Database name
$tbl_name="members"; // Table name

// Connect to server and select databse.
mysql_connect("$host", "$username", "$password")or die("cannot connect");
mysql_select_db("$db_name")or die("cannot select DB");

// username and password sent from form
$myusername=$_POST['username'];
$mypassword=$_POST['password'];

// To protect MySQL injection
$myusername = stripslashes($myusername);
$mypassword = stripslashes($mypassword);
$myusername = mysql_real_escape_string($myusername);
$mypassword = mysql_real_escape_string($mypassword);

$sql="SELECT * FROM $tbl_name WHERE username='$myusername' and password='$mypassword'";
$result=mysql_query($sql);

// Mysql_num_row is counting table row
$count=mysql_num_rows($result);

// If result matched $myusername and $mypassword, table row must be 1 row
if($count==1){
echo "true";
}
else {
echo "Login Failed";
}
?>
user2214618
  • 51
  • 1
  • 1
  • 12
  • Not an Android programmer myself, but that error message (now in the title of the question) is pretty clear. Seems like you are accessing something that is private to another thread. Have you [searched for it](https://duckduckgo.com/?q=Only+the+original+thread+that+created+a+view+hierarchy+can+touch+its+views)? - plenty of results there. – halfer Apr 04 '13 at 18:59
  • you can not modify UI widgets outside of UI thread. only the UI thread can do it and yet run result.setText(str); on a new thread. runOnUIThread() may help you but i would also remove the `public void postLoginData()` method body off the onClick() method it looks that it was created inside of onClick() which is weird. – Sergey Benner Apr 04 '13 at 21:10
  • @SergeyBenner i edit the androidlogin.java take a look but the problem is that i get that the string str can not be resolved because the str is initialize within the postlogindata () method – user2214618 Apr 04 '13 at 21:29
  • i changed your code see if works for you. add your `package` too. dont forget it. – Sergey Benner Apr 04 '13 at 21:51

3 Answers3

2

The solution is in the log from logcat:

04-04 18:38:47.596: E/AndroidRuntime(413): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Posting user/password is working. You get the "true" response alright, but then you try to set a label or similar, in a view that was created outside the thread. That's a no-no.

result.setText("Login successful");

Look at the Android SDK docs about threads/processes on how to update views from other threads: http://developer.android.com/guide/components/processes-and-threads.html

vidario
  • 479
  • 2
  • 5
1

You may not make changes to android views off the main UI thread. In your example you are starting a new thread and running postLoginData() on it. Because postLoginData ALSO sets the text of a textview you get this error.

You should: do the http request on your new thread, then on the UI thread change the text.

There are a variety of ways to do this.

And this super simple but probably not advised way to do it to just get you on your feet. Yo will want to do this anytime you are making a change inside your new thread to the UI, so in this example when you are setting the text of result.

result.post(new Runnable() {
        public void run() {
            result.setText(str);
        }
    });
}

Which will run on the UI thread. You really should look at the two options I posted first or you will just run into more trouble.

** edit ** You need to just replace this code to publish on the main thread instead of the new thread.

if(str.toString().equalsIgnoreCase("true"))
{
 Log.w("SENCIDE", "TRUE");
 result.setText("Login successful");  
}else
{
 Log.w("SENCIDE", "FALSE");
 result.setText(str);            
}

Make it look like this:

final String resultText;
if(str.toString().equalsIgnoreCase("true")) {
    resultText = "Login successful";
}else {
    resultText = str;
}
result.post(new Runnable() {
        public void run() {
            result.setText(resultText);
        }
    });
}
sgarman
  • 6,152
  • 5
  • 40
  • 44
1

OK I made some modifications to your code it's still ugly and requires lots of refactoring but tell me if it throws any exceptions.

EDIT: Added your username and password passing to the request as parameters to your postLoginData(String password,String username) method. That should do it.


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class AndroidLogin extends Activity implements OnClickListener {


    Button ok, back, exit;
    TextView result;
    EditText uname;
    EditText pword;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        StrictMode.ThreadPolicy policy = 
        new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        // Login button clicked
        ok = (Button) findViewById(R.id.btn_login);
        ok.setOnClickListener(this);
        uname = (EditText) findViewById(R.id.txt_username);
        pword = (EditText) findViewById(R.id.txt_password);
        result = (TextView) findViewById(R.id.lbl_result);


    }

    @Override
    public void onClick(View view) {
        // TODO Auto-generated method stub
        final String resultText;   

        final String username = uname.getText().toString();           
        final String password = pword.getText().toString();


        if (view == ok) {
            Thread t = new Thread() {

                public void run() {
                    postLoginData(username,password);
                }
            };
            t.start();

        }
    }

    private void postLoginData(String username,String password) {

        try {
            // Create a new HttpClient and Post Header
            HttpClient httpclient = new DefaultHttpClient();
            Log.e("Response-->", "after httpclient");
        /* login.php returns true if username and password is equal to saranga */
            HttpPost httppost = new HttpPost("http://10.0.2.2/login.php");
            Log.e("Response-->", "after httppost");


            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("username", username));
            nameValuePairs.add(new BasicNameValuePair("password", password));

            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            Log.e("Responce-->", "after using the list name pair");

            // Execute HTTP Post Request
            Log.w("SENCIDE", "Execute HTTP Post Request");
            HttpResponse response = httpclient.execute(httppost);
            Log.e("Responce-->", "after execute the http response");
            String str = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);

            if (str.toString().equalsIgnoreCase("true")) {

                runOnUiThread(new Runnable() {
                    public void run() {
                        result.setText("Login Successful");

                    }
                });


            } else {
                runOnUiThread(new Runnable() {
                    public void run() {
                        result.setText("Duh");

                    }
                });
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}
Sergey Benner
  • 4,421
  • 2
  • 22
  • 29
  • this code work somehow but it just display these msg **04-04 22:02:40.218: E/Response-->(578): after httpclient 04-04 22:02:40.224: E/Response-->(578): after httppost 04-04 22:02:40.254: E/Responce-->(578): after using the list name pair 04-04 22:02:40.254: W/SENCIDE(578): Execute HTTP Post Request 04-04 22:02:40.484: E/Responce-->(578): after execute the http response** without getting Login Successful or Duh – user2214618 Apr 04 '13 at 22:04
  • somehow... :))) you have to print out your `str` e.g `Log.d("str",str);` variable after `EntityUtils.toString` line and see what's in there. what you're receiving in your response and then basing on that make your condition. – Sergey Benner Apr 04 '13 at 23:00
  • it print true but i mean in the app it must display a login successful why it did not can you help me i know i am bothering you thank you – user2214618 Apr 04 '13 at 23:57
  • ok now it workkk very good thank you – user2214618 Apr 05 '13 at 00:02