How do I put the translation api code to AsyncTask? - java

I am working on to speech to text with translation. What I want to do is when the user inputs his/her voice, there will be an automatic translation based on what it is selected in the spinner.
This is the code from my project, I am receiving an error android.os.NetworkOnMainThreadException. And the solution that I found was to put it in async.
I tried searching around the internet and even asked forums, I cannot find a solution to put this code inside a asynctask. This is the code where I want to put in async.
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Translate translate = TranslateOptions.getDefaultInstance().getService();
TextView translatedText = view.findViewById(R.id.translatedText);
switch (position){
case 1:
Translation enTranslation = translate
.translate(translatedText
.getText()
.toString(), TranslateOption.sourceLanguage("en"), TranslateOption.targetLanguage("en"));
translatedText.setText(enTranslation.getTranslatedText());
break;
case 2:
Translation filTranslation = translate
.translate(translatedText
.getText()
.toString(), TranslateOption.sourceLanguage("en"), TranslateOption.targetLanguage("fil"));
translatedText.setText(filTranslation.getTranslatedText());
break;
case 3:
Translation cebTranslation = translate
.translate(translatedText
.getText()
.toString(), TranslateOption.sourceLanguage("en"), TranslateOption.targetLanguage("ceb"));
translatedText.setText(cebTranslation.getTranslatedText());
break;
}
}
I expected that I won't get android.os.NetworkOnMainThreadException. Thanks in advance :)

Using AsyncTask
You can use an AsyncTask. It has 3 steps to it.
1. onPreExecute() - things you want to do before running doInBackground(). This happens in the UI main thread.
2. doInBackground()- the AsyncTask, will do operations in a background thread (the background thread is created by Android so you don't need to worry about it).
3.onPostExecute() - here you can receive any data from the doInBackground method. The postExecute method is executed again, in the UI main thread.
So you can do any I/O operations in doInBackground(), and return the value you received from the server or any other data source.
How to Declare
To use AsyncTask, you need to extend the Android AsyncTask.
So your own AsyncTask declaration will look like this:
private class MyAsyncTask extends AsyncTask<Void, Void, Void> { ... }
What are the 3 generic arguments you ask?
1. Params - the type of the parameters sent to the task upon execution.
2. Progress - the type of the progress units published during the background computation. (Almost always will be Void, unless you care about the actual progress of the operation. Notice this is Void with a capital letter, and not void as the return type).
3. Result - the type of the result of the background computation.
Full Example
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = findViewById(R.id.output);
txt.setText(result);
}
}
In the example, I create a fake, long operation, that you can not run on the UI main thread (because it is a blocking operation).
When the operation is finished, it returns a String, and that same String is received in the onPostExecute() method (and remember, onPostExecute() runs on the UI main thread again). So you can change your UI with the String value you received from the long,blocking operation.
If you want the documentation, here it is:
https://developer.android.com/reference/android/os/AsyncTask

Related

AsyncTask executes at the end of the function

