I'm new to using Android Studio, and am currently writing an app that makes use of sensors in the phone to control another device. I searched and haven't found much that helps me address my issue. Eventually I need to transmit the data I get from the sensors over a network, but I'm nowhere near that point yet so that's for another day.
Right now, the app can access the sensors and display it on the phone screen. Each time the on screen button is pressed it updates the readings. What I want it to do though is once I press the button once, continually update the values in real time as the phone is moved around. If the button is pressed again I'd like it to stop. Below is my current code in the main activity. What I tried to do was use an integer that I would toggle each time the button was pressed and run a do while loop on one of the values. When the do while loop is in there it won't do anything. If I take it out, it runs like it originally did updating the values each time the button is pressed. I also am displaying the value of "toggle" next to the sensor values and it is toggling when the do while loop isn't in there. I don't understand why the do while loop won't run at all. I also tried using a boolean value and toggling between true and false but I got the same result. I also realize that the way the do while loop is set up it would probably not be able to be stopped, but I would've thought it would've at least entered the loop and kept running which would've at least got me started.
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.TextView;
import android.widget.Button;
import android.view.View;
public class MainActivity extends AppCompatActivity
{
MySensorUpdateThread mySensorUpdateThread = null;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySensorUpdateThread = new MySensorUpdateThread(this);
SensorManager sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
final float[] mValuesMagnet = new float[3];
final float[] mValuesAccel = new float[3];
final float[] mValuesOrientation = new float[3];
final float[] mRotationMatrix = new float[9];
final Button btn_valider = (Button) findViewById(R.id.btn1);
final TextView txt1 = (TextView) findViewById(R.id.textView1);
final SensorEventListener mEventListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mValuesAccel, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mValuesMagnet, 0, 3);
break;
}
}
;
};
setListners(sensorManager, mEventListener);
btn_valider.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
mySensorUpdateThread.toggleThread();
if (mySensorUpdateThread.isRunning())
{
mySensorUpdateThread.start();
}
}
});
}
public void setListners(SensorManager sensorManager, SensorEventListener mEventListener)
{
sensorManager.registerListener(mEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(mEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL);
}
public class MySensorUpdateThread extends Thread
{
private boolean keepRunning = false;
private String sensorResults = "";
private MainActivity mActivity;
public MySensorUpdateThread(MainActivity activity)
{
this.mActivity = activity;
}
public void toggleThread()
{
this.keepRunning = !this.keepRunning;
}
public boolean isRunning()
{
return this.keepRunning;
}
public String getSensorResults()
{
return this.sensorResults;
}
#Override
public void run()
{
int i = 0;
int maxIterations = 100;
try{
while(this.keepRunning)
{
// This keeps the thread from going on too long in case
if(i > maxIterations)
{
this.keepRunning = false;
break;
}
// This causes the thread to rest for 50ms to
// slow things down
try
{
Thread.sleep(50);
}
catch(InterruptedException e)
{
}
SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAccel, mValuesMagnet);
SensorManager.getOrientation(mRotationMatrix, mValuesOrientation);
sensorResults = "Roll/Pitch (degrees): " + /*mValuesOrientation[0]*(180/Math.PI) + " "+ "," + " " +*/
mValuesOrientation[1] * (180 / Math.PI) + " " + "/" + " " +
mValuesOrientation[2] * (-180 / Math.PI);
// Now post the results to the UI Thread
runOnUiThread(new Runnable(){
#Override
public void run(){
txt1.setText(getSensorResults());
}
});
}
}
catch()
{
Log.e(TAG, ex.getMessage());
}
}
}
}
I found it helpful when I used handler thread for long time tasks, handler thread is androids official way for handling long running task. Here is the offical link
for more information on how to use a handler thread.
https://developer.android.com/reference/android/os/HandlerThread.html
Put your sensor reading in a background thread. This is just an example. Make modifications as may be needed!
In your Activity class you will need to setup your background thread object:
MySensorUpdateThread mySensorUpdateThread = null;
In your Activities onCreate() method initialize the background thread by adding:
mySensorUpdateThread = new MySensorUpdateThread();
In your onClick() method start and stop you background thread:
public void onClick(View view){
mySensorUpdateThread.toggleThread();
if(mySensorUpdateThread.isRunning()){
mySensorUpdateThread.start();
}
});
Now here is the code for the background thread:
public class MySensorUpdateThread extends Thread{
SensorManager sensorManager = null;
private boolean keepRunning = false;
private String sensorResults = "";
public void toggleThread(){
this.keepRunning = !this.keepRunning;
}
public void isRunning(){
return this.keepRunning;
}
public String getSensorResults(){
return this.sensorResults;
}
#Override
public void run(){
if(sensorManager == null){
sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
}
int i = 0;
int maxIterations = 100;
String mess = "";
try{
while(this.keepRunning){
mess = "Number of iterations: " + i;
Log.e(TAG, mess);
// This keeps the thread from going on too long in case
if(i > maxIterations){
this.keepRunning = false;
break;
}
// This causes your thread to rest for 500ms it might be a
// good idea to slow things down a bit -- just a suggestion
Thread.sleep(500);
// Get your sensor data here and set it to the
// local variable to be posted to the UI Thread
//this.sensorResults = sensorString;
// Now post the results to the UI Thread
runOnUiThread(new Runnable(){
#Override
public void run(){
txt1.setText(getSensorResults());
}
}
}
}
catch(){
Log.e(TAG, ex.getMessage());
}
}
}
You will probably want to stop the background thread on the Activities onPause() method and perhaps restart it on onResume().
Related
I spent a while trying to find out why my emulator keeps freezing, turned out to be because of a while loop I had introduced. After button is clicked, a random number (LoadG1) is outputted then disappears after 4 seconds. User then inputs a number, if it's equal to loadg1 they get a point and program is looped by having another loadg1 available for 4 secs before disappearing etc...
I can't have the loop unless it's its own thread apparently. I made a thread for it and then tried. The whole app freezing after button press didn't happen, but when the loadg1 was up for 4 seconds, the app shut down. It's as if the first line of loop worked, then failed after the 4 seconds was over. I received the following error:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the
original thread that created a view hierarchy can touch its views.
After querying this I saw that I need to put it in a runOnUiThread, so I did, only to encounter the same issue. Here's my code:
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.Random;
public class game1 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game1);
final Button loseStarter1;
loseStarter1 = (Button) findViewById(R.id.Starter1);
loseStarter1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loseStarter1.setVisibility(View.GONE);
final int[] score = {0};
Random generateG1 = new Random();
final int loadG1 = generateG1.nextInt(1000000)+10000;
final TextView number = (TextView) findViewById(R.id.number);
number.setText(" "+loadG1);
new CountDownTimer(18000, 1000) {
#Override
public void onTick (long millisUntilFinished) {
}
public void onFinish() {
TextView result = (TextView) findViewById(R.id.outcome);
result.setText("Score: "+ score[0]);
TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setVisibility(View.GONE);
}
}.start();
runOnUiThread(new Runnable() {
#Override
public void run() {
Runnable myRunnable = new Runnable() {
#Override
public void run() {
while (true) {
SystemClock.sleep(4000);
number.setVisibility(View.GONE);
final TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setText(" Enter the number");
final EditText input = (EditText) findViewById(R.id.enterAnswer);
input.setVisibility(View.VISIBLE);
input.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
Editable answer = input.getText();
int finalAnswer = Integer.parseInt(String.valueOf(answer));
int finalLoadG1 = Integer.parseInt(String.valueOf(loadG1));
input.setVisibility(View.GONE);
prompt.setVisibility(View.GONE);
if (finalAnswer == finalLoadG1) {
score[0]++;
}
return true;
default:
}
}
return false;
}
});
}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
});
}
});
}
}
I felt like I was so close to resolving this issue, would greatly appreciate all help given.
EDIT: I have tried an alternative solution without a loop, code here:
runOnUiThread(new Runnable() {
#Override
public void run() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
SystemClock.sleep(4000);
number.setVisibility(View.GONE);
final TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setText(" Enter the number");
final EditText input = (EditText) findViewById(R.id.enterAnswer);
input.setVisibility(View.VISIBLE);
input.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
Editable answer = input.getText();
int finalAnswer = Integer.parseInt(String.valueOf(answer));
int finalLoadG1 = Integer.parseInt(String.valueOf(loadG1));
input.setVisibility(View.GONE);
prompt.setVisibility(View.GONE);
if (finalAnswer == finalLoadG1) {
score[0]++;
}
return true;
default:
}
}
return false;
}
});
}
});
}
}, 0, 4000);
}
});
Now the random number is generated and displayed for 4 seconds, but when user input is made available the app freezes. Apparently 238 frames are skipped (I believe every four seconds this is shown), and the 'main thread' is doing too much work. NOTE: EVEN WITHOUT THE RUNONUITHREAD ENCAPSULATING MY CODE, THE SAME OUTCOME OCCURS. I TRIED BOTH WAYS WITH NO DIFFERENCE FOUND.
Would honestly appreciate anyone who can help me resolve this.
don't do while(true) with UI operations, this is why you have stuck, Even more don't use while(true) at all - this is bad practice.
if you need to run some repeat operations use timer for this, you can start/stop timer, you can start another timer, even several in one time )
Don't make UI operations in threads, make them only on UI thread.
for hard operations use async tasks - and when all hard operations done then update UI. (in async task you can update UI by publishing progress), on stackoverflow tons of samples for async tasks.
OnKeyListener - runs on non UI thread, but please read above and avoid using while(true)
update to answer:
okay if you want to run like this and dont want to have lags then do following:
create timer - no need to start it in runOnUIThread. all codes with calculations move ti async task which you will start in timer, in async task before run - stop timer to avoid run again, make all calculations in async task, on end async task - update ui and (or you can update on publish progress) and on end of async task you can start your timer again. if you need delay before next run use Handler and postDelayed
In my program, it is needed to receive user latitude and longitude as soon as GPS is Enabled... I'm using onGpsStatusChanged to constantly check GPS Status and the checking works... The only problem is that it tries to retrieve user location instantly, and it returns latitude 0.0 and longitude 0.0 cause it takes some seconds to get those informations... If I try to retrieve some seconds later using clickListener on a button it works perfectly...
Then I thought: If I could make the device wait some seconds after GPS is Enabled and only then retrieve the coordinates it would work...
But: If I use another Thread or AsyncTask (already tried both), it keeps returning 0.0 for coordinates, cause the real coordinates are cached into the Map's Main Activity Thread...
So, how to make android wait in the main Thread? I've tried 'wait(long)' and the app crashes. I'm trying to solve this for weeks and my time is running out... Some holy soul help me please
you can achieve that by using handler
int time=3000 // in milliseconds
Handler h=new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//here you can do the job
}
},time);
if you want to update the UI from the handler you will end up with an error but you can userunOnUiThread
runOnUiThread(new Runnable() {
#Override
public void run() {
//code to update the ui
}
});
good luck
i not recommend you handler,you can use Interface here.
where you get all values use pass it to your activity and use that one.
Here i have posted example just try to follow and use this way.
You can pass interval here according to your need.
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000
and one more thing you can pass fastest interval that is also help you.
Thanks
I have been creating a simple Waiter class for it. It is really easy to understand and does the job very well. I post it for those who need it. just copy Waiter class and WaitListener interface and use it like I show.
Here is the Class:
import android.os.Handler;
import android.os.Looper;
public class Waiter {
WaitListener waitListener;
int waitTime = 0;
Handler handler;
int waitStep = 1000;
int maxWaitTime = 5000;
boolean condition = false;
public Waiter(Looper looper, final int waitStep, final int maxWaitTime){
handler = new Handler(looper);
this.waitStep = waitStep;
this.maxWaitTime = maxWaitTime;
}
public void start(){
handler.post(new Runnable() {
#Override
public void run() {
waitListener.checkCondition();
if (condition) {
waitListener.onConditionSuccess();
} else {
if (waitTime <= maxWaitTime) {
waitTime += waitStep;
handler.postDelayed(this, waitStep);
} else {
waitListener.onWaitEnd();
}
}
}
});
}
public void setConditionState(boolean condition){
this.condition = condition;
}
public void setWaitListener(WaitListener waitListener){
this.waitListener = waitListener;
}
}
And here is the Interface :
public interface WaitListener {
public void checkCondition();
public void onWaitEnd();
public void onConditionSuccess();
}
You can for example use it like that for a connection check:
ConnectivityManager mConnMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
final int result = mConnMgr.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableMMS");
final Waiter waiter = new Waiter(getMainLooper(), 1000, 5000);
waiter.setWaitListener(new WaitListener() {
#Override
public void checkCondition() {
Log.i("Connection", "Checking connection...");
NetworkInfo networkInfo = mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
waiter.setConditionState(networkInfo.isConnected());
}
#Override
public void onWaitEnd() {
Log.i("Connection", "No connection for sending");
//DO
}
#Override
public void onConditionSuccess() {
Log.i("Connection", "Connection success, sending...");
//DO
}
});
waiter.start();
As the title suggests I am trying to create a Stopwatch app and am having problems adding a lap button and continue button that work. I have added the buttons to the layout.xml file but am having trouble with the java code that gets them to function.
I need to display the "stopped/paused" time when the lap button is clicked, the internal clock needs to keep running however and no longer be displayed, or the stopped/paused time needs to be shown in a new display whichever is easier to accomplish. When the lap timer is clicked subsequently it should display the current time (internal clock)
I need the continue button to then resume the paused/stopped time.
Could somebody help me with the code, I'm relatively inexperienced in java, so any help would be appreciated
here's the code of my main java file:
package com.hfad.stopwatch;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.TextView;
public class StopwatchActivity extends Activity implements View.OnClickListener {
Button Continue;
Button lapChrono;
Chronometer chrono;
long time =0;
//Number of seconds displayed on the stopwatch.
private int seconds = 0;
//Is the stopwatch running?
private boolean running;
private boolean wasRunning;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stopwatch);
Continue=(Button)findViewById(R.id.Continue_button);
lapChrono=(Button)findViewById(R.id.lap_button);
lapChrono.setOnClickListener(this);
Continue.setOnClickListener(this);
chrono=(Chronometer)findViewById(R.id.chronometer);
if (savedInstanceState != null) {
seconds = savedInstanceState.getInt("seconds");
running = savedInstanceState.getBoolean("running");
wasRunning = savedInstanceState.getBoolean("wasRunning");
}
runTimer();
}
#Override
protected void onPause() {
super.onPause();
wasRunning = running;
running = false;
}
#Override
protected void onResume() {
super.onResume();
if (wasRunning) {
running = true;
}
}
public void onClick(View arg0) {
switch (arg0.getId()){
case R.id.Continue_button:
chrono.setBase(SystemClock.elapsedRealtime()+time);
chrono.setBase(time);
break;
case R.id.lap_button:
time = chrono.getBase()+SystemClock.elapsedRealtime();
break;
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("seconds", seconds);
savedInstanceState.putBoolean("running", running);
savedInstanceState.putBoolean("wasRunning", wasRunning);
}
//Start the stopwatch running when the Start button is clicked.
public void onClickStart(View view) {
running = true;
}
//Stop the stopwatch running when the Stop button is clicked.
public void onClickStop(View view) {
running = false;
}
//Reset the stopwatch when the Reset button is clicked.
public void onClickReset(View view) {
running = false;
seconds = 0;
}
//Sets the number of seconds on the timer.
private void runTimer() {
final TextView timeView = (TextView)findViewById(R.id.time_view);
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int hours = seconds/3600;
int minutes = (seconds%3600)/60;
int secs = seconds%60;
String time = String.format("%d:%02d:%02d",
hours, minutes, secs);
timeView.setText(time);
if (running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
}
I am just having problems getting things to run smoothly as I'm not too fluent in my Java, apologies, that is why help is needed. The logic isn't quite there. The continue button doesn't function properly nor does the lap, I'm needing it to function as described above.
chrono object is not initialized and used in onClick(). Hence NPE occurs.
Try to initialise it in onCreate().
i need to check a variable for change, if the change happens i will update a textview.
so i created a new thread with a while loop for this purpose. i check the variable every 1 second, via Thread.sleep()
this thread created and started in onCreate(). so it's one time.
the problem is every time i flip my phone (from vertical to horizontal or ...) a new thread will be created.
here is my code:
public class HomeActivity extends Activity
{
private final static int LOAD_SUCCESSFULL = 1;
private final long LOCATION_THREAD_SLEEP = 1000;
private boolean flag = false;
static TextView lat;
static TextView lon;
static Location currentLocation = null;
Thread locationThread;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.new_home2);
this.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.new_home_titlebar);
lat = (TextView)findViewById(R.id.t2rt3);
lon = (TextView)findViewById(R.id.t2rt4);
/* FindLocation class is a helper class that find location via simcard or gps in separate thread,
same problem happen with this thread also, it create multiple thread, for ease of work i
commented this part.
*/
//FindLocation fn = new FindLocation(this);
locationThread = new Thread(null, loadLocation, "loadLocationHomePage");
locationUpdater();
}
private static Handler locationUpdateHandler = new Handler()
{
public void handleMessage(Message msg)
{
switch(msg.what)
{
case LOAD_SUCCESSFULL:
lat.setText(Double.toString(currentLocation.getLatitude()));
lon.setText(Double.toString(currentLocation.getLongitude()));
//stopThread();
break;
}
}
};
private Runnable loadLocation = new Runnable()
{
public void run()
{
//boolean flag = false;
while(!flag)
{
if(Data.currLocation != null)
{
currentLocation = new Location(Data.currLocation);
Message msg = locationUpdateHandler.obtainMessage(LOAD_SUCCESSFULL);
locationUpdateHandler.sendMessage(msg);
//return;
flag = true;
//return;
}
else
{
try
{
Thread.sleep(LOCATION_THREAD_SLEEP);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
public void locationUpdater()
{
//Thread locationThread = new Thread(null, loadLocation, "loadLocationHomePage");
locationThread.start();
}
so how i can solve this?
Actually the problem is that EveryTime you flip the phone a new instance of Activity is created and because of this you on every rotation you get a call on onCreate() where you are blindly creating a new Thread and Starting the new Thread.
This is the default behavior of every Activity but we can change this re-creation of Activity by stating an attribute in AndroidManifest file for the Activity
<activity
android:name="yourPackage.ActivityName"
android:configChanges="keyboardHidden|orientation|screenSize"
</activity>
This will prevent from creation of Activity on orientation change.
You will also get these orientation event if you override
#Override
public void onConfigurationChanged(Configuration newConfig) {}
Hope this will solve this problem without implementing such a complex logic which may broke in some other uses case.
I think you aren't perhaps going about this in the most efficient way possible.
But if your question is simply, how do i prevent multiple worker threads from being spawned, you should look into a UIless fragment.
http://www.vogella.com/articles/AndroidFragments/article.html#headlessfragments1
i don't know why android doing this. if i putted my code in onResume(), then this behavior make sence but in my case, i don't know.
anyway i found a dirty solution. the idea is finding list of all thread and search them for mine, if it existed prevent to create another.
public boolean checkThreadExist()
{
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
for(int i = 0; i < threadArray.length ; i++)
{
if(threadArray[i].getName().equalsIgnoreCase("loadLocationHomePage"))
return true;
}
return false;
}
updated onCreate() :
if(checkThreadExist())
{
}
else
{
locationThread = new Thread(null, loadLocation, "loadLocationHomePage");
locationUpdater();
}
I'm trying perform some steps inside a function on Android. I would like to tell to user what is happen in a specific moment without exit of my function. something like it:
public boolean updateServiceList() {
LinearLayout start = (LinearLayout) findViewById(R.id.start);
LinearLayout major = (LinearLayout) findViewById(R.id.major);
TextView messenger = (TextView) findViewById(R.id.messenger);
Integer i = 0;
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isOnline = cm.getActiveNetworkInfo().isConnectedOrConnecting();
if(isOnline==false) {
Button exit = (Button) findViewById(R.id.exit_btn);
ProgressBar pg = (ProgressBar) findViewById(R.id.progress);
exit.setText("OK");
exit.setVisibility(View.VISIBLE);
exit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
gMain.this.finish();
}
});
pg.setVisibility(View.GONE);
messenger.setText(R.string.nointernet);
while(isOnline==false) {
i++;
messenger.setText(messenger.getText()+"Try: "+ i.toString);
boolean isOnline = cm.getActiveNetworkInfo().isConnectedOrConnecting();
}
return false;
} else {
isOnline = cm.getActiveNetworkInfo().isConnected();
while (isOnline==false || 1==1) {
isOnline = cm.getActiveNetworkInfo().isConnected();
}
}
return true;
}
My problem is in "while(isOnline)" where I can't see the update messages. I tried invalidate() and postInvalidate() there but no results. Any ideas?
EDIT:
I found the solution! There it is:
How to refresh a TextView while looping in Android?
The Rackers's answer:
public class myClass extends Activity{
private Handler mHandler;
private TextView text;
private int i;
#Override
public void onCreate(Bundle savedInstanceState) {
text = (TextView) findViewById(R.id.textView01);
i = 0;
mHandler = new Handler();
mHandler.post(mUpdate);
}
private Runnable mUpdate = new Runnable() {
public void run() {
text.setText("My number: " + i);
i++;
mHandler.postDelayed(this, 1000);
}
};}
So, at my case I just call the others steps if the current is solved. If not, I just post the step again...
Your approach will not work.
When you call messenger.setText(), you think the screen is supposed to update right then. You are mistaken.
What really happens when you call messenger.setText() is that a message goes on a message queue, to be processed by the main application thread. That's the same thread you're tying up with your while() loop. While you are in that while() loop, your entire UI is frozen: no clicks, no updates, nothing.
I suggest that you get rid of the while() loop and move along with the rest of your app.