Kirara
Kirara

Reputation: 103

Android Honeycomb Strict Mode crashes app despite being AsyncTask

I am trying to run my app on a 3.2 Android Device (Honeycomb).

Unfortunately, my app crashes whenever I try to edit one of the objects listed in my app using EditCaseActivity. Logcat seems to tell me that StrictMode is causing the crash, but I'm already using AsyncTask.

Any form of help is greatly appreciated! :)

My friend suspects that it has something to do with RunOnUiThread, but trying to edit away the RunOnUiThread of the code brings me errors with 'params' in lines 126 and 127.

EditCaseActivity.java

package com.pivestigator.cases;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.pivestigator.JSONParser;
import com.pivestigator.R;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class EditCaseActivity extends Activity {

    EditText txtCaseName;
    EditText txtCaseUser;
    EditText txtCaseCategory;
    EditText txtCreatedAt;
    Button btnSave;
    Button btnDelete;

    String cid;

    // Progress Dialog
    private ProgressDialog pDialog;

    // JSON parser class
    JSONParser jsonParser = new JSONParser();

    // single case url
    private static final String url_case_details = "http://nsecure.5gbfree.com/PIvestigator/case/get_case_details.php";

    // url to update case
    private static final String url_update_case = "http://nsecure.5gbfree.com/PIvestigator/case/update_case.php";

    // url to delete case
    private static final String url_delete_case = "http://nsecure.5gbfree.com/PIvestigator/case/delete_case.php";

    // JSON Node names
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_CASE = "case";
    private static final String TAG_CID = "cid";
    private static final String TAG_CASE_NAME = "case_name";
    private static final String TAG_CASE_USER = "case_user";
    private static final String TAG_CASE_CATEGORY = "case_category";

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

        // save button
        btnSave = (Button) findViewById(R.id.btnSave);
        btnDelete = (Button) findViewById(R.id.btnDelete);

        // getting case details from intent
        Intent i = getIntent();

        // getting case id (cid) from intent
        cid = i.getStringExtra(TAG_CID);

        // Getting complete case details in background thread
        new GetCaseDetails().execute();

        // save button click event
        btnSave.setOnClickListener(new View.OnClickListener() {

            public void onClick(View arg0) {
                // starting background task to update case
                new SaveCaseDetails().execute();
            }
        });

        // Delete button click event
        btnDelete.setOnClickListener(new View.OnClickListener() {

            public void onClick(View arg0) {
                // deleting case in background thread
                new DeleteCase().execute();
            }
        });

    }

    /**
     * Background Async Task to Get complete case details
     * */
    class GetCaseDetails extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditCaseActivity.this);
            pDialog.setMessage("Loading case details. Please stare at spinner to increase loading speed...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Getting case details in background thread
         * */
        protected String doInBackground(String... params) {

            // updating UI from Background Thread
            runOnUiThread(new Runnable() {
                public void run() {
                    // Check for success tag
                    int success;
                    try {
                        // Building Parameters
                        List<NameValuePair> params = new ArrayList<NameValuePair>();
                        params.add(new BasicNameValuePair("cid", cid));

                        // getting case details by making HTTP request
                        // Note that case details url will use GET request
                        JSONObject json = jsonParser.makeHttpRequest(
                                url_case_details, "GET", params);

                        // check your log for json response
                        Log.d("Single Case Details", json.toString());

                        // json success tag
                        success = json.getInt(TAG_SUCCESS);
                        if (success == 1) {
                            // successfully received case details
                            JSONArray caseObj = json
                                    .getJSONArray(TAG_CASE); // JSON Array

                            // get first case object from JSON Array
                            JSONObject cases = caseObj.getJSONObject(0);

                            // case with this cid found
                            // Edit Text
                            txtCaseName = (EditText) findViewById(R.id.inputCaseName);
                            txtCaseUser = (EditText) findViewById(R.id.inputCaseUser);
                            txtCaseCategory = (EditText) findViewById(R.id.inputCaseCategory);

                            // display case data in EditText
                            txtCaseName.setText(cases.getString(TAG_CASE_NAME));
                            txtCaseUser.setText(cases.getString(TAG_CASE_USER));
                            txtCaseCategory.setText(cases.getString(TAG_CASE_CATEGORY));

                        }else{
                            // case with cid not found
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog once got all details
            pDialog.dismiss();
        }
    }

    /**
     * Background Async Task to  Save case Details
     * */
    class SaveCaseDetails extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditCaseActivity.this);
            pDialog.setMessage("Saving case ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Saving case
         * */
        protected String doInBackground(String... args) {

            // getting updated data from EditTexts
            String case_name = txtCaseName.getText().toString();
            String case_user = txtCaseUser.getText().toString();
            String case_category = txtCaseCategory.getText().toString();

            // Building Parameters
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair(TAG_CID, cid));
            params.add(new BasicNameValuePair(TAG_CASE_NAME, case_name));
            params.add(new BasicNameValuePair(TAG_CASE_USER, case_user));
            params.add(new BasicNameValuePair(TAG_CASE_CATEGORY, case_category));

            // sending modified data through http request
            // Notice that update case url accepts POST method
            JSONObject json = jsonParser.makeHttpRequest(url_update_case,
                    "POST", params);

            // check json success tag
            try {
                int success = json.getInt(TAG_SUCCESS);

                if (success == 1) {
                    // successfully updated
                    Intent i = getIntent();
                    // send result code 100 to notify about case update
                    setResult(100, i);
                    finish();
                } else {
                    // failed to update case
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog once case updated
            pDialog.dismiss();
        }
    }

    /*****************************************************************
     * Background Async Task to Delete Case
     * */
    class DeleteCase extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditCaseActivity.this);
            pDialog.setMessage("Deleting Case...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Deleting case
         * */
        protected String doInBackground(String... args) {

            // Check for success tag
            int success;
            try {
                // Building Parameters
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                params.add(new BasicNameValuePair("cid", cid));

                // getting case details by making HTTP request
                JSONObject json = jsonParser.makeHttpRequest(
                        url_delete_case, "POST", params);

                // check your log for json response
                Log.d("Delete Case", json.toString());

                // json success tag
                success = json.getInt(TAG_SUCCESS);
                if (success == 1) {
                    // case successfully deleted
                    // notify previous activity by sending code 100
                    Intent i = getIntent();
                    // send result code 100 to notify about case deletion
                    setResult(100, i);
                    finish();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog once case deleted
            pDialog.dismiss();

        }

    }
}

Logcat Output:

09-05 15:13:17.250: D/All Cases:(4519): {"cases":[{"case_name":"1111","created_at":"2012-07-23 20:35:05","updated_at":"2012-07-24 01:08:41","case_category":"111111111111111","case_user":"1111111","cid":"10"},{"case_name":"c","created_at":"2012-07-23 23:12:36","updated_at":"0000-00-00 00:00:00","case_category":"action2","case_user":"a","cid":"11"},{"case_name":"Klara","created_at":"2012-07-23 23:15:30","updated_at":"0000-00-00 00:00:00","case_category":"i dont know wha","case_user":"Rara","cid":"12"},{"case_name":"chicken","created_at":"2012-07-24 00:58:43","updated_at":"2012-07-24 01:07:24","case_category":"DERPID 2","case_user":"Sherlock","cid":"13"},{"case_name":"derpy\t","created_at":"2012-07-24 01:13:24","updated_at":"2012-07-24 01:29:04","case_category":"blkchicken.chic","case_user":"Sherlock","cid":"14"}],"success":1}
09-05 15:13:33.340: D/AndroidRuntime(4519): Shutting down VM
09-05 15:13:33.340: W/dalvikvm(4519): threadid=1: thread exiting with uncaught exception (group=0x400ee760)
09-05 15:13:33.340: E/AndroidRuntime(4519): FATAL EXCEPTION: main
09-05 15:13:33.340: E/AndroidRuntime(4519): android.os.NetworkOnMainThreadException
09-05 15:13:33.340: E/AndroidRuntime(4519):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1077)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at java.net.InetAddress.lookupHostByName(InetAddress.java:477)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at java.net.InetAddress.getAllByNameImpl(InetAddress.java:277)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at java.net.InetAddress.getAllByName(InetAddress.java:249)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:136)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at com.pivestigator.JSONParser.makeHttpRequest(JSONParser.java:62)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at com.pivestigator.cases.EditCaseActivity$GetCaseDetails$1.run(EditCaseActivity.java:131)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at android.os.Handler.handleCallback(Handler.java:587)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at android.os.Handler.dispatchMessage(Handler.java:92)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at android.os.Looper.loop(Looper.java:132)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at android.app.ActivityThread.main(ActivityThread.java:4126)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at java.lang.reflect.Method.invokeNative(Native Method)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at java.lang.reflect.Method.invoke(Method.java:491)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
09-05 15:13:33.340: E/AndroidRuntime(4519):     at dalvik.system.NativeStart.main(Native Method)
09-05 15:13:35.360: I/dalvikvm(4519): threadid=4: reacting to signal 3
09-05 15:13:35.370: I/dalvikvm(4519): Wrote stack traces to '/data/anr/traces.txt'

Upvotes: 0

Views: 597

Answers (2)

Sherif elKhatib
Sherif elKhatib

Reputation: 45942

The mistake is in SaveCaseDetails class.

Your are making an HTTP request (I suppose) using the function makeHttpRequest on the UI Thread inside the doInBackground function.

Even though the code is inside the background thread; however you are calling runOnUiThread there which will run on the UI Thread and cause this exception.

Remove the runOnUiThread inside the doInBackground of the class SaveCaseDetails.

If needed, use it only to update the UI.


Because of the params renaming, errors will occur so change their name by changing the line

protected String doInBackground(String... params)

to

protected String doInBackground(String... taskParams)

Upvotes: 0

Athul Harikumar
Athul Harikumar

Reputation: 2491

change this to on post execute return the json object as result and run it there

  // json success tag
                    success = json.getInt(TAG_SUCCESS);
                    if (success == 1) {
                        // successfully received case details
                        JSONArray caseObj = json
                                .getJSONArray(TAG_CASE); // JSON Array

                        // get first case object from JSON Array
                        JSONObject cases = caseObj.getJSONObject(0);

                        // case with this cid found
                        // Edit Text
                        txtCaseName = (EditText) findViewById(R.id.inputCaseName);
                        txtCaseUser = (EditText) findViewById(R.id.inputCaseUser);
                        txtCaseCategory = (EditText) findViewById(R.id.inputCaseCategory);

                        // display case data in EditText
                        txtCaseName.setText(cases.getString(TAG_CASE_NAME));
                        txtCaseUser.setText(cases.getString(TAG_CASE_USER));
                        txtCaseCategory.setText(cases.getString(TAG_CASE_CATEGORY));

                    }else{
                        // case with cid not found
                    }

Upvotes: 0

Related Questions