0

Recently, I moved my database from localhost into an online database. Everything was working fine with my localhost. I did not change any of the code except the url. Why am I facing this error now when it did not appear before?

Logcat:

03-17 04:15:26.370: E/AndroidRuntime(804): FATAL EXCEPTION: AsyncTask #3
03-17 04:15:26.370: E/AndroidRuntime(804): java.lang.RuntimeException: An error occured while executing doInBackground()
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.os.AsyncTask$3.done(AsyncTask.java:299)
03-17 04:15:26.370: E/AndroidRuntime(804):  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
03-17 04:15:26.370: E/AndroidRuntime(804):  at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
03-17 04:15:26.370: E/AndroidRuntime(804):  at java.util.concurrent.FutureTask.run(FutureTask.java:239)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
03-17 04:15:26.370: E/AndroidRuntime(804):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
03-17 04:15:26.370: E/AndroidRuntime(804):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
03-17 04:15:26.370: E/AndroidRuntime(804):  at java.lang.Thread.run(Thread.java:841)
03-17 04:15:26.370: E/AndroidRuntime(804): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5908)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:869)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.view.ViewGroup.invalidateChild(ViewGroup.java:4253)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.view.View.invalidate(View.java:10482)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.TextView.invalidateRegion(TextView.java:4591)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.TextView.invalidateCursor(TextView.java:4534)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.TextView.spanChange(TextView.java:7412)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.TextView$ChangeWatcher.onSpanAdded(TextView.java:9103)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.text.SpannableStringBuilder.sendSpanAdded(SpannableStringBuilder.java:979)
03-17 04:15:26.370: E/AndroidRuntime(804):  at  android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:688)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:588)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.text.Selection.setSelection(Selection.java:76)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.text.Selection.setSelection(Selection.java:87)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.text.method.ArrowKeyMovementMethod.initialize(ArrowKeyMovementMethod.java:302)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.TextView.setText(TextView.java:3759)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.TextView.setText(TextView.java:3629)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.EditText.setText(EditText.java:80)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.widget.TextView.setText(TextView.java:3604)
03-17 04:15:26.370: E/AndroidRuntime(804):  at my.fyp.inticlassifieds.DisplayItemInfoEdit$GetProductDetails.doInBackground(DisplayItemInfoEdit.java:175)
03-17 04:15:26.370: E/AndroidRuntime(804):  at my.fyp.inticlassifieds.DisplayItemInfoEdit$GetProductDetails.doInBackground(DisplayItemInfoEdit.java:1)
03-17 04:15:26.370: E/AndroidRuntime(804):  at android.os.AsyncTask$2.call(AsyncTask.java:287)
03-17 04:15:26.370: E/AndroidRuntime(804):  at java.util.concurrent.FutureTask.run(FutureTask.java:234)
03-17 04:15:26.370: E/AndroidRuntime(804):  ... 4 more

Class:

public class DisplayItemInfoEdit extends Activity {

EditText txtName;
EditText txtPrice;
EditText txtDesc;
EditText txtCreatedAt;
Button btnSave;
Button btnCancel;
Spinner requeststatus;
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://10.0.2.2:8000/project/get_item_info.php";
private static final String url_product_detials = "http://inticlassifields.comze.com/phpscripts/get_item_info.php";

// url to update product
//private static final String url_update_product = "http://10.0.2.2:8000/project/update_item.php";
private static final String url_update_product = "http://inticlassifields.comze.com/phpscripts/update_item.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";
private static final String TAG_STATUS = "status";

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

    btnSave = (Button) findViewById(R.id.btnSave);
    btnCancel = (Button) findViewById(R.id.btnCancel);
    requeststatus = (Spinner) findViewById(R.id.reqstatusspinner);
    // Create an ArrayAdapter using the string array and a default spinner
    // layout
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
            this, R.array.request_status,
            android.R.layout.simple_spinner_item);
    // Specify the layout to use when the list of choices appears
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    // Apply the adapter to the spinner
    requeststatus.setAdapter(adapter);

    // 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) {
            if(txtName.length()<2)
            {
                Toast.makeText(DisplayItemInfoEdit.this,"Please enter valid item name", Toast.LENGTH_LONG).show();
                return;
            }
             if(txtPrice.length()==0)
             {              
                Toast.makeText(DisplayItemInfoEdit.this,"Please enter item price", Toast.LENGTH_LONG).show();
                return;
             } 

            // starting background task to update product
            new SaveProductDetails().execute();
        }
    });

    // Cancel button click event
    btnCancel.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // return to main menu
            Intent i = new Intent();
            i.setClass(DisplayItemInfoEdit.this, MainMenu.class);
            startActivity(i);
        }
    });

}