I am using AsyncTask so that the function I want executes immediately and does not wait till the end to be executed..
but for some reason I don't why it executes in at the end of all process!
I looked at other solutions and found that Thread should be executed at the end but for AsyncTask it should be executed whenever it is called..
here is my code
private void LogMeIn()
{
string CheckValue;
// Here I call the AsyncTask
new GCM().execute(null,null,null);
//gcmRegID is a public variable and should has GCM value assigned to it by now, but I it is empty as GCM() has not been executed yet
//This is always return empty string
CheckValue = gcmRegID;
}
This is the AsyncTask that wait till the end to be executed
//This is the AsyncTask
private class GCM extends AsyncTask<String, String, String> {
private String resp;
private Context context;
#Override
protected String doInBackground(String... params) {
GCMHelper gcmRegistrationHelper = new GCMHelper (
getApplicationContext());
try {
gcmRegID = gcmRegistrationHelper.GCMRegister("123456789");
} catch (Exception e) {
e.printStackTrace();
}
return gcmRegID;
}
}
I tried to put the call for GCMRegister in onPreExecute but i get an error that it has to be in the main thread
it is like i am going in circles....
the call has to be in the main thread and the main thread will be executed at the end of the function...
it is like no way to get the GCM code in the middle!!!!
How can I make this AsyncTask executes when it called??
Thanks
Without seeing more of your code it's hard for me to tell but I would take a look at where you are calling LogMeIn(). Because your AsyncTask and call to execute are nested in the LogMeIn() function, it won't be called until LogMeIn() is first called.
AsyncTask goes through the following 4 steps in order after calling execute():
onPreExecute()
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
These can be added to your GCM class and used however you like. Note that you don't call them directly. AsyncTask does it automatically after calling .execute().
Only the tasks specified in doInBackground(Params...) are executed on a background thread. The rest are all done on the UI(or main) thread. I would suggest putting either a toast or a log inside onPreExecute() and in onPostExecute() to debug where/when GCM().execute is actually being called and then to tell you when the background task is complete. This will give you a better idea of what is going on.
Make sure you aren't trying to update the UI in doInBackground().
Would love to help more but we would need to see more of your code.
#Override
public void onPreExecute() {
super.onPreExecute();
Log.d("GCM", "onPreExecute: called");
}
#Override
public void onPostExecute(String resultOfDoInBackground) {
super.onPostExecute(resultOfDoInBackground);
Log.d("GCM", "onPostExecute: called");
}
AsyncTask keeps a queue of tasks and a thread pool,the thread pool execute the tasks one by one,so if you have too more tasks ,you will find it not execute your tasks immediately.
And in one process ,all your AsyncTask share one thread pool.In this case,you should make one task queue by yourself,you can just use HandleThread to execute a timely task.
Try placing your new GCM().execute(null,null,null); in the protected void onCreate(Bundle savedInstanceState) method. this way it will be called once the app is ran. This way you will have your GCM id before you get to the LogMEIn method.
Try this -
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new GCM().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params);
} else {
new GCM().execute();
}

Activity collides with AsyncTask? How to implement AsyncTask into GUI?

I am sorry for my bad english skills. I'm new to programming/stackoverflow and try to create a little android quiz app. This app has to connect to a php server and login/getquestion...
The simplest example is the login. The user has to type in his data and then i have to connect.
To provide that the Gui doesnt freeze i have to use asynchronous tasks.
Here the activity's code:
public void login(final String username, final String password) {
final Activity a = this;
FutureTask t = new FutureTask(new Callable() {
public Object call() {
Connection.GetInstance(a).login(username,password);
afterLoginTry(username,password);
return null;
}
});
t.run();
}
This calls a method in another class, which calls another FutureTask which calls an AsyncTask. At the end there is always an public synchronized method such as afterlogintry(). This works but it's a bit slow and i think dirty code.
My main problem is that i don't know how to give results back through different layers of classes and especially to the activity without using hotfixes all the time.
Is there any good explanation or tutorial, which describes how to design such a construct?
Thx for help
The way you can pass AsyncTask results back to other classes, is by declaring callbacks for the task, that will then report the result to a listener. Here is how it works.
First, you must declare an interface in your AsyncTask which contains a method that will send out the result of the task. So in my example task below, my result is a String. The String gets passed to onPostExecute() when the task finishes its work. I then call my callback method on a registered listener, and pass that return value on to whoever is listening for it. You register a listener by passing in an instance of your callbacks from whichever class is creating the task.
public class MyTask extends AsyncTask<String, Void, String> {
MyTaskCallback listener;
public MyTask(MyTaskCallback listener) {
this.listener = listener;
}
protected String doInBackground(String... params) {
String input = params[0];
//do work
input += "did some work on this String";
return input;
}
//When the thread finishes its work, this gets
//called on the main UI thread
protected void onPostExecute(String result) {
listener.onResultReceived(result);
}
public interface MyTaskCallback {
void onResultReceived(String result);
}
}
So next we need to register a listener for these callbacks, so when the result comes in from the task, it will get reported directly to our class. So let's say we have a simple Activity. The way we register the callbacks is to use the implements keyword on our class declaration, and then to actually implement the callback method in the class itself. We then create our task, and we pass in this which is our Activity that implements the callbacks. A simple example Activity that does this looks like this:
public class TaskActivity extends AppCompatActivity implements MyTask.MyTaskCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
//we pass in "this" because our Activity itself
//implements the callbacks below.
MyTask myTask = new MyTask(this);
myTask.execute();
}
//Here we implement our callback method, so the task
//can send its results straight through here
public void onResultReceived(String theResult) {
Log.d("TASK RESULT", "Here is our result String: "+theResult);
}
}
Now, our task has our Activity connected to it, through the callbacks we passed into it. So now when our task gets a result, we can send it directly to our listener, which is our Activity, and the result will come right through to our implemented onResultReceived method.
Callbacks are a great way to pass information around between classes while also keeping everything very separated. Hope this helps!

