Android Honeycomb Strict Mode приводит к сбою приложения, несмотря на то, что это AsyncTask

Я пытаюсь запустить свое приложение на устройстве Android 3.2 (Honeycomb).

К сожалению, мое приложение вылетает всякий раз, когда я пытаюсь отредактировать один из объектов, перечисленных в моем приложении, с помощью EditCaseActivity. Logcat, кажется, говорит мне, что StrictMode вызывает сбой, но я уже использую AsyncTask.

Любая форма помощи приветствуется! :)

Мой друг подозревает, что это как-то связано с RunOnUiThread, но попытка отредактировать RunOnUiThread кода приводит к ошибкам с параметрами в строках 126 и 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();

        }

    }
}

Вывод логкэта:

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'

comment
com.pivestigator.JSONParser.makeHttpRequest(JSONParser.java:62) вызывается из другого класса jsonparser   -  person Athul Harikumar    schedule 05.09.2012
comment
@droidhot Спасибо за ответ! Но JSON Parser одинаков во всем приложении, и ни одно из других действий не дает сбоев. Есть ли у вас какие-либо предложения о том, как я могу это исправить, если виновником является JSON Parser?   -  person Kirara    schedule 05.09.2012


Ответы (2)


измените это на пост-выполнение, верните объект json в качестве результата и запустите его там

  // 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
                    }
person Athul Harikumar    schedule 05.09.2012

Ошибка в SaveCaseDetails классе.

Вы делаете HTTP-запрос (я полагаю), используя функцию makeHttpRequest в потоке пользовательского интерфейса внутри функции doInBackground.

Несмотря на то, что код находится внутри фонового потока; однако вы вызываете runOnUiThread там, который будет работать в потоке пользовательского интерфейса и вызовет это исключение.

Удалите runOnUiThread внутри doInBackground класса SaveCaseDetails.

При необходимости используйте его только для обновления пользовательского интерфейса.


Из-за переименования параметров будут возникать ошибки, поэтому измените их имя, изменив строку

protected String doInBackground(String... params)

to

protected String doInBackground(String... taskParams)

person Sherif elKhatib    schedule 05.09.2012
comment
Спасибо за помощь! Аааа~ Она (мой друг, который указал на runOnUiThread) была права, в конце концов, я полагаю. Знаете ли вы, как я могу избавиться от ошибок в строках 126 и 127 (относительно params) после удаления runOnUiThread? - person Kirara; 05.09.2012
comment
хе-хе о! Я не видел, чтобы вы там говорили о своем друге :P В любом случае измените эту строку protected String doInBackground(String... params) на protected String doInBackground(String... taskParams) - person Sherif elKhatib; 05.09.2012