0

I'm stuck again need help from you guys. I'm getting NetworkOnMainThreadException exception at getting response from my service. I'm still learning Android so don't know the nutty gritty of threading in Android. Any help with explanation and working example would be great. Thanks in advance, you guys are awesome help.

package com.abcd.myapp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.util.Log;

public class RequestManager {

    String baseUrl = "http://dev.mysite.com/Service/MyService.svc/";

    public String GetResponse(String url) {
        String responseText = "";
        // Create a HTTP client 
        HttpClient httpClient = new DefaultHttpClient(); 
        HttpGet httpGet = new HttpGet(baseUrl + url);

        try {
            // get the response 
            HttpResponse response = httpClient.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                InputStream is = entity.getContent();               
                BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
                // Create a buffer 
                StringBuilder sb = new StringBuilder();

                String line;
                while((line = reader.readLine()) != null) {                 
                    sb.append(line + "\n");
                }

                is.close();
                responseText = sb.toString();
                // do something with response 
            } else {
                Log.d("RequestManager", "Error fetching data. Server returned status code: {0}"+ statusLine.getStatusCode());
                // handle bad response
            }
        } catch (ClientProtocolException e) {
            // handle exception
             e.printStackTrace(); 
        } catch (IOException e) {
            // handle exception
             e.printStackTrace(); 
        }
        return responseText.toString(); 
    }
}

My Activity Class:

package com.abcd.myapp;

import java.util.HashSet;
import java.util.Set;

import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class CheckEmailActivity  extends Activity {

    EditText txtEmail;
    Button btnGo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.check_email);
        btnGo = (Button) findViewById (R.id.btnGo);
        txtEmail = (EditText)findViewById (R.id.tbCheckEmail);
        btnGo.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(txtEmail.getWindowToken(), 0);

                if (TextUtils.isEmpty(txtEmail.getText()))
                {
                    String msg = "Oops! Please enter your email.";
                    Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
                }
                else
                {
                    String email = txtEmail.getText().toString().toLowerCase();
                    String response = "";
                    RequestManager rm = new RequestManager();
                    String x = "";

                    try
                    {
                        String url = "CheckEmail///" + email;
                        response = rm.GetResponse(url);
                        JSONObject obj = new JSONObject(response);

                        x = obj.getString("CheckEmailResult");
                        if (x == "1")
                        {
                            //Send Confirmation Email
                            String msg = "Please check your email.";

                            SharedPreferences prefAccount = getApplicationContext().getSharedPreferences("CoDiAccount", Context.MODE_PRIVATE);

                            Set<String> newq = new HashSet<String>();
                            newq = prefAccount.getStringSet("Accounts", newq);
                            Editor prefEditorAccount = prefAccount.edit();
                            prefEditorAccount.putString("email", email);                        
                            newq.add(email);
                            prefEditorAccount.putStringSet("Accounts", (Set<String>) newq);
                            prefEditorAccount.commit();
                            String directoryname = "CoDiApp" + email;
                            SharedPreferences prefs = getApplicationContext().getSharedPreferences(directoryname, Context.MODE_PRIVATE);

                            Editor prefEditor = prefs.edit();
                            prefEditor.putString("login", "0");
                            prefEditor.putString("email", email);
                            prefEditor.commit();
                            Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();

                            //Validate account
                            Intent verifyAccount = new Intent(CheckEmailActivity.this, VerifyAccountActivity.class);
                            startActivity(verifyAccount);
                        }
                        else
                        {
                            String msg = "Sorry, Your email address  not found.";
                            Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                        }
                    }
                    catch (Exception ex)
                    {
                        response = ex.getMessage().toString();
                        String msg = "Network is unavailable. Please try again later." + response;
                        AlertDialog.Builder builder = new AlertDialog.Builder(CheckEmailActivity.this);
                        builder.setMessage(msg)
                               .setCancelable(false)
                               .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                   public void onClick(DialogInterface dialog, int id) {
                                        //do things
                                   }
                               });
                        AlertDialog alert = builder.create();
                        alert.setTitle("Re-Try");
                        alert.show();
                    }
                }
            }
        }) ;           
    } 
Rashid
  • 105
  • 1
  • 11

2 Answers2

0

You should make your http call in async task and also add INTERNET permission to your manifest.

You can get some information about async tasks from here: http://developer.android.com/reference/android/os/AsyncTask.html

Ps: When i have time i will edit my answer and will give a code sample.

savepopulation
  • 11,736
  • 4
  • 55
  • 80
0

You can't perform network operations on the main/UI thread. You should use an AsyncTask instead. Modify your method as follows:

String response;

public String GetResponse(String url) {
  String responseText = "";
        // Create a HTTP client 
        HttpClient httpClient;
        HttpGet httpGet;
    AsyncTask<String, Void, String> myAsyncTask = new AsyncTask<String, Void, String>() {
        @Override
        protected void onPreExecute() {

            super.onPreExecute();
         httpClient = new DefaultHttpClient(); 
    httpGet = new HttpGet(baseUrl + url);
        }

        @Override
        protected String doInBackground(String... params) {
             try {
        // get the response 
        HttpResponse response = httpClient.execute(httpGet);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();               
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
            // Create a buffer 
            StringBuilder sb = new StringBuilder();

            String line;
            while((line = reader.readLine()) != null) {                 
                sb.append(line + "\n");
            }

            is.close();
            responseText = sb.toString();
            // do something with response 
        } else {
            Log.d("RequestManager", "Error fetching data. Server returned status code: {0}"+ statusLine.getStatusCode());
            // handle bad response
        }
    } catch (ClientProtocolException e) {
        // handle exception
         e.printStackTrace(); 
    } catch (IOException e) {
        // handle exception
         e.printStackTrace(); 
    }
    return responseText.toString();

        }

        @Override
        protected void onPostExecute(String result) {
            response = result;
        }

    };//
    myAsyncTask.execute("");
}

