Setting text in EditText causing app crash - android

I am programming an app in Android Studio. I am taking json file from server, then extracting it to strings and want to show in EditText to let it be modifiable.
Here my code
protected String doInBackground(String... atr) {
new Thread(new Runnable() {
public void run() {
int success;
try {
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("pid", pid));
params.add(new BasicNameValuePair("name", table_name));
JSONObject json = jsonParser.makeHttpRequest(url_product_details, "GET", params);
Log.d("Single Product Details", json.toString());
success = json.getInt(TAG_SUCCESS);
if (success == 1) {
JSONArray productObj = json.getJSONArray(TAG_PRODUCT);
JSONObject product = productObj.getJSONObject(0);
String _name = product.getString("name");
name.setText(_name, EditText.BufferType.EDITABLE);
if(!product.isNull("price")) {
Integer _price = product.getInt("price");
price.setText(_price, EditText.BufferType.EDITABLE);
}
if(!product.isNull("quantity")) {
Integer _quantity = product.getInt("quantity");
quantity.setText(_quantity, EditText.BufferType.EDITABLE);
}
if(!product.isNull("promotion")) {
Integer _promotion = product.getInt("promotion");
promotion.setText(_promotion, EditText.BufferType.EDITABLE);
}
} else {
Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
i.putExtra(TAG_PID, pid);
i.putExtra("list_name", table_name);
startActivity(i);
finish();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}).start();
return null;
}
unfortunately, when I am trying like this app crashes when i try upload text to EditText. I confirmed that EditText isn't null, Strings too. There is no error message what impede this problem. Have anybody some idea? I looked everywhere (maybe i can't search xD) and didn't find anything reasonable.

First thing, unwrap your code from that Thread. doInBackground() is already asynchronous, so there it's redundant. Either use a Thread or an AsyncTask, not both.
Second thing, Views, such as EditText, can only be modified on the main or UI Thread. When you run setText(), or any other methods on View, it needs to be on the main Thread.
If this is inside an Activity, you can use:
runOnUiThread(new Runnable() {
#Override
public void run() {
//appropriate setText()
}
});
Otherwise, you'll need to use a Handler. Create a global variable:
private Handler handler = new Handler(Looper.getMainLooper());
and instead of using runOnUiThread(), use handler.post(), with the same syntax (just replace runOnUiThread with handler.post).
However, there's also a third thing. You shouldn't really be handling your JSON String in the background. You should only be retrieving the String at that point. Your logic should go in onPostExecute(), which already executes on the main Thread for you.
Your code should look like this:
#Override
protected String doInBackground(String... atr) {
try {
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("pid", pid));
params.add(new BasicNameValuePair("name", table_name));
JSONObject json = jsonParser.makeHttpRequest(url_product_details, "GET", params);
Log.d("Single Product Details", json.toString());
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
return json; //return the JSON String on success
} else {
Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
i.putExtra(TAG_PID, pid);
i.putExtra("list_name", table_name);
startActivity(i);
finish();
}
} catch (JSONException e) {
e.printStackTrace();
}
return null; //return null for any other result
}
#Override
protected void onPostExecute(String result) {
if (result != null) { //make sure result isn't null
JSONArray productObj = result.getJSONArray(TAG_PRODUCT);
JSONObject product = productObj.getJSONObject(0);
String _name = product.getString("name");
name.setText(_name, EditText.BufferType.EDITABLE);
if (!product.isNull("price")) {
Integer _price = product.getInt("price");
price.setText(_price, EditText.BufferType.EDITABLE);
}
if (!product.isNull("quantity")) {
Integer _quantity = product.getInt("quantity");
quantity.setText(_quantity, EditText.BufferType.EDITABLE);
}
if (!product.isNull("promotion")) {
Integer _promotion = product.getInt("promotion");
promotion.setText(_promotion, EditText.BufferType.EDITABLE);
}
}
}

When you are interacting with any UI element, like EditText, you can't use anything other than UI thread (or main thread).
In other words, UI elements must be changed from UI thread.
What you can do:
Move codes where UI element(like EditText) is updated from doInBackground(String... str) to onPostExecuted(String str).
Every time you use any UI element from another thread, use View.post(Runnable runnable) method. Like:
editText.post(
new Runnable() {
#Override
public void run() {
//do your work
}
}
);
or use Activity.runOnUiThread(Runnable runnable) method when within an Activity
runOnUiThread(
new Runnable() {
#Override
public void run() {
//do your work
}
}
);