/**
 * 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(DisplayItemInfoEdit.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... args) {
        // 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());
        try {
            // json success tag
            int success;
            success = json.getInt(TAG_SUCCESS);
            if (success == 1) {
                // successfully received product details
                JSONArray productObj = json.getJSONArray(TAG_PRODUCT); 

                // 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(DisplayItemInfoEdit.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();
        String status = requeststatus.getSelectedItem().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));
        params.add(new BasicNameValuePair(TAG_STATUS, status));

        // 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
                DisplayItemInfoEdit.this.runOnUiThread(new Runnable() {
                      public void run() {
                        Toast.makeText(DisplayItemInfoEdit.this,"Item updated", Toast.LENGTH_LONG).show();
                      }
                    });
                Intent i = new Intent();
                i.setClass(DisplayItemInfoEdit.this, MainMenu.class);
                startActivity(i);
            } 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 updated
        pDialog.dismiss();
    }
}
}

The error is from this lines of code:

txtName.setText(product.getString(TAG_NAME));
txtPrice.setText(product.getString(TAG_PRICE));
txtDesc.setText(product.getString(TAG_DESCRIPTION));
Benz
  • 237
  • 3
  • 16
  • `I did not change any of the code except the url.` Strange, because updating Views in `doInBackground()` will always cause an exception and has never worked. `txtName.setText(product.getString(TAG_NAME));` this, plus all of the other UI updates, should be done in `onPostExecute()`. – Simon Mar 17 '14 at 08:31
  • 1
    possible duplicate of [Android "Only the original thread that created a view hierarchy can touch its views."](http://stackoverflow.com/questions/5161951/android-only-the-original-thread-that-created-a-view-hierarchy-can-touch-its-vi) – Simon Mar 17 '14 at 08:32

2 Answers2

0

You cannot change touch android UI toolkit from outside UI thread (mainthread). So, move the following lines to onPostExecute() api:

txtName.setText(product.getString(TAG_NAME));
txtPrice.setText(product.getString(TAG_PRICE));
txtDesc.setText(product.getString(TAG_DESCRIPTION));

doInBackground() api is running in another thread.

android developer quote:

Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:

Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread

Follow the link for more details:

http://developer.android.com/guide/components/processes-and-threads.html

Bibhas Debnath
  • 14,559
  • 17
  • 68
  • 96
Sushil
  • 8,250
  • 3
  • 39
  • 71
  • how to i fix the error of 'product cannot be resolved' when i move those codes to onPostExecute? – Benz Mar 17 '14 at 08:37
  • @firaga With respect, it that is a problem for you, you need to go back to some basic programming and Java tutorials. You are not ready to build an app. – Simon Mar 17 '14 at 08:39
  • declare product as a global variable of class GetProductDetails. – Sushil Mar 17 '14 at 08:39
  • @Sushil How can a field in an Activity be global? Global, by definition, has scope and lifetime equal to the application. – Simon Mar 17 '14 at 08:39
  • @Simon I meant class scope. The variable should be global with respect to class GetProductDetails – Sushil Mar 17 '14 at 08:42
0

As Sushil said you cannot modify android ui toolkit outise of the UI Thread. You can move your code or implement an handler system to notify your main thread to modify your edittext. Basically all you have to do is just to create an handler that you notify where you do :

txtName.setText(product.getString(TAG_NAME));
txtPrice.setText(product.getString(TAG_PRICE));
txtDesc.setText(product.getString(TAG_DESCRIPTION))
Substitut
  • 373
  • 1
  • 3
  • 9