Using an AsyncTask to call a Handler. Is this good practice?

I want to know whether a practice I am using is correct or not? Please have a look!
I am using an AsyncTask to call a Handler to animate (increment gradually over time) the progress in a ProgressBar.
I could only use Handler to animate it but I needed to animate multiple ProgressBars using the same Handler. I did not find it possible to pass a paramerer "ProgressBar" to a Handler, nor did declaring a global variable (maybe array?) looked clean.
So I pass the ProgressBar into an AsyncTask as a parameter, and then within the AsyncTask, I have defined the Handler which manipulates the passed ProgressBar using the method of AsyncTask called publishProgress(int). So Each call to AsyncTask is effectively equal to serving the Handler a unique passed ProgressBar.
I am including a stripped down code which shows the structure:
public class animateProgress extends AsyncTask<ArrayList<ArrayList>, Integer, Boolean> {
ProgressBar pb;
int incrementProgress;
#Override
protected Boolean doInBackground(ArrayList<ArrayList>... arrayLists) {
ArrayList<ArrayList> gotArrayList = arrayLists[0]; //get passed arraylist
ArrayList<ProgressBar> alP = gotArrayList.get(1);
pb = alP.get(0); // REFERENCE TO PROGRESSBAR IS ACQUIRED HERE.
scoreCounter.postDelayed(scoreCounterUpdate, 0);
return null;
}
private Handler scoreCounter = new Handler();
private Runnable scoreCounterUpdate = new Runnable() {
public void run() {
if (MY_LOGIC_THAT_PROGRESS_SHOULD_INCREMENT) {
publishProgress(incrementProgress);
}
if (MY_LOGIC_THAT_WE_SHOULD_EXIT) {
scoreCounter.removeCallbacks(scoreCounterUpdate);
} else {
scoreCounter.postDelayed(this, 50);
}
}
};
#Override
protected void onProgressUpdate(Integer... values) {
pb.incrementProgressBy(values[0]);
super.onProgressUpdate(values);
}
}
The code works perfectly but my concern is that I think I should either not use AsyncTask or not use Handler.
Also, I think that doInBackground() should theoretically finish as soon as I call scoreCounter.postDelayed(), and so should the whole AsyncTask. But in reality, the publishProgress() called by handler many seconds later still works. This is confusing.

Wait for thread, get its result, show progressbar in the process and do not block UI Thread

So as the title probably suggests - I've done a lot of research on the topic, but I am still confused and unable of achieving what I want.
In very simplified scenario, I have a LoginActivity in which is method boolean validateUserInput(String mail, String password) and I want to do the check input in the separate thread. I suppose I will extend it in the future to do the log-in itself as well (http request). Naturally I would like to get boolean value if the operation was successful or not - and in the process of operation I want to show progressbar dialog.
Make a thread, run the code, return its result, show the progress bar in a meantime, piece of cake right?
Should I use asynctask or runnable? How do I do this so I do not block the UI thread?
This is code I tried to use in LoginActivity:
new Thread(new Runnable() {
#Override
public void run() {
mUserInputValidated = validateUserInput(inputEmail.getText().toString(), inputPassword.getText().toString());
}
}).start();
if(mUserInputValidated)
{
attemptUserLogin(inputEmail.getText().toString(), inputPassword.getText().toString());
}
I also tried asynctask approach, but ended up with various errors since I started progress dialog in onPreExecute() and ended it in onPostExecute(), using reference like LoginActivity.this where was the problem with memory leak which I was also unable to fix?
I assume this is pretty usual scenarios, since almost every app use it, so - what are common approaches? How do I fix my code?
You have to use asynctask this will take the work off from main-thread and place it on background thread once the work is done
This is a sample that shows how to do it
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// might want to change "executed" for the returned string passed
// into onPostExecute() but that is upto you
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
Reference

Asynctask ArrayList object not passing from doInBackground to onPostExecute

