Android Handler unable to access GUI elements - android

I feel kind of dumb asking this question because I have another app that this works for fine or at least I think it is the same. I definitely need another set of eyes on this because to me, it looks like it should work. My code is below:
public class InventorySystemActivity extends Activity {
private EditText barcode;
private EditText proddesc;
private EditText quantity;
public String scan_result;
public int which;
private InventorySystemDB db;
public Item singleItem;
public Item[] itemList;
private Thread t;
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
barcode.setText(scan_result);
proddesc.setText(singleItem.name);
quantity.setText(singleItem.quantity);
break;
case 3:
updateUI();
pd.dismiss();
}
}
};
public static Intent in = new Intent("com.google.zxing.client.android.SCAN");
private ProgressDialog pd;
private Thread dbt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.db = new InventorySystemDB(this);
try {
this.db.createDataBase();
this.db.openDataBase();
} catch (Exception e) {
e.printStackTrace();
}
this.dbt = new Thread(this.db);
setContentView(R.layout.main);
Button scan = (Button) findViewById(R.id.scan);
scan.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
startActivityForResult(in, 0);
}
});
Button search = (Button) findViewById(R.id.searchbutton);
search.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
pd.show();
which = 1;
scan_result = barcode.getText().toString();
dbt.start();
}
});
barcode = (EditText) findViewById(R.id.barcodenum);
proddesc = (EditText) findViewById(R.id.proddesc);
quantity = (EditText) findViewById(R.id.prodquantity);
pd = new ProgressDialog(this);
pd.setMessage("Loading data...");
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
scan_result = intent.getStringExtra("SCAN_RESULT");
barcode.setText(scan_result);
} else if (resultCode == RESULT_CANCELED) {
}
}
}
private void updateUI() {
barcode.setText(singleItem.upc);
proddesc.setText(singleItem.name);
quantity.setText("0");
}
}
All my thread does is it takes the UPC number and pulls up info from a couple websites. The code sends the message to the handler just fine and I've made a few apps like this using threads and handlers, not sure why I have this issue now. Anyway, I can dismiss the ProgressDialog, but I am unable to update any UI objects. It all looks fine to me, so I really need some more sets of eyes on this. Thanks guys.

You need to do UI changes in runOnUIThread()

Related

How can i code a time limit in my android game

i have a quiz game for my android that has a time limit. what i want is there is a choices button that if you click one of the buttons it you will be automatically intent to the class next level but if you didnt answer or click any of the button you will be intent to the other class, thats why the game has a time limit. my problem is i dont know how to put a time limit that will intent or transfer you in another class automatically if you didnt click any of the button choices. i tried sleep but what happen is even i already clicked the correct answer and im on the next level class it will sleep to the class i intented to my sleep. please help me with my problem. i also try handler but didnt work
public class EasyOne extends Activity {
Button a, b, c;
TextView timer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.easyone);
a = (Button) findViewById(R.id.btn_ea1);
b = (Button) findViewById(R.id.btn_eb1);
c = (Button) findViewById(R.id.btn_ec1);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"CORRECT!",
Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getApplicationContext(),EasyTwo.class);
startActivity(intent);
}
});
}
private Runnable task = new Runnable() {
public void run() {
Handler handler = new Handler();
handler.postDelayed(task, 5000);
Intent intent = new Intent(getApplicationContext(),TimesUp.class);
startActivity(intent);
}
};
You should use a handler but in order to cancel the timeout you must remove the delayed message from the handler in your click listener code.
public class EasyOne extends Activity {
static private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 123) {
((EasyOne) msg.obj).onTimeout();
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.easyone);
a = (Button) findViewById(R.id.btn_ea1);
b = (Button) findViewById(R.id.btn_eb1);
c = (Button) findViewById(R.id.btn_ec1);
Message msg = mHandler.obtainMessage(123,this);
mHandler.sendMessageDelayed(msg,5000);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"CORRECT!",
Toast.LENGTH_SHORT).show();
mHandler.removeMessages(123,this);
Intent intent = new Intent(getApplicationContext(),EasyTwo.class);
startActivity(intent);
}
});
}
private void onTimeout() {
//your code
}
}

ViewRoot$CalledFromWrongThreadException on android app