Related

AsyncTask keep returning null

I am using for loop to call asynctask
this is how I call the asynctask in a Fragment:
private void LoadPartiList() {
for (int i = 0; i < participants.length; i ++){
String getlistparti = cmd.getPartList();
participants = getlistparti.split(",");
partiparti = ((CommentandLikeActivity)getActivity()).getparticipantlist(participants[i]);
Log.d("test","testlogcat " + partiparti);
}
here my asynctask which allocate in the activity which contain the fragment :
public ArrayList<User> getparticipantlist(final String participationID) {
final ArrayList<User> list = new ArrayList<User>();
final User user = new User();
new AsyncTask<String, String, ArrayList<User>>() {
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected ArrayList<User> doInBackground(String... params) {
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// Check for success tag
int success;
try {
// Building Parameters
Log.d("participantid", "17112015 " + participationID);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("userid", participationID));
// getting product details by making HTTP request
// Note that product details url will use GET request
JSONObject json = jsonParser.makeHttpRequest(
"http://192.168.168.111:80/testing/participationlist.php", "GET", params);
// check your log for json response
Log.d("Single Product Details", json.toString());
// json success tag
success = json.getInt("success");
if (success == 1) {
// successfully received product details
JSONArray productObj = json
.getJSONArray("product"); // JSON Array
// get first product object from JSON Array
JSONObject product = productObj.getJSONObject(0);
user.setId(String.valueOf(product.getString(String.valueOf("vuid"))));
user.setUsername(product.getString("vusername"));
user.setProfileimage(product.getString("vprofileimage"));
list.add(user);
Log.d("","getwalalala " +product.getString(String.valueOf("vuid")) +" : "+ product.getString("vusername") + " : " +product.getString("vprofileimage") );
}else{
// product with pid not found
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return list;
}
#Override
protected void onPostExecute(ArrayList<User> list) {
List<User> mUserlist = new ArrayList<User>();
mAdapterr = new participantlistAdapter(getApplicationContext(), mUserlist);
mAdapterr.Update();
mAdapterr.add(user);
}
}.execute(null, participationID, null);
return list;
}
here is what I Log when run the Asynctask
Logcat for Log.d("","getwalalalala")
but why it will just return [] or null? any wrong with my code? help please...
I want to loop the userid to get username from phpserver according to the length in the participants.length and display in the listview, how should I do it?
I get no answer after research online for few days
As you are trying to return data from AsyncTask which is not correct. AsyncTask doInBackground return data to your onPostExecute. So whatever you are trying to return can only be received in onPostExecute. but still you want to implement Asynctask then you achieve this by one of the following way:
By defining AsyncTask as inner private class in your activity and directly using the data in onPostExecute to update your ui.
Second method is to pass interface callback to your asynctask and with the help of that interface callback update your ui from AsyncTask to activity.

how can i call an new activity from onPostExecute?

protected String doInBackground(String... args) {
String myres = null;
String bot_string = args[0] ;
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("question", bot_string));
JSONObject json = jsonParser.makeHttpRequest(url_pythonwebservice, "GET", params);
// Check your log cat for JSON reponse
Log.d("results: ", json.toString());
try {
myres = json.getString(TAG_BOTRESPONSE);
} catch (JSONException e) {
e.printStackTrace();
}
return myres;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
Toast.makeText(getApplicationContext(),file_url , Toast.LENGTH_LONG).show();
//Get reference to textview above in oncreate method
//bot.setText(file_url);
}
if (file_url == "Navigation"){
Intent i = new Intent(Voice.this, MapsActivity.class);
startActivity(i);
}
Toast is printing.I want to call MapsActivity.class if String file_url == "Navigaion" but this is not working if i put inside the onPostExecute. How can i call MapsActivity.class. This is a voice recognition application.
In Java, you should compare two string as,
if(string1.equals(string2))
{
// code block
}
So, for your example, you should change your code like,
if (file_url.equals("Navigation"))
{
// more code follows
}

Android Background web service Issue

I really need your help. I am building an Android app that needs a lot of HTTP requests such as logging to the server(check if user is exists or not) and storing the session to the database (user_sessions table), adding, updating and deleting records.
In my Login Activity, I have my AsyncTask (to check if user exits) and other background threads (logs the user session and download user info to database) . This is successful. Next, when I update the user info, it updates successfully. But what if I update using my web app? My should display the newly updated info on my android app. How can I resolve this problem?
This is what I've tried so far:
private void logSessionToServer() {
// TODO Auto-generated method stub
Thread thread = new Thread(){
public void run(){
strUsername = etUsername.getText().toString();
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair( TAG_USERNAME, strUsername ));
// getting JSON Object
// Note it accepts POST method only
JSONObject json = jsonParser.makeHttpRequest(url_log_session,
"POST", params);
// check log cat from response
Log.d("Create Response", json.toString());
// check for success tag
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
Log.d("", "Successfully logged session!");
} else {
// failed
Log.d("", "Not Successful!");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
thread.start();
}
/**
* Background Async Task to Create new record
* */
class LoginTask extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Login.this);
pDialog.setIcon(R.drawable.upload);
pDialog.setTitle("Connecting to server");
pDialog.setMessage("Validating login details..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
*
* */
protected String doInBackground(String... args) {
strUsername = etUsername.getText().toString();
strPassword = etPassword.getText().toString();
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair( TAG_USERNAME, strUsername ));
params.add(new BasicNameValuePair( TAG_PASSWORD, strPassword ));
// getting JSON Object
// Note it accepts POST method only
JSONObject json = jsonParser.makeHttpRequest(url_login,
"POST", params);
// check log cat from response
Log.d("Create Response", json.toString());
// check for success tag
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
logSessionToServer(); // Save login to server
saveUserInfoToDB(); // Save user info to DB
saveUserloggedIn(); // Save user logged in to preference
savePriestInfoToDB(); // Save priest to DB
Log.d("", "Successful Login!");
Intent i = new Intent(Login.this, MainActivity.class);
startActivity(i);
finish();
} else {
// failed
new Thread()
{
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
Toast.makeText(getBaseContext(),
"Not Successful Login", Toast.LENGTH_SHORT).show();
}
});
}
}.start();
Log.d("", "Not Successful Login!");
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String result) {
// dismiss the dialog once done
pDialog.dismiss();
}
}
private void saveUserInfoToDB() {
// TODO Auto-generated method stub
Thread thread = new Thread(){
public void run(){
// Create the array
arraylist = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given website URL in JSONfunctions.class
String result = JSONFunctions.getJSONfromURL(url_view_loggedUser_profile);
try {
JSONArray jr = new JSONArray(result);
for(int i=0;i<jr.length();i++)
{
HashMap<String, String> map = new HashMap<String, String>();
jb = (JSONObject)jr.get(i);
map.put(TAG_FIRSTNAME, jb.getString(TAG_FIRSTNAME));
map.put(TAG_MIDDLENAME, jb.getString(TAG_MIDDLENAME));
map.put(TAG_LASTNAME, jb.getString(TAG_LASTNAME));
map.put(TAG_EMAIL, jb.getString(TAG_EMAIL));
map.put(TAG_AGE, jb.getString(TAG_AGE));
map.put(TAG_GENDER, jb.getString(TAG_GENDER));
map.put(TAG_USERNAME, jb.getString(TAG_USERNAME));
map.put(TAG_PASSWORD, jb.getString(TAG_PASSWORD));
map.put(TAG_BARANGAY, jb.getString(TAG_BARANGAY));
map.put(TAG_COMPLETEADDRESS, jb.getString(TAG_COMPLETEADDRESS));
map.put(TAG_CUS_ID, jb.getString(TAG_CUS_ID));
map.put(TAG_REG_DATE, jb.getString(TAG_REG_DATE));
map.put(TAG_BD_MONTH, jb.getString(TAG_BD_MONTH));
map.put(TAG_BD_DATE, jb.getString(TAG_BD_DATE));
map.put(TAG_BD_YEAR, jb.getString(TAG_BD_YEAR));
arraylist.add(map);
String strCusID = jb.getString(TAG_CUS_ID);
String strFname = jb.getString(TAG_FIRSTNAME);
String strMname = jb.getString(TAG_MIDDLENAME);
String strLname = jb.getString(TAG_LASTNAME);
String strEmail = jb.getString(TAG_EMAIL);
String strAge = jb.getString(TAG_AGE);
String strGender = jb.getString(TAG_GENDER);
String strUsername = jb.getString(TAG_USERNAME);
String strPassword = jb.getString(TAG_PASSWORD);
String strBarangay = jb.getString(TAG_BARANGAY);
String strCompleteAddress = jb.getString(TAG_COMPLETEADDRESS);
String strRegDate = jb.getString(TAG_REG_DATE);
String strBDMonth = jb.getString(TAG_BD_MONTH);
String strBDDate = jb.getString(TAG_BD_DATE);
String strBDYear = jb.getString(TAG_BD_YEAR);
try{
dbHelper.insertEntry(strCusID, strFname, strMname, strLname, strEmail,
strAge, strGender, strUsername, strPassword,
strBarangay, strCompleteAddress, strRegDate,
strBDMonth, strBDDate, strBDYear);
Log.d("Response", "Successfully inserted record");
} catch (SQLiteException e) {
Log.d("Response", "Not successful");
}
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
}
};
thread.start();
}
private void savePriestInfoToDB() {
// TODO Auto-generated method stub
Thread thread = new Thread(){
public void run(){
// Create the array
arraylist = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given website URL in JSONfunctions.class
String result = JSONFunctions.getJSONfromURL(URL_VIEW_PRIESTS);
try {
JSONArray jr = new JSONArray(result);
for(int i=0;i<jr.length();i++)
{
HashMap<String, String> map = new HashMap<String, String>();
jb = (JSONObject)jr.get(i);
map.put(TAG_P_ID, jb.getString(TAG_P_ID));
map.put(TAG_P_FIRSTNAME, jb.getString(TAG_P_FIRSTNAME));
map.put(TAG_P_MIDDLENAME, jb.getString(TAG_P_MIDDLENAME));
map.put(TAG_P_LASTNAME, jb.getString(TAG_P_LASTNAME));
map.put(TAG_P_EMAIL, jb.getString(TAG_P_EMAIL));
map.put(TAG_P_AGE, jb.getString(TAG_P_AGE));
map.put(TAG_P_ADDRESS, jb.getString(TAG_P_ADDRESS));
map.put(TAG_P_CONTACT, jb.getString(TAG_P_CONTACT));
map.put(TAG_P_STATUS, jb.getString(TAG_P_STATUS));
arraylist.add(map);
String strP_ID = jb.getString(TAG_P_ID);
String strP_Fname = jb.getString(TAG_P_FIRSTNAME);
String strP_Mname = jb.getString(TAG_P_MIDDLENAME);
String strP_Lname = jb.getString(TAG_P_LASTNAME);
String strP_Email = jb.getString(TAG_P_EMAIL);
String strP_Age = jb.getString(TAG_P_AGE);
String strP_Address = jb.getString(TAG_P_ADDRESS);
String strP_Status = jb.getString(TAG_P_STATUS);
String strP_Contact = jb.getString(TAG_P_CONTACT);
try{
dbHelper.insertPriest(strP_ID, strP_Fname, strP_Mname,
strP_Lname, strP_Email, strP_Age,
strP_Address, strP_Status, strP_Contact);
Log.d("Response - Priest", "Successfully inserted record");
} catch (SQLiteException e) {
Log.d("Response - Priest", "Not successful");
}
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
}
};
thread.start();
}
Feel free to check out my codes and give feedback if this is the best practice for HTTP requests. I am new to Web Services so I really need your help. Any help will be greatly appreciated. Thanks
Well what I just said: you write a thread which downloads user-info every 5 seconds. then it compares the user info downloaded with the user info that is already stored on your device. if there is a difference, an update has been made, and your thread invokes a new download of the updated user info.

Android Async doinbackaground data to onpostexecute

I need some help with taking results from doinbackground to onpostexecute. The results are in the form of JSONArray. I want to populate two textviews in the UI through onpostexecute. There is no error in the code but nothing happens as it seems inpostexecute is not getting called. Please help. I have looked at several similar questions here and tried many things but unable to get it to work..thanks in advance. Please note private static final String TAG_LATEST_SCORES = "cricket_scores";
class PostScores extends AsyncTask<JSONArray, Void, JSONArray> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(NewScoreupdatescricketActivity.this);
pDialog.setMessage("Posting LiveScore Updates..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Creating product
* */
protected JSONArray doInBackground(JSONArray... args) {
String runs1 = runs.getText().toString();
String wicket1 = wicket.getText().toString();
String overs1 = over.getText().toString();
String rr1 = rr.getText().toString();
String team_name = null;
String bat1;
if (innings.isChecked() == false) {
bat1 = "1";
team_name = bat.getText().toString();
} else {
bat1 = "2";
team_name = bat.getText().toString();
}
if (rr1.equals("NA")) {
rr1 = "0";
}
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("runs", runs1));
params.add(new BasicNameValuePair("wickets", wicket1));
params.add(new BasicNameValuePair("id", id1));
params.add(new BasicNameValuePair("overs", overs1));
params.add(new BasicNameValuePair("rr", rr1));
params.add(new BasicNameValuePair("bat", bat1));
params.add(new BasicNameValuePair("team_name", team_name));
// getting JSON Object
// Note that create product url accepts POST method
JSONObject json = jsonParser.makeHttpRequest(url_create_product,
"POST", params);
// check log cat fro response
Log.d("Create Response", json.toString());
// check for success tag
try {
int success = json.getInt(TAG_SUCCESS);
pDialog.dismiss();
if (success == 1) {
latest_scores = json.getJSONArray(TAG_LATEST_SCORES);
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
pDialog.dismiss();
return latest_scores;
}
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(JSONArray latest_sc) {
// dismiss the dialog once done
try {
for (int i = 0; i < latest_sc.length(); i++) {
JSONObject c = latest_sc.getJSONObject(i);
String wickets = c.getString(TAG_WICKETS);
String runs = c.getString(TAG_RUNS);
score_inngs1.setText(wickets + runs);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Check your brackets. After your definition of doInBackground, you have an extra bracket - that one closes off your PostScores class, so your onPostExecute method is defined as a member of whatever class is enclosing PostScores, if any.
Also, you'll need to #Override the AsyncTask methods to provide your own implementation.

pass arraylist from asynctask to the method calling it android

I am having a scenario in which I am calling asynctask in onclicklistener of button. In post execute method of asynctask I am adding values in arraylist which I want to return to the method calling asynctask
This is my asynctask
public class FetchtopTask extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
try {
String getitemcode=params[0];
// Building Parameters
ArrayList<NameValuePair> params1 = new ArrayList<NameValuePair>();
params1.add(new BasicNameValuePair("ItemCode",getitemcode));
Log.d("request!", "starting");
response = CustomHttpClient.executeHttpPost("http://10.0.2.2/top.php",params1);
String retstring=response.toString();
Log.d(retstring,"stringggggg");
return retstring;
}
catch(Exception io){
msg = "No Network Connection";
}
return null;
}
#Override
protected void onPostExecute(String sJson) {
try {
JSONArray aJson = new JSONArray(sJson);
for(int i=0;i<aJson.length();i++)
{
JSONObject jsonO = aJson.getJSONObject(i);
top1.add(jsonO.getString("MName"));
top2.add(jsonO.getString("Amount"));
top3.add(jsonO.getString("TaxStruct"));
}
}catch(JSONException e){
msg = "Invalid response";
}
}
}
I want to pass top1,top2,top3 arraylists to calling method
please help me to achieve this.
You may use ArrayList of ArrayLists:
ArrayList<ArrayList<String>> tops= new ArrayList<ArrayList<String>>();
tops.add(top1);
tops.add(top2);
tops.add(top3);
and
return tops;
hey Just call AsyncTask in btn Click
and in post execute method
call another method which will use that Array which is created in post Execute.
#Override
protected void onPostExecute(String sJson) {
try {
JSONArray aJson = new JSONArray(sJson);
for(int i=0;i<aJson.length();i++)
{
JSONObject jsonO = aJson.getJSONObject(i);
top1.add(jsonO.getString("MName"));
top2.add(jsonO.getString("Amount"));
top3.add(jsonO.getString("TaxStruct"));
anotherMethod(top);
}
}catch(JSONException e){
msg = "Invalid response";
}
}

Categories

Resources