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.
Related
I am trying to learn MultiThreading in android although my code works fine when I print the data on Logcat window but my app crashes and gives me a null point exception whenever I try to update a component from the asynctask.
It gives me the following error
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.append(java.lang.CharSequence)' on a null object reference
at com.shivam.asynctasks.MainActivity.logm(MainActivity.java:41)
Line 41
textView.append(message + "\n");
My Code
public class MainActivity extends AppCompatActivity {
Button button ;
TextView textView;
String TAG = "MyTag";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=findViewById(R.id.button);
textView=findViewById(R.id.TextView);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String TAG ="MyTag";
Log.d(TAG,"OnClick Thread Started");
MyTask mytask =new MyTask();
mytask.execute("Red","Black","Yellow","Blue","Orange");
}
});
}
public void logm(String message) {
Log.d(TAG, message);
textView.append(message + "\n");
}
}
class MyTask extends AsyncTask<String,String,String>{
#Override
protected String doInBackground(String... strings) {
String TAG = "MyTag";
for (String value :
strings) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "do in Background : "+value);
publishProgress(value);
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
MainActivity mainActivity =new MainActivity();
for (String color : values) {
mainActivity.logm(color);
}
}
}
You need to reference your activity not create new one. Here you can see.
import android.os.AsyncTask;
public class MainActivity extends AppCompatActivity {
Button button ;
TextView textView;
String TAG = "MyTag";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=findViewById(R.id.button);
textView=findViewById(R.id.TextView);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String TAG ="MyTag";
Log.d(TAG,"OnClick Thread Started");
MyTask mytask =new MyTask(this);
mytask.execute("Red","Black","Yellow","Blue","Orange");
}
});
}
public void logm(String message) {
Log.d(TAG, message);
textView.append(message + "\n");
}
}
class MyTask extends AsyncTask<String,String,String> {
WeakReference<MainActivity> mainActivityRef;
public MyTask(MainActivity activity){
mainActivityRef = new WeakReference<MainActivity>(activity);
}
#Override
protected String doInBackground(String... strings) {
String TAG = "MyTag";
for (String value :
strings) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "do in Background : "+value);
publishProgress(value);
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
MainActivity mainActivity = mainActivityRef.get();
for (String color : values) {
mainActivity.logm(color);
}
}
You are getting the error because the you are creating the instance of the mainactivity class again inside the onProgressUpdate() method whose textView is not initiated. Thats why you are getting the null pointer exception as the textview field is not being initiated.
There is a simple solution to your problem. The onProgressUpdate() method runs on the main UI thread and you have the access to the textview variable inside the onProgressUpdate() method. so simply do the following:
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
MainActivity mainActivity =new MainActivity();
for (String color : values) {
textView.append(color + "\n");
}
}
In my Android project, inside the MainActivity I have :
String receivedData = new myTask().execute().get();
Now myTask-task is:
public class MainActivity extends Activity {
private Button button;
private TextView finalResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.btn_do_it);
finalResult = (TextView) findViewById(R.id.tv_result);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String receivedData = new myTask().execute().get();
finalResult.setText(receivedData);
}
});
}
private class myTask extends AsyncTask<String, Void, String> {
#Override
protected Void doInBackground(Void... params) {
Gson gson = new Gson();
List<Myobject> newObject = new ArrayList<Myobject>();
try {
//here I add object valus to the list
newObject.add(valueadded)
} catch {
Exception e
}
//here returning the value as String
return gson.toJson(newObject);
}
protected void onPostExecute(String result) {
String receivedData = result;
}
}
}
But receivedData is not receiving any value from AsyncTask.
Why is that so? What am I doing wrong?
Your AsyncTask is defined as this:
private class myTask extends AsyncTask<String, Void, Void>
The last generic type is the type of your result. You have Void there. That means your AsyncTask does not return a value. If you want a String result, you will have to define it like this:
private class myTask extends AsyncTask<String, Void, String>
This means you can now return a String from doInBackground().
Try something like this
public class MainActivity extends Activity {
String receivedData;
private Button button;
private TextView finalResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.btn_do_it);
finalResult = (TextView) findViewById(R.id.tv_result);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new myTask().execute().get();
}
});
}
private class myTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(Void... params) {
Gson gson = new Gson();
List<Myobject> newObject = new ArrayList<Myobject>();
try {
//here I add object valus to the list
newObject.add(valueadded)
} catch (Exception e) {
//here returning the value as String
return gson.toJson(newObject);
}
}
protected void onPostExecute(String result) {
String receivedData = result;
finalResult.setText(receivedData);
}
}
}
You can add onPostExecute method inside the AsynchTask to receive the String. Like Below
private class myTask extends AsyncTask<String, Void, String> {
#Override
protected Void doInBackground(Void... params) {
.........
return someString;
}
protected void onPostExecute(String result) {
String receivedData = result;
}
}
I have app where i generate longitude and latitude from address i use AsyncTask where i start in doInBackground generating coordinates my problem is that in my code it appears that Handler is not turned on when i put this line :
viedotGeoCoo();
outside from AsyncTask it appears that everything is working perfectly.
This is my code:
public class AddEvent extends Activity {
Button addressButton, timeButton;
TextView addressTV,textView2;
TextView latLongTV, longCo, textView4;
EditText editNosaukums;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_event);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
addressTV = (TextView) findViewById(R.id.addressTV);
latLongTV = (TextView) findViewById(R.id.latLongTV);
longCo = (TextView) findViewById(R.id.longCo);
textView4 = (TextView) findViewById(R.id.textView4);
editNosaukums = (EditText) findViewById(R.id.editNosaukums);
textView2 = (TextView) findViewById(R.id.textView2);
addressButton = (Button) findViewById(R.id.addressButton);
addressButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.addressButton:
DownloadFilesTask task = new DownloadFilesTask();
task.execute((Void[]) null);
break;
}
}
});
}
private class DownloadFilesTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... urls) {
Looper.prepare();
viedotGeoCoo();
return null;
}
protected void onProgressUpdate(Void... progress) {
}
protected void onPostExecute(Void result) {
Log.e("Add_Event", "GEO IZDEVAAS");
sutitDatus();
}
}
public void viedotGeoCoo() {
EditText editValsts = (EditText) findViewById(R.id.editValsts);
EditText editPilseta = (EditText) findViewById(R.id.editPilseta);
EditText editIelaNr = (EditText) findViewById(R.id.editIelaNr);
String valsts = editValsts.getText().toString();
String pilseta = editPilseta.getText().toString();
String ielanr = editIelaNr.getText().toString();
String address = valsts + " "+ pilseta + " " + ielanr;
Log.e("ADD_EVENT", "HANDLER SAAKAS");
GeocodingLocation locationAddress = new GeocodingLocation();
locationAddress.getAddressFromLocation(address,
getApplicationContext(), new GeocoderHandler());//jadublice jaataisa speciala klase
GeocodingLocationLat locationAddressLat = new GeocodingLocationLat();
locationAddressLat.getAddressFromLocation(address,
getApplicationContext(), new GeocoderHandlerLat());//jadublice jaataisa speciala klase
Log.e("ADD_EVENT", "GEO GENEREETS");
}
//sanjem stringu no com.wunderlist.slidinglayersample.GeocodingLocation.java
private class GeocoderHandler extends Handler {
#Override
public void handleMessage(Message message) {
Log.e("Add_Event", "HANDLER_LONG");
}
}
private class GeocoderHandlerLat extends Handler {
#Override
public void handleMessage(Message message) {
Log.e("Add_Event", "Handler_Lat");
}
}
}
Has anyone have any idea why my code is not working properly?
You calling videotGeoConn() in background Thread but Thread is exiting after doInBackground
You can call a constructor from super class and pass main looper:
private class GeocoderHandlerLat extends Handler {
public GeocoderHandlerLat(){
super(Looper.getMainLooper());
}
#Override
public void handleMessage(Message message) {
Log.e("Add_Event", "Handler_Lat");
}
}
Or you can add a paremeter to videotGeoConn and create handler in onPreExecuteMethod:
private class DownloadFilesTask extends AsyncTask<Void, Void, Void> {
private GeocoderHandlerLatHandler handler;
protected void onPreExecute(){
handler = new GeocoderHandlerLat();
}
protected Void doInBackground(Void... urls) {
// Looper.prepare() is not needed
viedotGeoCoo(handler);
return null;
}
}
I want to bring up a progress dialog when the user loads up the twitter feed and when the twitter feed has loaded the progress dialog disappears.
This is the TwitterAsyncTask class:
public class TwitterAsyncTask extends AsyncTask<Object, Void, ArrayList<TwitterTweet>> {
ListActivity callerActivity;
private ProgressDialog pd;
final static String TWITTER_API_KEY = "ddd";
final static String TWITTER_API_SECRET ="fffff";
Context cnt;
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(cnt.getApplicationContext());
pd.setMessage("loading");
pd.show();
}
#Override
protected ArrayList<TwitterTweet> doInBackground(Object... params) {
ArrayList<TwitterTweet> twitterTweets = null;
callerActivity = (ListActivity) params[1];
if (params.length > 0) {
TwitterAPI twitterAPI = new TwitterAPI(TWITTER_API_KEY,TWITTER_API_SECRET);
twitterTweets = twitterAPI.getTwitterTweets(params[0].toString());
}
return twitterTweets;
}
#Override
protected void onPostExecute(ArrayList<TwitterTweet> twitterTweets) {
ArrayAdapter<TwitterTweet> adapter =
new ArrayAdapter<TwitterTweet>(callerActivity, R.layout.twitter_tweets_list,
R.id.listTextView, twitterTweets);
callerActivity.setListAdapter(adapter);
ListView lv = callerActivity.getListView();
lv.setDividerHeight(0);
lv.setBackgroundColor(callerActivity.getResources().getColor(R.color.white));
if (pd != null)
{
pd.dismiss();
}
}
}
And here is the class that calls the TwitterAsyncTask class:
public class MainActivity extends ListActivity {
final static String twitterScreenName = "CFABUK";
final static String TAG = "MainActivity";
private AsyncTask<Object, Void, ArrayList<TwitterTweet>> tat;
boolean done;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
done = false;
AndroidNetworkUtility androidNetworkUtility = new AndroidNetworkUtility();
if (androidNetworkUtility.isConnected(this)) {
new TwitterAsyncTask().execute(twitterScreenName, this);
} else {
Log.v(TAG, "Network not Available!");
}
}
public void timerDelayRemoveDialog(long time, final ProgressDialog d) {
new Handler().postDelayed(new Runnable() {
public void run() {
d.dismiss();
}
}, time);
}
}
the error seems to appear for the line pd = new ProgressDialog(cnt.getApplicationContext());...What should I put for this? thanks
Just add Constructor in your AsyncTask like
Context mContext;
public TwitterAsyncTask(Context mContext){
this.mContext=mContext;
}
And from your activity
Context mContext=this;
new TwitterAsyncTask(mContext).execute(twitterScreenName, this);
Instead of cnt.getApplicationContext() replace it with YourClassName.this
Embed your Async task in your activity, and replace your Context cnt by YourActivity.class... And please include some log.
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().