I have read some threads regarding this and I did already take steps to resolve it.
I am using a handler (so that I don't update the UI on a separate thread) and so far I can't understand why this is still happening.
public class MyApp extends Activity implements OnClickListener, Runnable {
private ViewSwitcher switcher;
private static final int REFRESH_SCREEN = 1;
private boolean isValid = false;
private ProgressDialog dialog;
private TextView errorMessage;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(this);
TextView errorMessage = (TextView)findViewById(R.id.txtErrorMessage);
errorMessage.setVisibility(View.GONE);
switcher = (ViewSwitcher) findViewById(R.id.profileSwitcher);
}
public void onClick(View v)
{
isValid = false;
dialog = ProgressDialog.show(ConcentraApp.this, "", "Loading. Please wait...", true);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
String username = ((TextView)findViewById(R.id.txtUsername)).getText().toString();
String password = ((TextView)findViewById(R.id.txtPassword)).getText().toString();
errorMessage = (TextView)findViewById(R.id.txtErrorMessage);
errorMessage.setVisibility(View.GONE);
/* ... contact web service and get response ..*/
try {
/* get result from web service */
isValid = Boolean.parseBoolean(result);
if(isValid)
{
handler.sendEmptyMessage(1);
}
else
{
handler.sendEmptyMessage(0);
}
} catch (Exception e) {
handler.sendEmptyMessage(2);
isValid = false;
}
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1)
{
errorMessage.setVisibility(View.VISIBLE);
errorMessage.setText("Correct login");
switcher.showNext();
}
else if(msg.what == 0)
{
errorMessage.setVisibility(View.VISIBLE);
errorMessage.setText("Invalid login");
}
else
{
errorMessage.setVisibility(View.VISIBLE);
errorMessage.setText("Internet error");
}
dialog.dismiss();
}
};
}
I am very new to this so I wouldn't be surprised if I'm missing something obvious.
It works fine without the thread, but then the process dialog doesn't show.
Many thanks in advance
You cannot call this:
errorMessage.setVisibility(View.GONE);
From a background thread. You should do it via handler as well.

How to save state when activity it destroyed with this

public class Talk extends Activity {
private ProgressDialog progDialog;
int typeBar;
TextView text1;
EditText edit;
Button respond;
private String name;
private String textAtView;
private String savedName;
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.dorothydialog);
text1 = (TextView)findViewById(R.id.dialog);
edit = (EditText)findViewById(R.id.repsond);
respond = (Button)findViewById(R.id.button01);
respond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
text1.setText("Welcome! Enter your name!");
respond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
name = edit.getText().toString();
text1.setText("Cool! your name is "+name);
}
});
}
});
}
}
Okay so i want to figure out how i would save the state of this activity. this is just a small snippet from my code to show you guys an example. So i want to save the state so when the activity is destroyed the user will come back where they left off.
Second thing, I would like to show a quick 5 second Progress dialog spinner between each button click.
For the second thing
This should work:
public class TestActivity extends Activity implements Runnable, OnClickListener {
private TextView tv;
private ProgressDialog pd;
private Button btn;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
tv = (TextView) this.findViewById(R.id.tv);
btn = (Button)findViewById(R.id.btn);
tv.setText("initial text");
btn.setOnClickListener(this);
}
public void onClick(View v) {
pd = ProgressDialog.show(TestActivity.this, "Please wait...", "Details here", true, false);
Thread thread = new Thread(TestActivity.this);
thread.start();
}
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
tv.setText("text after 5 sec passed");
}
};
}

TextToSpeech.OnInitListener.onInit(int) being called continuously

