I've been learning Android programming for the last 3 weeks or so and I'm developing an app that takes the user's result using an EditText and Translating it to the user's language of choice using Microsoft Translate API.
the Problem I'm facing is i couldn't get the application to let the user select a language from the menu and then translate the text given in the EditText box. This problem is due to my unfamiliarity with AsyncTask, i tried to run the application without using it but it would return the e exception. It does work however when i select one default language as shown in the following code
class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
@Override
protected Boolean doInBackground(Void... arg0) {
Translate.setClientId("MicrosoftTranslatorJavaAPI");
Translate.setClientSecret(secret_key);
try {
translatedText = Translate.execute(et.getText().toString(), Language.ENGLISH, Language.FRENCH);
} catch(Exception e) {
translatedText = e.toString();
}
return true;
}
}
Any help would be appreciated
Here is the full code.
java file
public class MicrosoftTranslatorAndroidTestActivity extends Activity {
/** Called when the activity is first created. */
TextView text;
String translatedText;
EditText et;
PopupMenu popupMenu;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
et=(EditText) findViewById(R.id.editText1);
Button b=(Button) findViewById(R.id.button1);
text = (TextView) findViewById(R.id.tv1);
text.setText("<This text should change after translation has occurred in AsyncTask>");
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
popupMenu = new PopupMenu(MicrosoftTranslatorAndroidTestActivity.this, v);
popupMenu.getMenuInflater().inflate(R.menu.popmenu, popupMenu.getMenu());
new MyAsyncTask() {
protected void onPostExecute(Boolean result) {
text.setText(translatedText);
}
}.execute();
popupMenu.show();
}
});
}
class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
@Override
protected Boolean doInBackground(Void... arg0) {
Translate.setClientId("MicrosoftTranslatorJavaAPI");
Translate.setClientSecret(secret_key);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()){
case R.id.ar:
try {
translatedText = Translate.execute(et.getText().toString(), Language.ENGLISH, Language.ARABIC);
} catch(Exception e) {
translatedText = e.toString();
}
break;
case R.id.fr:
try {
translatedText = Translate.execute(et.getText().toString(), Language.ENGLISH, Language.FRENCH);
} catch(Exception e) {
translatedText = e.toString();
}
break;
case R.id.sp:
try {
translatedText = Translate.execute(et.getText().toString(), Language.ENGLISH, Language.SPANISH);
} catch(Exception e) {
translatedText = e.toString();
}
break;
default:
break;
}
return true;
}
});
return true;
}
}
You can't access ui methods (such as launching a popup menu) from a background thread.
What's more, that would result in having your popup shown but the runInBackgroundMethod would finish in any case and your translate.execute would not be called.
You have to decouple the asyncrhonous interaction with translate from the interactions with the ui elements. Assuming that you need to perform the Translate.execute() method in a background thread, what you should do is to fetch the parameters of the translation BEFORE launching the backgound thread and fetch the results in your asyncthread's onPostExecute().
Something like
private class TranslateTask extends AsyncTask<String, Void, String> {
protected void onProgressUpdate() {
}
protected void onPostExecute(String... result) {
String translated = result[0];
}
@Override
protected String doInBackground(String... params) {
String toTranslate = params[0];
String language = params[1];
// translate here and return the result
return translated;
}
}
and then call
translateTask.execute(toTranslate, language);