1

I'm developing an android app. I have a list view with multiple elements. I'm fetching the elements of the list from a mysql database using a php script. But while obtaining the items, my app crashes and log cat shows the following error. What is wrong here?

Here is my logcat output.

12-22 16:03:30.440: D/dalvikvm(1431): GC_FOR_ALLOC freed 233K, 8% free 3989K/4296K, paused 85ms, total 99ms
12-22 16:03:32.070: I/Choreographer(1431): Skipped 219 frames!  The application may be doing too much work on its main thread.
12-22 16:03:32.610: D/AndroidRuntime(1431): Shutting down VM
12-22 16:03:32.610: W/dalvikvm(1431): threadid=1: thread exiting with uncaught exception (group=0xb3a55ba8)
12-22 16:03:32.690: E/AndroidRuntime(1431): FATAL EXCEPTION: main
12-22 16:03:32.690: E/AndroidRuntime(1431): Process: com.example.orders, PID: 1431
12-22 16:03:32.690: E/AndroidRuntime(1431): android.os.NetworkOnMainThreadException
12-22 16:03:32.690: E/AndroidRuntime(1431):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at libcore.io.IoBridge.connect(IoBridge.java:112)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at java.net.Socket.connect(Socket.java:843)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at com.example.orders.JSONParser.makeHttpRequest(JSONParser.java:62)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at com.example.orders.EditProductActivity$GetProductDetails$1.run(EditProductActivity.java:132)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at android.os.Handler.handleCallback(Handler.java:733)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at android.os.Handler.dispatchMessage(Handler.java:95)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at android.os.Looper.loop(Looper.java:136)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at android.app.ActivityThread.main(ActivityThread.java:5001)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at java.lang.reflect.Method.invokeNative(Native Method)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at java.lang.reflect.Method.invoke(Method.java:515)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
12-22 16:03:32.690: E/AndroidRuntime(1431):     at dalvik.system.NativeStart.main(Native Method)
12-22 16:03:41.360: I/Process(1431): Sending signal. PID: 1431 SIG: 9
12-22 16:03:42.990: D/gralloc_goldfish(1457): Emulator without GPU emulation detected.

Here is my EditProductActivity

package com.example.orders;


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 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 EditProductActivity extends Activity {

    EditText txtName;
    EditText txtPrice;
    EditText txtDesc;
    EditText txtCreatedAt;
    Button btnSave;
    Button btnDelete;

    String pid;

    // Progress Dialog
    private ProgressDialog pDialog;

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

    // single product url
    private static final String url_product_detials = "http://192.168.1.31/test/get_product_details.php";

    // url to update product
    private static final String url_update_product  = "http://192.168.1.31/test/update_product.php";

    // url to delete product
    private static final String url_delete_product  = "http://192.168.1.31/test/delete_product.php";

    // JSON Node names
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_PRODUCT = "product";
    private static final String TAG_PID = "pid";
    private static final String TAG_NAME = "name";
    private static final String TAG_PRICE = "price";
    private static final String TAG_DESCRIPTION = "description";

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

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

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

        // getting product id (pid) from intent
        pid = i.getStringExtra(TAG_PID);

        // Getting complete product details in background thread
        new GetProductDetails().execute();

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

            @Override
            public void onClick(View arg0) {
                // starting background task to update product
                new SaveProductDetails().execute();
            }
        });

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

            @Override
            public void onClick(View arg0) {
                // deleting product in background thread
                new DeleteProduct().execute();
            }
        });

    }

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

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditProductActivity.this);
            pDialog.setMessage("Loading product details. Please wait...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Getting product 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("pid", pid));

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

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

                        // json success tag
                        success = json.getInt(TAG_SUCCESS);
                        if (success == 1) {
                            // successfully received product details
                            JSONArray productObj = json
                                    .getJSONArray(TAG_PRODUCT); // JSON Array

                            // get first product object from JSON Array
                            JSONObject product = productObj.getJSONObject(0);

                            // product with this pid found
                            // Edit Text
                            txtName = (EditText) findViewById(R.id.inputName);
                            txtPrice = (EditText) findViewById(R.id.inputPrice);
                            txtDesc = (EditText) findViewById(R.id.inputDesc);

                            // display product data in EditText
                            txtName.setText(product.getString(TAG_NAME));
                            txtPrice.setText(product.getString(TAG_PRICE));
                            txtDesc.setText(product.getString(TAG_DESCRIPTION));

                        }else{
                            // product with pid 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 product Details
     * */
    class SaveProductDetails extends AsyncTask<String, String, String> {

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

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

            // getting updated data from EditTexts
            String name = txtName.getText().toString();
            String price = txtPrice.getText().toString();
            String description = txtDesc.getText().toString();

            // Building Parameters
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair(TAG_PID, pid));
            params.add(new BasicNameValuePair(TAG_NAME, name));
            params.add(new BasicNameValuePair(TAG_PRICE, price));
            params.add(new BasicNameValuePair(TAG_DESCRIPTION, description));

            // sending modified data through http request
            // Notice that update product url accepts POST method
            JSONObject json = jsonParser.makeHttpRequest(url_update_product,
                    "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 product update
                    setResult(100, i);
                    finish();
                } else {
                    // failed to update product
                }
            } 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 product uupdated
            pDialog.dismiss();
        }
    }

    /*****************************************************************
     * Background Async Task to Delete Product
     * */
    class DeleteProduct extends AsyncTask<String, String, String> {

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

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

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

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

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

                // json success tag
                success = json.getInt(TAG_SUCCESS);
                if (success == 1) {
                    // product successfully deleted
                    // notify previous activity by sending code 100
                    Intent i = getIntent();
                    // send result code 100 to notify about product 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 product deleted
            pDialog.dismiss();

        }

    }
}
colombo
  • 520
  • 2
  • 9
  • 24

1 Answers1

1

Use an AsyncTask or Thread to use any network related actions. This is because some network operations can be blocking and your app will be unresponsive. Multiply this a few times if you have a slow internet connections.

See this post on the difference between a service, thread and an async task.

And see this link on the async task documentation.

EDIT: I see you use thread in an asyncTask, but you also specify runOnUiThread which defeats the purpose of having an asynctask. Also, an AsyncTask is already a thread, so specifying a new runnable is not recommended.

// updating UI from Background Thread runOnUiThread(new Runnable() {

If you look at the specification, onPreExecute,onProgressUpdate and onPostExecute are already on the main thread, so you can access your product details there and post updates. Just make sure you only retrieve information there and do the network operation in doInBackground

Community
  • 1
  • 1
Lars Celie
  • 622
  • 5
  • 17