I have an AsyncTask that takes in context (used onPostExecute) and runs doInBackground to return an ArrayList of objects from a server. When I execute this I can see that doInBackground runs fine, however it is not passing the result on to onPostExecute.
After much searching, I have yet to find an answer of how to return an ArrayList of objects in an AsyncTask.
This is the object I'm creating in doInBackground and using onPostExecute:
public class ServerTimeCard {
public String eventNameInput;
Boolean isLocation, isImage, isVoice;
public ServerTimeCard(String eventNameInput, boolean isLocation, boolean isImage, boolean isVoice) {
this.eventNameInput = eventNameInput;
this.isLocation = isLocation;
this.isImage = isImage;
this.isVoice = isVoice;
}
}
I'm executing the AsyncTask with new LoadFriendCards(context).execute(); in onCreate.
Expected Output: doInBackground should return an ArrayList to onPostExecute
Current Output: The ArrayList<ServerTimeCard> in onPostExecute has a size of zero when the same arraylist in doInBackground has a larger size.
The following is the AsyncTask code.
public class LoadFriendCards extends AsyncTask<Void, Void, ArrayList<ServerTimeCard>> {
Context context;
ArrayList<ServerTimeCard> result;
public LoadFriendCards(Context context) {
this.context = context;
}
#Override
protected ArrayList<ServerTimeCard> doInBackground(Void... voids) {
result = new ArrayList<ServerTimeCard>();
// ...a bunch of data retrieval goes on here...
// querying parse for object info
// adding a new object to the local ArrayList for all in db
for (String friend : friendsListNames) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("TestObject");
query.whereEqualTo("accountName", friend+"#gmail.com");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
for (ParseObject cardInfo : objects) {
ServerTimeCard item = new ServerTimeCard(
cardInfo.getString("eventName"),
cardInfo.getBoolean("isImage"),
cardInfo.getBoolean("isImage"),
cardInfo.getBoolean("isVoice"));
result.add(item);
Log.e("New item called: ", String.valueOf(item.eventNameInput));
Log.e("New size of array...", String.valueOf(result.size()));
}
} else {
Log.d("info", "Error: " + e.getMessage());
}
}
});
}
// returning the new ArrayList<ServerTimeCard> to onPostExecute
// PROBLEM: THE SIZE OF THE RESULT IS 0
Log.e("Size of passing array", String.valueOf(result.size()));
return result;
}
#Override
protected void onPostExecute(ArrayList<ServerTimeCard> result) {
// PROBLEM: This returns 0
Log.e("Data list size: ", String.valueOf(result.size()));
// trying to use all objects in the arraylist here but it doesn't work
// due to the size. Something isn't passing correctly.
}
}
Logcat output of Log.e: (which looks like it calls doInBackground, then onPostExecute, then doInBackground again)
E/Size of passing array﹕ 0
E/Data list size:﹕ 0
E/New item called:﹕ yah
E/New size of array...﹕ 1
E/New item called:﹕ lplokolol
E/New size of array...﹕ 2
E/New item called:﹕ It works
E/New size of array...﹕ 3
SOLVED: I originally thought I needed the AsyncTask but I ended up deleting it all and throwing all the code into a method in my Main class. I was running too many things at once in an asynctask and the structure was throwing data all over the place. Lesson learned: keep it simple.
Your issue is that you are using findInBackground for your query. That method is done in a background thread. So you're basically running an async task, within an async task.
doInBackground
findInBackground -> run asynchronously so code execute continues
onPostExecute is called before your query finishes.
The done call back is then called for your query to fill your list
So what you need to do instead is either use findInBackground outside of an AsyncTask (that method is intended to not be used in an AsyncTask) or use the find function.
You're modifying result in an anonymous inner class. Your code there doesn't see the result you think it sees, but rather a closure. This is the root of the problem.
You are starting a background thread (your async task), and here you call query.findInBackground() multiple times which starts MORE background threads. This, however, isn't a problem.
You're getting problems because the AsyncTask is done before all the other threads it started have finished. You only know the other threads are done when each of their FindCallback's done() method is called.
If you want to know the correct size, you need to code it in a way so that you check the size in the last done() method.
You dont have to make doInBackground to return an arraylist which can be used in onPostExecute. Just return "ok" or "error". Declare and create a private arraylist as member of your ask. Then fill it in doInBackground and use it in onPostexecute.
An alternative and simpler way is to declare your doInBackground as List type.
Here is my Example
#Override
protected ArrayList<ServerTimeCard > doInBackground(String... urls) {
// Perform the HTTP request for earthquake data and process the response.
ArrayList<ServerTimeCard > result = QueryUtils.fetchTheData(urls[0]);
return result;
}

Categories