I'm getting reports that, on some (not all) HTC Desire HD (FRF91, 2.2) and HTC EVO 4G ( PC36100|3.29.651.5, 2.2), the TextToSpeech.OnInitListener.onInit(int) is being called repeatedly (over 1500 times in the space of a few seconds) on the same object. This behaviour does not occur for any of my other users (or with other Desire HD users) AFAICT.
The code is:
TextToSpeech tts = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
private int mCallCount = 0; // trying to investigate potential infinite loops
#Override
public void onInit(int status) {
if ((mCallCount % 100) == 1) {
// report this
}
mCallCount++;
}
});
Anyone any ideas?
EDIT: I have also tried calling the shutdown() method (the first time multiple listener calls are detected) but this doesn't seem to help.
Maybe you should get around it with your own intermediary method, for example:
private long lastCall = 0;
private long deepBreath = 5*1000; //5 seconds
private boolean hasRested;
TextToSpeech tts = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
long thisCall = Calendar.getInstance().getTimeInMillis();
intermediaryMethod(status, thisCall);
}
});
//new method
public void intermediaryMethod(int status, long thisCall) {
hasRested = (thisCall-lastCall)>=deepBreath;
if (hasRested) {
lastCall = thisCall;
//do something about 'status'
}
}
This may or may not help, but I had a similar problem when call tts from a service, luckily for me I was better off doing my tts from an activity which solved the problem.
If you do this, and it is appropriate, make sure your manifest for the activity has:
android:finishOnTaskLaunch="true"
Try to create object of the Textospeech before on create ie. globally .try this code and check is it still calling many times????
public class TtsActivity extends Activity implements OnInitListener {
private int MY_DATA_CHECK_CODE = 0;
private TextToSpeech tts;
private EditText inputText;
private Button speakButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
inputText = (EditText) findViewById(R.id.input_text);
speakButton = (Button) findViewById(R.id.speak_button);
speakButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String text = inputText.getText().toString();
if (text!=null && text.length()>0) {
Toast.makeText(TtsActivity.this, "Saying: " + text, Toast.LENGTH_LONG).show();
tts.speak(text, TextToSpeech.QUEUE_ADD, null);
}
}
});
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
tts = new TextToSpeech(this, this);
}
else {
// missing data, install it
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
Toast.makeText(TtsActivity.this,
"Text-To-Speech engine is initialized", Toast.LENGTH_LONG).show();
}
else if (status == TextToSpeech.ERROR) {
Toast.makeText(TtsActivity.this,
"Error occurred while initializing Text-To-Speech engine", Toast.LENGTH_LONG).show();
}
}
}

startActivityForResult to an activity that only displays a progressdialog

I'm trying to make an activity that is asked for some result. This result is normally returned instantly (in the onCreate), however, sometimes it is nesesary to wait for some internet-content to download which causes the "loader"-activity to show. What I want is that the loader-activity don't display anything more than a progressdialog (and that you can still se the old activity calling the loader-activity in the background) and I'm wondering wheather or not this is possible.
The code I'm using as of now is:
//ListComicsActivity.java
public class ListComicsActivity extends Activity
{
private static final int REQUEST_COMICS = 1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.list_comics);
Button button = (Button)findViewById(R.id.Button01);
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intents.ACTION_GET_COMICS);
startActivityForResult(intent, REQUEST_COMICS);
}
});
}
/** Called when an activity called by using startActivityForResult finishes. */
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
Toast toast = Toast.makeText(this, "The activity finnished", Toast.LENGTH_SHORT);
toast.show();
}
}
//LoaderActivity.java (answers to Intents.ACTION_GET_COMICS action-filter)
public class LoaderActivity extends Activity
{
private Intent result = null;
private ProgressDialog pg = null;
private Runnable returner = new Runnable()
{
public void run()
{
if(pg != null)
pg.dismiss();
LoaderActivity.this.setResult(Activity.RESULT_OK, result);
LoaderActivity.this.finish();
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
String action = getIntent().getAction();
if(action.equals(Intents.ACTION_GET_COMICS))
{
Runnable loader = new Runnable()
{
public void run()
{
WebProvider.DownloadComicList();
Intent intent = new Intent();
intent.setDataAndType(ComicContentProvider.COMIC_URI, "vnd.android.cursor.dir/vnd.mymir.comic");
returnResult(intent);
}
};
pg = ProgressDialog.show(this, "Downloading", "Please wait, retrieving data....");
Thread thread = new Thread(null, loader, "LoadComicList");
thread.start();
}
else
{
setResult(Activity.RESULT_CANCELED);
finish();
}
}
private void returnResult(Intent intent)
{
result = intent;
runOnUiThread(returner);
}
}
It turns out you can do this by setting the activitys theme-attribute to #android:style/Theme.Dialog and calling this.setVisible(false); in the onCreate-method of the activity.

Categories

Resources