You can't perform network operations on the main/UI thread. You should use an AsyncTask instead. Modify your method as follows:

Update:

Async tasks are asynchronous hence are executed in the background independent of the programs current UI thread. So on lines:

 response = rm.GetResponse(url);
  JSONObject obj = new JSONObject(response);

the JSONObject might be constructed before the response is fetched in GetResponse() Use the result in the onPostExecute since it executes on the UI thread. You can use this method in your activity class:

//new method in activity class to fetch result and process it

Your Activity Class:

String response;

public String getResponseAndProcess(String url) {
  String responseText = "";
        // Create a HTTP client 
        HttpClient httpClient;
        HttpGet httpGet;
    AsyncTask<String, Void, String> myAsyncTask = new AsyncTask<String, Void, String>() {
        @Override
        protected void onPreExecute() {

            super.onPreExecute();
         httpClient = new DefaultHttpClient(); 
    httpGet = new HttpGet(baseUrl + url);
        }

        @Override
        protected String doInBackground(String... params) {
             try {
        // get the response 
        HttpResponse response = httpClient.execute(httpGet);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();               
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
            // Create a buffer 
            StringBuilder sb = new StringBuilder();

            String line;
            while((line = reader.readLine()) != null) {                 
                sb.append(line + "\n");
            }

            is.close();
            responseText = sb.toString();
            // do something with response 
        } else {
            Log.d("RequestManager", "Error fetching data. Server returned status code: {0}"+ statusLine.getStatusCode());
            // handle bad response
        }
    } catch (ClientProtocolException e) {
        // handle exception
         e.printStackTrace(); 
    } catch (IOException e) {
        // handle exception
         e.printStackTrace(); 
    }
    return responseText.toString();

        }

        @Override
        protected void onPostExecute(String result) {
             try
                {
                    JSONObject obj = new JSONObject(result);

                    x = obj.getString("CheckEmailResult");
                    if (x == "1")
                    {
                        //Send Confirmation Email
                        String msg = "Please check your email.";

                        SharedPreferences prefAccount = getApplicationContext().getSharedPreferences("CoDiAccount", Context.MODE_PRIVATE);

                        Set<String> newq = new HashSet<String>();
                        newq = prefAccount.getStringSet("Accounts", newq);
                        Editor prefEditorAccount = prefAccount.edit();
                        prefEditorAccount.putString("email", email);                        
                        newq.add(email);
                        prefEditorAccount.putStringSet("Accounts", (Set<String>) newq);
                        prefEditorAccount.commit();
                        String directoryname = "CoDiApp" + email;
                        SharedPreferences prefs = getApplicationContext().getSharedPreferences(directoryname, Context.MODE_PRIVATE);

                        Editor prefEditor = prefs.edit();
                        prefEditor.putString("login", "0");
                        prefEditor.putString("email", email);
                        prefEditor.commit();
                        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();

                        //Validate account
                        Intent verifyAccount = new Intent(CheckEmailActivity.this, VerifyAccountActivity.class);
                        startActivity(verifyAccount);
                    }
                    else
                    {
                        String msg = "Sorry, Your email address  not found.";
                        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                    }
                }
                catch (Exception ex)
                {
                    response = ex.getMessage().toString();
                    String msg = "Network is unavailable. Please try again later." + response;
                    AlertDialog.Builder builder = new AlertDialog.Builder(CheckEmailActivity.this);
                    builder.setMessage(msg)
                           .setCancelable(false)
                           .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                               public void onClick(DialogInterface dialog, int id) {
                                    //do things
                               }
                           });
                    AlertDialog alert = builder.create();
                    alert.setTitle("Re-Try");
                    alert.show();
                }
            }

        }

    };//
    myAsyncTask.execute("");
}

Then in the onClick():

btnGo.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(txtEmail.getWindowToken(), 0);

            if (TextUtils.isEmpty(txtEmail.getText()))
            {
                String msg = "Oops! Please enter your email.";
                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
            }
            else
            {
                String email = txtEmail.getText().toString().toLowerCase();
                String x = "";
                String url = "CheckEmail///" + email;
                getResponseAndProcess(url);
              }
    }) ;           
}     
Nana Ghartey
  • 7,901
  • 1
  • 24
  • 26
  • Thanks Nana Ghartey. I applied your solution to my code and the exception is gone. But I'm getting a blank response from service. I'll work on my code further. Thanks anyways. – Rashid Jul 17 '14 at 13:02
  • You're welcome.It's probably from the service. Trying logging the output of each step. Thanks – Nana Ghartey Jul 17 '14 at 13:40
  • I tried the above solution but the service is unable to give a response and responseText returns an empty string. Any help? @Nana Ghartey – Rashid Jul 21 '14 at 10:47
  • What's the status of the response. Is it returning a "HttpStatus.SC_OK" code? Have you tried with a different url? – Nana Ghartey Jul 21 '14 at 11:04
  • On debugging it does not get inside the asynctask block and straight away gets out to myAsyncTask.execute("");. If you ask I can give you the real service url to try. @Nana Ghartey – Rashid Jul 21 '14 at 11:26
  • I've edited my question and added Activity class where I'm using the service response. Please have a look. – Rashid Jul 21 '14 at 12:31
  • Please check out my updated answer and let's see how it goes :) – Nana Ghartey Jul 21 '14 at 17:44
  • Thanks @Nana Ghartey .... but the service is still giving empty response where as it should give a response like: {"CheckEmailResult":"Rashid"}. I think I'm returning response in the "responseText", before it gets response from the service. Point me in right direction if I'm wrong. – Rashid Jul 22 '14 at 11:40