0

I am new in android development.

Right now I have public class for execute HTTP Request (REST web service)

The problem is that I don't know how to use AsyncTask so whenever the request process take a long time it makes the application not responding and freeze.

here is my code

public class RESTClient {

private ArrayList<NameValuePair> params;
private ArrayList <NameValuePair> headers;

private String url;

private int responseCode;
private String message;

private String response;

public String getResponse() {
    return response;
}

public String getErrorMessage() {
    return message;
}

public int getResponseCode() {
    return responseCode;
}

public enum RequestMethod
{
    GET,
    POST,
    PUT,
    DELETE
}

public RESTClient(String url)
{
    this.url = url;
    params = new ArrayList<NameValuePair>();
    headers = new ArrayList<NameValuePair>();
}

public void AddParam(String name, String value)
{
    params.add(new BasicNameValuePair(name, value));
}

public void AddHeader(String name, String value)
{
    headers.add(new BasicNameValuePair(name, value));
}

public void Execute(RequestMethod method) throws Exception
{
    switch(method) {
        case GET:
        {
            //add parameters
            String combinedParams = "";
            if(!params.isEmpty()){
                combinedParams += "?";
                for(NameValuePair p : params)
                {
                    String paramString = URLEncoder.encode(p.getValue(), "UTF-8");
                    if(combinedParams.length() > 1)
                    {
                        combinedParams  +=  "|" + paramString;
                    }
                    else
                    {
                        combinedParams += paramString;
                    }
                }
            }

            HttpGet request = new HttpGet(url);
            executeRequest(request, url);
            break;
        }
        case POST:
        {
            HttpPost request = new HttpPost(url);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }

            if(!params.isEmpty()){
                NameValuePair param = params.get(0);
                String val = param.getValue();

                StringEntity data = new StringEntity("{\"Value\": \"" + val + "\"}");
                data.setContentType("application/json");
                request.setEntity(data);
            }

            executeRequest(request, url);
            break;
        }
        case PUT:
        {
            HttpPut request = new HttpPut(url);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }

            if(!params.isEmpty()){
                NameValuePair param = params.get(0);
                String val = param.getValue();

                StringEntity data = new StringEntity("{\"Value\": \"" + val + "\"}");
                data.setContentType("application/json");
                request.setEntity(data);
            }

            executeRequest(request, url);
            break;
        }
        case DELETE:
        {
            HttpDelete request = new HttpDelete(url);

            //add parameters
            String combinedParams = "";
            if(!params.isEmpty()){
                combinedParams += "?";
                for(NameValuePair p : params)
                {
                    String paramString = URLEncoder.encode(p.getValue(), "UTF-8");
                    if(combinedParams.length() > 1)
                    {
                        combinedParams  +=  "|" + paramString;
                    }
                    else
                    {
                        combinedParams += paramString;
                    }
                }
            }

            executeRequest(request, url);
            break;
        }
    }
}

private void executeRequest(HttpUriRequest request, String url)
{

   HttpClient client = new DefaultHttpClient();

    HttpResponse httpResponse;
    try {

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        httpResponse = client.execute(request);
        responseCode = httpResponse.getStatusLine().getStatusCode();
        message = httpResponse.getStatusLine().getReasonPhrase();

        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {

            InputStream instream = entity.getContent();
            response = convertStreamToString(instream);

            // Closing the input stream will trigger connection release
            instream.close();
        }

    } catch (ClientProtocolException e)  {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    } catch (IOException e) {
        client.getConnectionManager().shutdown();
        e.printStackTrace();

    }
}


private static String convertStreamToString(InputStream is) {

    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();
}
}

Is there any way to include asyncTask process into my class ?

--EDITED-- after using mad sciendtist

