I have a question regarding an Android application. I want to, later on, create a game and i am currently trying out classes and functions that I need to understand.
At the moment im trying to get a grip of how to use threads in a good way, but my application is "force closing" when i touch the button.
For this test application, all have on the screen is one TextView and one button.
The button is calling threadStart() when pressed. (onClick in xml)
And what i want it to do is to create a thread which increases the variable value by 1 and then report to the UI thread which then update the textview with the new value.
Can someone see what i am doing wrong with this small pice of code?
package com.weldeborn.tc;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
public class ThreadCounter extends Activity {
TextView txtCounter1;
int value=0;
final Handler mHandler = new Handler();
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResult();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtCounter1 = (TextView) findViewById(R.id.counter1);
}
protected void threadStart() {
Thread t = new Thread() {
public void run() {
doSomething();
mHandler.post(mUpdateResults);
}
};
t.start();
}
private void doSomething() {
value = value+1;
}
private void updateResult() {
txtCounter1.setText(value);
}
}
My code is based on an example from Android Developer: The Common Tasks and how to do them section under the "Handling Expensive Operations in the UI Thread" heading.
I am thankful for any help.
setText doesn't work correctly when you pass an integer, directly. Try converting it to String before:
txtCounter1.setText(String.valueOf(value));
Also, check this answer about the usage of threads that need to update the UI.
if threadStart is your onClick the signature needs to be
public void threadStart(View v)
Related
I'm facing this problem with TextView. It is not erasing the previous instances of data.
When I'm running my application in emulator it displays output data in TextView. That's fine. But when I'm clicking back button in my emulator and re opening the application it does not clear the previous data. Instead it appends the data to already existing data.
Any help is appreciated.
My code is as below:
public class MainActivity extends ActionBarActivity
{
private TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.text_test);
new Thread(new TestLocalHost()).start();
}
private class TestLocalHost implements Runnable
{
#Override
public void run()
{
final String s = JSONParser.doGet("http://192.168.0.107:15071/GetResult.ashx?op=getInfo",null);
runOnUiThread(new Runnable()
{
#Override
public void run()
{
mTextView.setText(s);
}
});
}
}
}
It's happening because your app still lives in the emulator memory, you need to force kill it if you want your app to run again from scratch.
You should click on the "running processes" button and swipe left/right the app process.
In the scenario that you described the activity wasn't destroyed yet, and when you reopen it only its onResume() method is being called.
I am a newer to Android development. now I want to show current system time in a thread via textview control. I get some example and can start the thread to draw text in textview control.
but when I trid to get system current time via below link:Display the current time and date in an Android application, I got errors,The error saying:getDateTimeInstance() is undefined for the type DateFormat.
Why this answer didn't work for me ? thx.
below is the code for your reference:
public class MainActivity extends Activity {
private TextView timeView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(){
public void run(){
System.out.println("Thread is running!!");
timeView = (TextView)findViewById(R.id.textView1);
String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
timeView.setText("I am Fired via Non-UI thread:"+s);
}
}.start();
}
Updatin ui in a thread not possible
timeView.setText("I am Fired via Non-UI thread:"+s);
Use runOnUiThread. Inside thread's run method
runOnUiThread(new Runnable() {
#Override
public void run() {
timeView.setText("I am Fired via Non-UI thread:"+s);
}
});
Also initialize textview in outside the thread
timeView = (TextView)findViewById(R.id.textView1)
Also check this
http://developer.android.com/reference/java/text/DateFormat.html
Check your import statement.
import java.text.DateFormat // import this
instead of
import android.text.format.DateFormat;
I have this project:
Im trying to undestand where is the problem and how can be solved, but a this simply point I really dont know where is the problem.
I have a button and a TextView.
When the button is clicked this procedure is called:
android:onClick="pulsaboton"
And the TextView show me the output.
This is Main_Activity.java
package com.example.pruebasonidos;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
public String cadena1="", cadena2="";
public TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textview01);
}
public class generamusica extends AsyncTask<String, Integer, Integer>
{
#Override
protected void onPreExecute(){
tv.setText(tv.getText().toString()+"Pre Execute");
}
#Override
protected Integer doInBackground(String...strings) {
String cadena=strings[0];
tv.setText(tv.getText().toString()+cadena);
return null;
}
#Override
protected void onPostExecute(Integer bytes){
tv.setText(tv.getText().toString()+"Post Execute");
}
}
public void pulsaboton(View v) {
cadena1="123"; cadena2="111";
tv.setText("");
new generamusica().execute(cadena1);
new generamusica().execute(cadena2);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
When pulsaboton is clicked, textview1 display this:
PreExecutePreExecute123111PostExecutePostExecute
I want this output:
PreExecute123PostExecutePreExecute111PostExecute
What is the error????
WARNING: INTERFACE MODIFICATION EXECUTED OUTSIDE OF UI THREAD!
protected Integer doInBackground(String...strings) {
...
tv.setText(tv.getText().toString()+cadena);
...
}
Why do you think AsyncTask exposes onPreExecute and onPostExecute? Couldn't you just do all of your interface work in doInBackground, before and after your async code?
In Android, the UI needs to be accessed from the main thread, the foreground thread; which doInBackground is not run in.
If you need to post updates to your UI during the execution of an AsyncTask, use the publishProgress mechanism.
Edit: "properly" accesing the interface is a lot more complex that just using onPreExecute and onPostExecute. See this blog post. Maybe you should try the Loader API, it's less troublesome.
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution..
http://developer.android.com/reference/android/os/AsyncTask.html
You are updating ui on the background thread which is not possible. You need to update ui on the ui thread
In doInBackground()
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
String cadena=strings[0];
tv.setText(tv.getText().toString()+cadena); ;
}
});
For your required output Call these two lines in onPostExecute,
cadena2="111";
new generamusica().execute(cadena2);
And dont try to update the UI in background thread.
See This for more info
The TextToSpeech constructor looks like it's designed to be 'owned' by an Activity. I'm producing an app with multiple different Activities, and I don't want to have to initialise a new TextToSpeech instance for each - I want the speech to carry on smoothly even if the Activity is changing.
My idea is to have a static TextToSpeech object accessed by all activities, initialised by the first one.
Does anyone know if the TextToSpeech implementation is thread-safe? I'm guessing not, but someone out there might know.
If I initialise it with the Context of my default Activity, will the TextToSpeech instance stop working when the Activity is destroyed?
I have never tried that, but I think you can pass an Application context as the parameter in the constructor, not necessarily an Activity.
But paying attention to the documentation, I see that the TTS engine has its own queing system, so you can call speak several times without worrying about the thread timing.
Regardind to your questions, I'm not sure about the number two, but as I wrote first, I would try passing an Application context, rather than Activity context.
About number one, well, there is one instance per engine at a time, I guess. And you normally have just one engine, but again, if the engine controls queries queuing, don't worry about the threads.
Thanks to those that told me to pass the ApplicationContext. Turned out that was the easy bit... The hard bit was whether the TextToSpeech object is guaranteed thread-safe.
Thanks for answers telling me how to make something thread-safe / assuming that it is, but the question was about whether the object already is. I probably should have said, I'm fine with implementing thread-safety, but I wanted to know whether I need to bother. And I don't want to assume thread-safety without being certain.
I ran the following and it seemed to work. So I assume the Android SDK TTS is thread-safe, but can't find any documentation saying that it's safe to assume this across all devices, so I'll be wrapping my TTS instance for the time being!
package com.example.testproject;
import java.util.Random;
import android.os.Bundle;
import android.app.Activity;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
public class TestActivity extends Activity implements OnInitListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tts = new TextToSpeech(getApplicationContext(), this);
}
TextToSpeech tts = null;
#Override
public void onInit(int arg0) {
for (int i = 0; i < 100; ++i) {
class Irritate implements Runnable {
Irritate(int iIn) {
i = iIn;
}
#Override
public void run() {
Random r = new Random();
try {
Thread.sleep(r.nextInt(2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
tts.speak(Integer.toString(i), TextToSpeech.QUEUE_ADD, null);
}
int i;
}
Thread t = new Thread(new Irritate(i));
t.start();
}
}
}
I've always used TTS as an Activity that I startedForResult.
I just fire an intent to it and then wait for it to come back.
If I remember correctly, if returns an array of answers sorted by confidence.
So you if you don't have a Context, then I don't believe there is another way to call it (at least using this model). Not sure if there is an object reference that you can get for it.
However, if there is, to use your idea. Then you can just extend Application and hold the static reference to your TTS in there. That way it's visible to all your Activities. I think this is answer you are looking for.
The above was helpful in helping me resolve this issue. In my case, I had also had a fragment and so, I did the following:
From a fragment (from a fragment, you want to say "getActivity().getApplicationContext()" instead of just "getApplicationContext()") :
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == MY_DATA_CHECK_CODE){
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
tts = new TextToSpeech(getActivity().getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status == TextToSpeech.SUCCESS){
result = tts.setLanguage(Locale.UK);
}
}
});
} else {
// missing data, install it
Intent installIntent = new Intent();
// The ACTION_INSTALL_TTS_DATA intent will take the user to Android Market, and will let the user initiate the download
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
TextToSpeech is not thread-safe with respect to the GUI, because a TextToSpeech listener method is called from a non-GUI thread.
If your listener methods interact with the GUI, you will have to include code to put the GUI changes into the Looper for the GUI thread.
There are plenty of examples of how to wrap a GUI command in a Handler and post it on the GUI thread's looper. Here is a sketch of what you'd do:
public class SpeechUtteranceListener extends UtteranceProgressListener {
#Override
public void onDone(String utteranceId) {
Runnable guiCommand = new Runnable() {
#Override
public void run() {
someButton.setEnabled(true);
}
}
};
runOnUiThread(asrStartCommand);
}
private void runOnUiThread(Runnable command){
Looper.getMainLooper().post(command);
}
}
If you have a handle to a Spinner object in an Android Activity, can you programmatically pop open the spinner options - thereby forcing the user to choose an option even though they did not click on the Spinner themselves?
To open the Spinner you just need to call it's performClick() method.
Keep in mind that you may only call this method from the UI thread. If you need to open the Spinner from a separate thread you should create a Handler in the UI thread and then, from your second thread, send a runnable object that calls performClick() to the Handler.
package com.example.SpinnerDemo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.os.Handler;
public class SpinnerDemo extends Activity {
private Handler h;
private Spinner s;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
h = new Handler();
s = (Spinner) findViewById(R.id.spinner);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this,
R.array.planets, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
// Open the Spinner...
s.performClick();
// Spawn a thread that triggers the Spinner to open after 5 seconds...
new Thread(new Runnable() {
public void run() {
// DO NOT ATTEMPT TO DIRECTLY UPDATE THE UI HERE, IT WON'T WORK!
// YOU MUST POST THE WORK TO THE UI THREAD'S HANDLER
h.postDelayed(new Runnable() {
public void run() {
// Open the Spinner...
s.performClick();
}
}, 5000);
}
}).start();
}
}
The resources used by this example can be found here.
To show the Spinner items you just need to call it's performClick() method.
Spinner spDeviceType = (Spinner) findViewById(R.id.spDeviceType);
spDeviceType.performClick();
You don't need to use 2 runnables as shown in the previous example.
This will be enough :
h.postDelayed(new Runnable() {
public void run() {
s.performClick();
}
}, 5000);
Simply use this
yourspinner.performClick();
#Override
protected void onResume() {
super.onResume();
_spinner_operations.performClick();
}
you need the call in onResume, in onCreate this not work.
You can call performClick() after the UI thread is done with its current operation(s). If you don't use post {}, you may not see the Spinner open.
findViewById<Spinner>(R.id.spinner).post {
performClick()
}