I'm new to android and working on a basic screen to use a web-service with android application.
I am posting values using AsyncTask and fetching the result from the webservice. It works fine until displaying the returned value. While displaying the Toast Message on click, I get old value of TextView resultReturned
public class TestPost extends Activity{
private TextView result = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.my_screen);
result = (TextView)findViewById(R.id.resultReturned);
Button submit = (Button)findViewById(R.id.btnSubmit);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String[] strPost = new String[]{"value1", "value2"};
SendAsyncRequest asyncSend = new SendAsyncRequest();
asyncSend.execute(strPost);
// ResultView retains old value and gets correct value on second click
String returned = result.getText().toString();
Toast.makeText(getApplicationContext(), returned, Toast.LENGTH_LONG).show();
}
});
}
public class SendAsyncRequest extends AsyncTask<String, Void, String>{
private String fetchedData = "";
#Override
protected String doInBackground(String... params ) {
// perform async task
return fetchedData;
}
#Override
protected void onPostExecute(String result) {
setReturedValue(result);
}
}
private void setReturedValue(String data){
result.setText(data);
}
So, how do I get the updated text value of the TextView?
AsyncTask takes time to get response from request, Show toast message in postExecute() method, like this, and remove from onclick.
#Override
protected void onPostExecute(String result) {
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
}
Try this
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String[] strPost = new String[]{"value1", "value2"};
SendAsyncRequest asyncSend = new SendAsyncRequest();
asyncSend.execute(strPost);
// ResultView retains old value and gets correct value on second click
String jsonResult;
try {
jsonResult=asyncSend.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), jsonResult, Toast.LENGTH_LONG).show();
}
});
And return your Json String in doInBackground().
Related
I am using a single button to do two task.
Watson Conversation.
Watson Text to Speech.
My code is executing only if my TextView has some Text name (string), but the Text to Speech is playing the last conversation response even though the new conversation response is updated at TextView display on my phone UI.. Continuation of this here Race condition with UI thread issue.
Also I found out, if I keep my TextView empty i get error this:
Code here:
private class ConversationTask extends AsyncTask<String, Void, String> {
String textResponse = new String();
#Override
protected String doInBackground(String... params) {
System.out.println("in doInBackground");
MessageRequest newMessage = new MessageRequest.Builder().inputText(params[0]).context(context).build();
// async
GLS_service.message("xxxxxxx", newMessage).enqueue(new ServiceCallback<MessageResponse>() {
#Override
public void onResponse(MessageResponse response) {
context = response.getContext();
textResponse = response.getText().get(0);
reply.setText(textResponse);
System.out.println(textResponse);
}
#Override
public void onFailure(Exception e) {
}
});
return textResponse;
}
}
//
private class WatsonTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(final String... textToSpeak) {
/* runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(" ");
}
});*/
TextToSpeech textToSpeech = initTextToSpeechService();
streamPlayer = new StreamPlayer();
streamPlayer.playStream(textToSpeech.synthesize(textToSpeak[0], Voice.EN_LISA).execute());
return "Text to Speech Done";
}
/*#Override protected void onPostExecute(String result) {
textView.setText("");
}*/
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Register the UI controls.
input = (EditText) findViewById(R.id.input);
send = (ImageButton) findViewById(R.id.send);
textView = (TextView) findViewById(R.id.textView);
reply = (TextView) findViewById(R.id.reply);
play = (ImageButton) findViewById(R.id.play);
new ConversationTask().execute("");
//Button function
send.setOnClickListener(action3);
}
//five actions on button click
public void action5() {
String textResponse = new String();
System.out.println("Text to Speech:" + reply.getText());
//textView.setText("");
WatsonTask task = new WatsonTask();
task.execute(String.valueOf(reply.getText()));
//new WatsonTask().execute(reply.getText().toString());
}
View.OnClickListener action3 = new View.OnClickListener() {
public void onClick(View v) {
//action here//
new ConversationTask().execute(input.getText().toString());
action5();
}
};
}
Please help.
Action 3
View.OnClickListener action3 = new View.OnClickListener() {
public void onClick(View v) {
//action here//
new ConversationTask().execute(input.getText().toString());
}
};
Action 5
public void action5(String replyString) {
WatsonTask task = new WatsonTask();
task.execute(replyString);
}
Conversation Task
private class ConversationTask extends AsyncTask<String, Void, String> {
String textResponse = new String();
#Override
protected String doInBackground(String... params) {
System.out.println("in doInBackground");
MessageRequest newMessage = new MessageRequest.Builder().inputText(params[0]).context(context).build();
// async
GLS_service.message("xxxxxxx", newMessage).enqueue(new ServiceCallback<MessageResponse>() {
#Override
public void onResponse(MessageResponse response) {
context = response.getContext();
textResponse = response.getText().get(0);
reply.setText(textResponse);
action5(textResponse);
}
#Override
public void onFailure(Exception e) {
}
});
return textResponse;
}
}
WatsonTask
private class WatsonTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(final String... textToSpeak) {
reply.setText(textToSpeak[0]);
TextToSpeech textToSpeech = initTextToSpeechService();
streamPlayer = new StreamPlayer();
streamPlayer.playStream(textToSpeech.synthesize(textToSpeak[0], Voice.EN_LISA).execute());
return textToSpeak[0];
}
}
And for the sake of completeness address to the comment by Marcin Jedynak
I think your program scenario will follow next sequences:
Enter text to conversation task.
Get conversation result from GLS_service.message().
Input the result from sequence 2, for make the voice.
So try to change your code like this.
// There is no need to return String. Just send result to TextToSpeech.
//private class ConversationTask extends AsyncTask<String, Void, String> {
private class ConversationTask extends AsyncTask<String, Void, Void> {
String textResponse = new String();
#Override
protected String doInBackground(String... params) {
System.out.println("in doInBackground");
MessageRequest newMessage = new MessageRequest.Builder().inputText(params[0]).context(context).build();
// async
GLS_service.message("xxxxxxx", newMessage).enqueue(new ServiceCallback<MessageResponse>() {
#Override
public void onResponse(MessageResponse response) {
context = response.getContext();
textResponse = response.getText().get(0);
reply.setText(textResponse);
System.out.println(textResponse);
action5(textResponse); // It is real result that you want.
}
#Override
public void onFailure(Exception e) {
}
});
//return textResponse; // Not necessary.
}
}
//
private class WatsonTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(final String... textToSpeak) {
/* runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(" ");
}
});*/
TextToSpeech textToSpeech = initTextToSpeechService();
streamPlayer = new StreamPlayer();
streamPlayer.playStream(textToSpeech.synthesize(textToSpeak[0], Voice.EN_LISA).execute());
return "Text to Speech Done";
}
/*#Override protected void onPostExecute(String result) {
textView.setText("");
}*/
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Register the UI controls.
input = (EditText) findViewById(R.id.input);
send = (ImageButton) findViewById(R.id.send);
textView = (TextView) findViewById(R.id.textView);
reply = (TextView) findViewById(R.id.reply);
play = (ImageButton) findViewById(R.id.play);
new ConversationTask().execute("");
//Button function
send.setOnClickListener(action3);
}
//five actions on button click
// Need a parameter to get String.
//public void action5() {
public void action5(String text) {
// String textResponse = new String(); // Replace to parameter as "text".
//System.out.println("Text to Speech:" + reply.getText());
System.out.println("Text to Speech:" + text);
//textView.setText("");
WatsonTask task = new WatsonTask();
//task.execute(String.valueOf(reply.getText()));
task.execute(text); // Replace to parameter as "text".
//new WatsonTask().execute(reply.getText().toString());
}
View.OnClickListener action3 = new View.OnClickListener() {
public void onClick(View v) {
//action here//
new ConversationTask().execute(input.getText().toString());
// action5(); // This invoking is not necessary at this point.
// Try to invoke this method after you get conversation result.
}
};
If it is not working even you changed, I want to know how you implement initTextToSpeechService() method.
Hope this helps you.
Hi I just created app for loading data from the website once the button is clicked in android.I want to change the app for loading data when the application open.How will I do it?
Here is my code..
public class PrimaryActivity extends Activity {
private static final String URL = "http://livechennai.com/powershutdown_news_chennai.asp";
ProgressDialog mProgressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_primary);
Button btnFetchData = (Button) findViewById(R.id.btnData);
btnFetchData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
new FetchWebsiteData().execute();
}
});
}
private class FetchWebsiteData extends AsyncTask<Void, Void, String[]> {
String websiteTitle, websiteDescription,websiteDescription1,websiteDescription2,websiteDescription3,listValue,listValue1;
ProgressDialog progress;
#Override
protected void onPreExecute() {
super.onPreExecute();
//some code here
}
#Override
protected String[] doInBackground(Void... params) {
ArrayList<String> hrefs=new ArrayList<String>();
try {
// parsing here
}
} catch (IOException e) {
e.printStackTrace();
}
//get the array list values
for(String s:hrefs)
{
//website data
}
//parsing first URL
} catch (IOException e) {
e.printStackTrace();
}
//parsing second URL
} catch (IOException e) {
e.printStackTrace();
}
try{
List<String> listString = new ArrayList<String>(Arrays.asList(resultArray));
listString.addAll(Arrays.asList(resultArray1));
String [] outResult= new String[listString.size()];
int i=0;
for(String str: listString){
outResult[i]=str;
i++;
}
return outResult;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] result) {
ListView list=(ListView)findViewById(R.id.listShow);
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(getBaseContext(),android.R.layout.simple_list_item_1,result);
list.setAdapter(arrayAdapter);
mProgressDialog.dismiss();
}
}
}
How to load the list view when we open the app? help me to get the exact answer?
Just load it in onCreate. This is what will be called when the app is opened first. Then read about other events like onResume.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_primary);
new FetchWebsiteData().execute();
}
Call FetchWebsiteData().execute() from one of the activity lifecycle methods such as onStart, onCreate, or onResume - please refer to docs to determine which fits in your case.
Put the method which does the fetching i.e. new FetchWebsiteData().execute(); outside of the code of button click and in the activity.onResume() method.
onResume is called everytime an app comes to foreground, if you put it oncreate(), the method will be called only when the activity is created.
I want to access activity and set text from async class.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button getBtn = (Button) findViewById(R.id.btn_result);
getBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView txt_res = (TextView)findViewById(R.id.txt_Result);
new GetText(txt_res).execute(); // Async class
}
});
}
}
//Async Class
public class GetText AsyncTask<Void, Void, Void>{
private TextView txt_res;
public GetText (TextView txt_res) {
this.txt_res = txt_res;
}
#Override
protected Void doInBackground(Void... params) {
try {
String Result = GetTextFromDb();
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
try
{
Log.v("Success", "Success"); // I see "Success" at Logcat
txt_res.SetText("Success"); // Textview didn't change
}catch (Exception e) {
Log.v("Error", e.getMessage()); // No error at Logcat
}
}
}
I redefine my question. Textview don't change. Whats my mistake.
I redefine my question again. Textview didn't change at two functions(doInBackground, onPostExecute)
You basically have 2 options. You cannot directly access the main thread from asych obviously, so you must use the proper format.
If the text view needs to be updated after the task finishes, simply do the updating in onPostExecute
If the textview is displaying some intermediate progress, use onProgressUpdate
Edit:
Ok so here is your problem now. With asycn tasks, you must return a value from doInBackground. Change the type to String, and change onPostExecute(String result). Void means you are returning nothing. You will also have to change the second of the three parameters at the top of the async task to string as well.
Also, the method is textview.setText(""); not textview.SetText(""). The latter should not compile
I have a method searchPlace() that updates a static Arrays of custom Place Object in a class A (FindItOnMap) with a google map, and a method updateMap() that updates the various geopoints .
I invoke these methods Button.onClick and all works properly.
Since these methods use internet data this operation could take a while, I have been looking for the implementation of an inner class B(YourCustomAsyncTask) inside the class A that extends AsyncTask to show a waiting dialog during the processing of these two methods
An user suggested a solution in this form (that apparently seems valid):
public class FindItOnMap extends MapActivity {
static Place[] foundResults;
private ProgressDialog dialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ricerca_condominio);
mapView = (MapView)findViewById(R.id.mapView);
...........
((ImageButton) findViewById(R.id.btSearch)).setOnClickListener(mSearchListenerListener);
}
OnClickListener mSearchListener = new OnClickListener() {
public void onClick(View v) {
String location=editorLocation.getText().toString();
String name=editorName.getText().toString();
//Call the AsyncTask here
new YourCustomAsyncTask().execute(new String[] {name, location});
}
};
private class YourCustomAsyncTask extends AsyncTask <String, Void, Void> {
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(Main.this);
dialog.setMessage("Loading....");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show(); //Maybe you should call it in ruinOnUIThread in doInBackGround as suggested from a previous answer
}
#Override
protected Void doInBackground(String... strings) {
try {
search(strings[0], string[1]);
return null;
} catch(Exception e) {
}
}
#Override
protected void onPostExecute(Void params) {
updateMapWithResult();
dialog.dismiss();
//result
}
.....
}
The waiting dialog is showed and the methods are invoked in background,
However for some strange reason the static list foundResults results filled with various null items...
How is this possible?
If I invoke the method search(location, name) outside the inner class all works properly and updateMapWithResult(); updates all geopoint, so these two methods are ok. Only if I try to invoke this in the inner class the json calls seem to be working but the static variable foundResults is filled with null elements and the program doesn't work properly.
Any suggestion?
I have understand where is the problem.
You have to run the search method on the UI thread.
So change this code block:
#Override
protected Void doInBackground(String... strings) {
try {
search(strings[0], string[1]);
return null;
} catch(Exception e) {
}
}
with this
#Override
protected Void doInBackground(final String... strings) {
try {
runOnUiThread(new Runnable() {
public void run() {
search(strings[0], string[1]);
return null;
}
});
} catch(Exception e) {
e.printStackTrace();
}
}
And all should works correctly.
Here is one problem:
OnClickListener mSearchListener = new OnClickListener() {
public void onClick(View v) {
String Location=editorLocation.getText().toString();
String name=editorName.getText().toString();
//Call the AsyncTask here
new YourCustomAsyncTask().execute(new String[] {name, location});
}
Your Location should be location.
Also here:
#Override
protected Void doInBackground(String... strings) {
try {
search(strings[0], string[1]);
} catch(Exception e) {
}
}
#Override
protected void onPostExecute(Void params) {
updateMapWithResult();
dialog.dismiss();
//result
}
In doInBackground you don't assign a value after you search. You might try this:
#Override
protected Void doInBackground(String... strings) {
try {
search(strings[0], string[1]);
String name = string[0];
String location = string[1]
} catch(Exception e) {
}
}
Or something else that will assign value while it runs. As it is, it appears that you just search, and then nothing else.
The reason foundResults is null is because you don't ever assign it a value.
There is nothing wrong with your AsyncTask. Please include the search() method.
Update1
activity:
public Integer _number = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
if (_number >0)
{
Log.d("onSuccessfulExecute", ""+_number);
}
else
{
Log.d("onSuccessfulExecute", "nope empty songs lists");
}
}
public int onSuccessfulExecute(int numberOfSongList) {
_number = numberOfSongList;
if (numberOfSongList >0)
{
Log.d("onSuccessfulExecute", ""+numberOfSongList);
}
else
{
Log.d("onSuccessfulExecute", "nope empty songs lists");
}
return numberOfSongList;
}
end Update1
UPDATE: AsynchTask has its own external class.
How to pass an value from AsyncTask onPostExecute()... to activity
my code does returning value from onPostExecute() and updating on UI but i am looking for a way to set the activity variable (NumberOfSongList) coming from AsynchTask.
AsyncTask class:
#Override
public void onPostExecute(asynctask.Payload payload)
{
AsyncTemplateActivity app = (AsyncTemplateActivity) payload.data[0];
//the below code DOES UPDATE the UI textView control
int answer = ((Integer) payload.result).intValue();
app.taskStatus.setText("Success: answer = "+answer);
//PROBLEM:
//i am trying to populate the value to an variable but does not seems like the way i am doing:
app.NumberOfSongList = payload.answer;
..............
..............
}
Activity:
public Integer NumberOfSongList;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Several UI Code
new ConnectingTask().execute();
Log.d("onCreate", ""+NumberOfSongList);
}
What about using a setter method? e.g.
private int _number;
public int setNumber(int number) {
_number = number;
}
UPDATE:
Please look at this code. This will do what you're trying to accomplish.
Activity class
public class TestActivity extends Activity {
public int Number;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Button btnDisplay = (Button) findViewById(R.id.btnDisplay);
btnDisplay.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast toast = Toast.makeText(v.getContext(), "Generated number: " + String.valueOf(Number), Toast.LENGTH_LONG);
toast.show();
}
});
new TestTask(this).execute();
}
}
AsyncTask class
public class TestTask extends AsyncTask<Void, Void, Integer> {
private final Context _context;
private final String TAG = "TestTask";
private final Random _rnd;
public TestTask(Context context){
_context = context;
_rnd = new Random();
}
#Override
protected void onPreExecute() {
//TODO: Do task init.
super.onPreExecute();
}
#Override
protected Integer doInBackground(Void... params) {
//Simulate a long-running procedure.
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
}
return _rnd.nextInt();
}
#Override
protected void onPostExecute(Integer result) {
TestActivity test = (TestActivity) _context;
test.Number = result;
super.onPostExecute(result);
}
}
Just a word of caution: Be very careful when attempting to hold a reference to an Activity instance in an AsyncTask - I found this out the hard way :). If the user happens to rotate the device while your background task is still running, your activity will be destroyed and recreated thus invalidating the reference being to the Activity.
Create a listener.
Make a new class file. Called it something like MyAsyncListener and make it look like this:
public interface MyAsyncListener() {
onSuccessfulExecute(int numberOfSongList);
}
Make your activity implement MyAsyncListener, ie,
public class myActivity extends Activity implements MyAsyncListener {
Add the listener to the constructor for your AsyncTask and set it to a global var in the Async class. Then call the listener's method in onPostExecute and pass the data.
public class MyCustomAsync extends AsyncTask<Void,Void,Void> {
MyAsyncListener mal;
public MyCustomAsync(MyAsyncListener listener) {
this.mal = listener;
}
#Override
public void onPostExecute(asynctask.Payload payload) {
\\update UI
mal.onSuccessfulExecute(int numberOfSongList);
}
}
Now, whenever your AsyncTask is done, it will call the method onSuccessfulExecute in your Activity class which should look like:
#Override
public void onSuccessfulExecute(int numberOfSongList) {
\\do whatever
}
Good luck.