public class RESTClient  {

private ArrayList<NameValuePair> params;
private ArrayList <NameValuePair> headers;
private String url;
private int responseCode;
private String message;

ProgressDialog progressBar;
private String response;
private Context mContext;

public String getResponse() {
    return response;
}

public String getErrorMessage() {
    return message;
}

public int getResponseCode() {
    return responseCode;
}

public enum RequestMethod
{
    GET,
    POST,
    PUT,
    DELETE
}

public RESTClient(String url)
{
    this.url = url;
    params = new ArrayList<NameValuePair>();
    headers = new ArrayList<NameValuePair>();
}

public void AddParam(String name, String value)
{
    params.add(new BasicNameValuePair(name, value));
}

public void AddHeader(String name, String value)
{
    headers.add(new BasicNameValuePair(name, value));
}

   public String Execute(RequestMethod method) throws Exception
    {
        switch(method) {
            case GET:
            {
                //add parameters
                String combinedParams = "";
                if(!params.isEmpty()){
                    combinedParams += "?";
                    for(NameValuePair p : params)
                    {
                        String paramString = URLEncoder.encode(p.getValue(), "UTF-8");
                        if(combinedParams.length() > 1)
                        {
                            combinedParams  +=  "|" + paramString;
                        }
                        else
                        {
                            combinedParams += paramString;
                        }
                    }
                }

                HttpGet request = new HttpGet(url);
                // IM CALLING THE ASYNCTASK HERE
              return new HttpRequest(request, url).get();

                break;
            }
            default:
                return "";
            break;

        }
    }
private void executeRequest(HttpUriRequest request, String url)
{
   HttpClient client = new DefaultHttpClient();

    HttpResponse httpResponse;
    try {

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        httpResponse = client.execute(request);
        responseCode = httpResponse.getStatusLine().getStatusCode();
        message = httpResponse.getStatusLine().getReasonPhrase();

        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {

            InputStream instream = entity.getContent();
            response = convertStreamToString(instream);

            // Closing the input stream will trigger connection release
            instream.close();
        }

    } catch (ClientProtocolException e)  {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    } catch (IOException e) {
        client.getConnectionManager().shutdown();
        e.printStackTrace();

    }
}


private static String convertStreamToString(InputStream is) {

    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();
}

private class HttpRequest extends AsyncTask<HttpUriRequest,Void, String> {

    private HttpUriRequest httpUriRequest;
    private String url;
    public HttpRequest(HttpUriRequest httpUriRequest , String url) {
        this.httpUriRequest = httpUriRequest;
        this.url = url;
    }

    @Override
    protected String doInBackground(HttpUriRequest... params) {

        // perform all network task on a different thread (i.e not on the main thread)
        HttpClient client = new DefaultHttpClient();
        String response=null;
        HttpResponse httpResponse;
        try {

            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
            httpResponse = client.execute(httpUriRequest);
            responseCode = httpResponse.getStatusLine().getStatusCode();
            message = httpResponse.getStatusLine().getReasonPhrase();

            HttpEntity entity = httpResponse.getEntity();

            if (entity != null) {

                InputStream instream = entity.getContent();
                response = convertStreamToString(instream);

                // Closing the input stream will trigger connection release
                instream.close();
            }

        } catch (ClientProtocolException e)  {
            client.getConnectionManager().shutdown();
            e.printStackTrace();
        } catch (IOException e) {
            client.getConnectionManager().shutdown();
            e.printStackTrace();

        }
        // return the response;
        return response;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // do not forget to add a progress dialog here or a progressbar

    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (!TextUtils.isEmpty(s)){
            // on succesfull callback. hide the progres bar or dialog

        }
    }


}

}

and this is my activity when calling async restclient, and i need to get the response json back

Login.Java

