2

I'm putting together my first Android application, which is also my introduction to the Java programming language, and so I'm stumbling over what may be some very basic concepts.

My plan is to set up a server full of php functions and place all the php calls within a single static function library. I could change that static class to singleton if it simplifies this issue.

From within an activity, I'm making the following call:

phpCalls.VerifyAccount(userName, password);

and within the phpCalls static class, I've got the following code:

    PHP_AsyncTask validateAccountTask = new PHP_AsyncTask();
    validateAccountTask.execute(new String[] {DOMAIN + PHP_confirm_account_exists, username, password});

and

private static class PHP_AsyncTask extends AsyncTask<String, Void, String>{
    //This class should take the full URL of the php function to call and return the string result. Somehow.
    @Override
    protected String doInBackground(String... args)
    {
        String response = "";

        try
        {
            String url = args[0];
            String username = args[1];
            String password = args[2];
            URL validateURL = new URL(url);
            String credentials = "Basic " + new String(Base64.encode((username + ":" + password).getBytes(), Base64.NO_WRAP)) ;

            //TODO: handle 501 result
            HttpURLConnection conn = (HttpURLConnection)validateURL.openConnection();
            conn.setDoOutput(true);
            conn.setRequestProperty("Authorization",credentials);

            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;

            while ((line = reader.readLine()) != null)
            {
                response += line;
            }
            reader.close();
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }

        return response;
    }


    @Override
    protected void onPostExecute(String result)
    {
        //have something happen when the php returns - need to pass the result somewhere
    }

Sorry if the formatting on the code is less than ideal - I'm not a regular poster on Stackoverflow.

Anyway, I'm trying to determine how best to handle the result from the php call - it's being returned to the onPostExecute function of the PHP_AsyncTask class as result, but I need to somehow pass it back to the UI thread. Apparently I can't create a pointer to a function within my activity and pass that through to the async class. Is there a way to create a listener within my activity and pass that along so that I can pass the result from PHP_AsyncTask back to my activity? Or am I completely barking up the wrong tree - is there some preferable approach which I should be pursuing?

Marvin Pinto
  • 30,138
  • 7
  • 37
  • 54
Greg
  • 83
  • 5

2 Answers2

2

1) onPostExecute is in UI thread

2) Instead of pointer to function you can pass pointer to interface. For example, if you have have such interface

public interface Listener{
    public void someFunc(String response);
}

you can pass as parameter any class that implements that interface. For example if your method is

public void sendRequest(Listener listener);

you can pass as listener your class:

public class SomeClass implements Listener{
    public void someFunc(String response){
        //do stuff
    }
}

like that

sendRequest(new SomeClass());

PS I didn't use AsyncTask in my answer, but I hope you'll get the idea

Dmitry Zaytsev
  • 23,650
  • 14
  • 92
  • 146
  • Thanks for pointing out that onPostExecute is in the UI thread - that's an important distinction. – Greg Jan 31 '12 at 14:04
0

So I don't have anyway to test this out right now but here is what I would do.

Create an interface for the listener

public interface MyListener {
    public void onDone(String response);
}

From the activity call VerifyAccount like so

phpCalls.VerifyAccount(userName,password, new MyListener() {
    @Override
    public void onDone(String response) {
        //do stuff
    }
});

Then change the constructor for PHP_AsyncTask to take in one paramater, the interface you created. Change the method signature for VerifyAccount to take the additional parameter and pass it into the new PHP_AsyncTask you created.

private static class PHP_AsyncTask extends AsyncTask<String, Void, String>{ 
    private MyListener listener;
    public PHP_AsyncTask (MyListener listener) {
        this.listener = listener;
    }

   .....

   @Override
   protected void onPostExecute(String result)
   {
      listener.onDone(result);
   }
}
Danny
  • 7,368
  • 8
  • 46
  • 70
  • So just to confirm - you're saying that I'll need to make sure that PHP_AsyncTask isn't static. Correct? – Greg Jan 31 '12 at 14:09
  • I've managed to thoroughly confused myself. I now realize now that my original code example declares a new PHP_AsyncTask inside what I determined was going to be a static class. Not sure of the legality or efficiency of that, but it's not even my primary problem at this point, although it's likely a show-stopper. I've created the listener and implemented it. But my issue with that setup is that the implementation is inside the phpCalls class, and I need to return control back to the calling (non-static) function. – Greg Jan 31 '12 at 16:26
  • @Greg I am thoroughly confused too. Sorry :-(. new PHP_AsyncTask is acceptable. Making PHP_AsyncTask a static class does not mean that it's methods are static. It just allow the class to be instantiated independently of it's enclosing class. I modified the code above a bit to show you how you can create the new PHP_AsyncTask and receive the callback within a static method. – Danny Jan 31 '12 at 18:05
  • It might be worthwhile to look at http://mindprod.com/jgloss/static.html since this is your introduction to java. – Danny Jan 31 '12 at 18:12