public class Login extends AppCompatActivity  {

private static String URLService;
// UI references.
private EditText USERID;
private EditText PASSWORD;
private View mProgressView;
private View mLoginFormView;
public static String UserID;
private static String Version="3.0";
private String VersionID;
private String VersionStatus;
private String hashed="";
private String Enc_Pass="";
private int responseCode;
Context context;
ProgressDialog mProgressDialog;
private String message;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    // Set up the login form.
    USERID = (EditText)findViewById(R.id.userID);
    //populateAutoComplete();
    URLService = getString(R.string.URLService);
    Enc_Pass = getString(R.string.password_encryption);
    PASSWORD = (EditText) findViewById(R.id.password);
    Button LOGINBUTTON = (Button) findViewById(R.id.email_sign_in_button);
    LOGINBUTTON.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            attemptLogin();
        }
    });

    mProgressView = findViewById(R.id.login_progress); 
    SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE);
    UserID = pref.getString("userId", "");
    if (!UserID.toString().equals(""))
    {
        Intent i = new Intent(Login.this, Index.class);
        startActivity(i);
    }
    else
    {
    }
}
private void attemptLogin() {

    // Reset errors.
    USERID.setError(null);
    PASSWORD.setError(null);
    // Store values at the time of the login attempt.

        try {
            String valueEncrypt = strUserId + "|" + strPassword;
            String encc  = "";
             try {
                  encc = AndroidCrypt.encrypt(Enc_Pass,valueEncrypt);
                  encc = encc.replace("+", "%2B");
            }catch (GeneralSecurityException e){
                //handle error
            }

       //     new BigProccess(Login.this, ProgressDialog.STYLE_SPINNER).execute();
          //  new HttpRequestMet(URLService+"do?method=dologin&value=" +encc,"GET").execute();
            RESTClient client = new RESTClient(URLService+"do?method=dologin&value=" +encc);

            client.Execute(RESTClient.RequestMethod.GET);

            String response = client.getResponse();

            response = response.replace("\\\"", "\"");
            response = response.substring(1, response.length() - 1);

            JSONParser jsonParser = new JSONParser();
            JSONObject jsonObject = (JSONObject) jsonParser.parse(response);
            Status = jsonObject.get("Status").toString();

            if (Status == "true") {

                String dataku = jsonObject.get("Data").toString();

                 try {
                 dataku = AndroidCrypt.decrypt(Enc_Pass, dataku);
                 }catch (GeneralSecurityException e){
                     //handle error - could be due to incorrect password or tampered encryptedMsg
                 }

                JSONParser parser = new JSONParser();
                JSONObject structure = (JSONObject) parser.parse(dataku);


                Toast.makeText(getApplicationContext(), "Welcome Back Mr./Mrs. " + FullName,
                        Toast.LENGTH_SHORT).show();

                Intent i = new Intent(Login.this, Index.class);
                startActivity(i);
                //  finish();



            } else {
                Toast.makeText(getApplicationContext(), "Login Failed",
                        Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(),"Cant Connect to server, please try again later",
                    Toast.LENGTH_SHORT).show();
        }
    }


}

}

MadScientist
  • 2,134
  • 14
  • 27
gilllsss
  • 97
  • 2
  • 11

2 Answers2

0

Simply put your network operation inside an AsyncTask,

class HTTPAsyncTask extends AsyncTask<String, Void, Boolean> {

@Override
protected void onPreExecute() {
    super.onPreExecute();

}

@Override
protected Boolean doInBackground(String... urls) {
     HttpGet request = new HttpGet(url);
     executeRequest(request, url);
     return false;
}

protected void onPostExecute(Boolean result) {

}

To execute the AsyncTask anywhere from the class write,

new HTTPAsyncTask().execute("");
Prokash Sarkar
  • 11,723
  • 1
  • 37
  • 50
0

Welcome to Android Dev, There's a main thread in Android (the UI thread) where all the view operations takes place. It is recommended that no heavy computation or FileSystem operations or NetworkTasks be performed on these threads, as views are dependent on this thread.

So as a solution to this problem, android has support for Worker threads which is made to handle these heavy operations.

AsyncTask is a good way to implement this structure. Read the doc here

As far as your code goes, you can create a new class in the same file

private class HttpRequest extends AsyncTask<Void,Void, String>{

private HttpUriRequest httpUriRequest;
private String url;
public HttpRequest(HttpUriRequest httpUriRequest , String url) {
    this.httpUriRequest = httpUriRequest;
    this.url = url;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
    // do not forget to add a progress dialog here or a progressbar
    progressBar.show();
}

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    if (!TextUtils.isEmpty(s)){
        // on succesfull callback. hide the progres bar or dialog
        progressBar.gone();
    }
}

@Override
protected String doInBackground(Void... voids) {

    // perform all network task on a different thread (i.e not on the main thread)
    HttpClient client = new DefaultHttpClient();
    String response=null;
    HttpResponse httpResponse;
    try {

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        httpResponse = client.execute(request);
        responseCode = httpResponse.getStatusLine().getStatusCode();
        message = httpResponse.getStatusLine().getReasonPhrase();

        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {

            InputStream instream = entity.getContent();
            response = convertStreamToString(instream);

            // Closing the input stream will trigger connection release
            instream.close();
        }

    } catch (ClientProtocolException e)  {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    } catch (IOException e) {
        client.getConnectionManager().shutdown();
        e.printStackTrace();

    }
    // return the response;
    return response;
}
}

And all you have to do is call initiate this class using the custom Contructor

ex. new HttpRequest(httpUriRequest, url).execute(); and handled the response in the onPostExecute() method.

Also, since you're new, a small recommendation, try naming method names with the first letter as a lowercase one, this way you will be able to distinguish a class from its methods.

And try Retrofit its way cool then the native way for HttpRequests

MadScientist
  • 2,134
  • 14
  • 27
  • hai , i tried that, but it dont directly go to doInBackground, i dont knwo why. so i get the catch exception first. and also didnt get the response – gilllsss Mar 03 '17 at 03:54
  • Can you post the exception. And also your original code. Try using [Pastebin](http://pastebin.ubuntu.com/) – MadScientist Mar 03 '17 at 06:12
  • I already update my post, please kindly check. and also i need to return the response back to my activity to get the json data. how can i do that? thx b4 – gilllsss Mar 03 '17 at 06:34
  • The edit look fine. Two things to make sure: 1. Please add the **ProgressBar** loading inside the `onPreExecute()` sometimes if the network request is large then you get an ANR if no progress is shown. 2. Make sure you log everything. use the studio logi shortcut inside all the three methods of the AsyncTask class. comment all your code before you do this, this is just to check whether your AsyncTask works properly or not. also, can you send me the stacktrace via the pastebin – MadScientist Mar 03 '17 at 06:49
  • And to send the result back to the calling activity, if its the same activity use the `new HttpRequest(Strings... ).get()` method. if its a different activity, setResult for the `onPostExecute()` method refer [this](http://stackoverflow.com/questions/42445890/how-do-i-add-data-i-have-keyed-in-a-edittext-box-into-an-array-to-list-in-anothe/42572204#42572204) – MadScientist Mar 03 '17 at 06:53
  • id try to put progress bar in prexecuted but it give me error java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ProgressDialog.show()' on a null object reference – gilllsss Mar 03 '17 at 07:03
  • and in the DoInBackgorund, i already put return response, that i wanted to get – gilllsss Mar 03 '17 at 07:05
  • Yes the response you return from doinbackground sends it to the onPostExecute() from there you have to send it to the calling class or you can use the AsyncTask **get()** method. Try logging the response inside the onPostExecute method – MadScientist Mar 03 '17 at 07:08
  • And as far as the progressbar goes, did you add it to the XML View? :D in the calling activity, add a view then using findViewById() method. Then setVisibiltiy to that view. ex. `ProgressBar progressBar;` assuming the view is added. then inside onPreExcute() just do this `progressBar.setVisibility(View.VISIBLE); – MadScientist Mar 03 '17 at 07:10
  • ive put my full Login.java for the activity, please review it, and also i put progress bar too. but it triggered from the RESTClient, how can i show it in the activity? – gilllsss Mar 03 '17 at 07:17