i need some help looping a timer in android. I need it to loop 5 times and then stop at 0 on the last run/countdown, but can seems to get it to work. I know it might be a simple.
Any help would be appreciated, thanks to anyone that does help.
package com.project.secondproject;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private int countdownValue;
private TextView textfield;
private Handler handler;
private boolean Running;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view){
int countdownValue = 30;
int counter = 0;
Running = true;
textfield = (TextView)findViewById(R.id.Timer);
handler = new Handler();
Runnable runnable = new Runnable(){
#Override
public void run(){
while(Running){
try{
//This controls the interval of the timer. every 1 second
Thread.sleep(1000);}
catch(InterruptedException e){
e.printStackTrace();
}
handler.post(new Runnable(){
#Override
public void run(){
countdownValue -= 1;
textfield.setText(String.valueOf(":" + countdownValue));
if(countdownValue == 1){
Running = false;
}
}
});
}
}
};
new Thread(runnable).start();
}
public void pause(View view){
Running = false;
}
}//End of class
Hope this is what you are looking for. Try this.!
public void run()
{
while(Running){
for (int counter = 5; counter > 0; counter++)
{
System.out.println(" loop..." + counter);
try{Thread.sleep(1000);} // 1 second pause
catch(Exception e){}
}
}
Related
I'm trying to stop a timer from a thread which start the count. When i press the "START" button everything is okay, but at the moment i press the "STOP" button i get the next error:
FATAL EXCEPTION: main
Process: com.example.user.a4_1_basic_handler, PID: 20375
java.lang.IllegalStateException: Could not execute method for android:onClick
I'm new at this, i'm just trying to put in practice thread using handler. If someone can tell me how to finish the thread that will be a plus :)
package com.example.user.a4_1_basic_handler;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
//Java variables
int num =0;
boolean stopThread=false;
//Android variables
static final String S_TAG=MainActivity.class.getSimpleName();
Handler handler;
Thread counter = new Thread(new tstart());
tstart test;
// UI
TextView textView;
Button start_button;
Button stop_button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(S_TAG,"OnCreate Thread ID: "+Thread.currentThread().getId());
handler = new Handler(getApplicationContext().getMainLooper());
tstart test;
textView=(TextView) findViewById(R.id.textView);
start_button=(Button) findViewById(R.id.start_button);
stop_button=(Button) findViewById(R.id.stop_button);
}
//UI
public void OnClick_start(View view){
counter.start();
}
public void OnClick_stop(View view){
test.finish();
}
//Methods
public void timer(){
num++;
textView.setText(String.valueOf(num));
}
public void clock(){
try {Thread.sleep(1000);}
catch (InterruptedException e) {e.printStackTrace();}
}
//Thread
class tstart extends Thread{
#Override
public void run() {
while (!stopThread) {
clock();
textView.post(new Runnable() {
#Override
public void run() {
timer();
}
});
}
}
public void finish(){
stopThread=true;
}
}
}
test is not initialisd.
Thread counter = new Thread(new tstart());
What is the need of counter, inside onCreate() create object of test
test=new tstart();
And use test instead of counter
public void OnClick_start(View view){
test.start();
}
Why don't you try Standard Java timer java.util.Timer and java.util.TimerTask that works fine in Android.
I got a little problem. I think the solution is very simple but unfortunately I can't find it. I hope someone can help me
I got a while-loop who has to count up to ten and write the number into a TextView.
It still doesn't work ...
Thanks for your help!
Here is the code:
package de.androidnewcomer.animation;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import static android.R.attr.button;
import static de.androidnewcomer.animation.R.id.textView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView ball=(ImageView)findViewById(R.id.ball);
Button button=(Button)findViewById(R.id.button);
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
count();
break;
}
}
private void count() {
TextView textView=(TextView)findViewById(R.id.textView);
int i;
i=1;
while(i<10) {
i++;
textView.setText(i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Using setText() with an integer value is for setting a string resource reference. To set the text itself, you have to provide a string: Use setText("" + i); and it should work.
The textView.setText(..) needs a string object, but you use a int. You have to convert your int into a string with the following possible options:
You can use String.valueOf(i): textView.setText(String.valueOf(i));
You can use Integer.toString(i): textView.setText(Integer.toString(i));
You can use the empty string literal: textView.setText("" + i);
I prefer the last option. With your code, it should looks like the following code:
private void count() {
TextView textView=(TextView)findViewById(R.id.textView);
int i;
i=1;
while(i<10) {
i++;
textView.setText("" + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You can use a for loop instead of a while loop, like the following code:
private void count() {
TextView textView=(TextView)findViewById(R.id.textView);
for(int i = 1; i < 11; i++){ // From 1 to 10
textView.setText("" + i);
Thread.sleep(200);
}
}
Use a CountDown because you are blocking the main thread
CountDownTimer countDownTimer = new CountDownTimer(2000 /*amount*/, 200/*step*/) {
public void onTick(long millisUntilFinished) {
textView.setText("what ever you want");
}
public void onFinish() {
textView.setText("Done");
}
};
countDownTimer.start();
In the code below, I maintain the "isFound" boolean variable to determine whether a thread should run or not. However, when I set the "isFound" to true. My threads will run exactly one more time. In other words, they will not stop properly which also causes the UI to not update the Textview properly. I guess this is due to some synchronized problems but I am not sure how to deal with it and I have tried using a synchronized block but it still does not work.
import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private ProgressBar progressBar;
private TextView message;
private TextView magicNumDisplay;
private boolean isFound = false;
private NotificationManager notificationManager;
private Notification notifyDetail;
private final Handler handler = new Handler(){
public void handleMessage(Message msg) {
if (isMagic(msg.what)) {
isFound = true;
progressBar.setVisibility(View.INVISIBLE);
magicNumDisplay.setText("The magic number is " + msg.what);
handler.removeMessages(0);
message.setText("A magic number s found");
Intent intent = new Intent("MAGIC_NUMBER");
intent.putExtra("THREAD_NAME", msg.obj.toString());
intent.putExtra("MAGIC_NUMBER", String.valueOf(msg.what));
sendBroadcast(intent);
} else {
message.setText("Finding a magic number...");
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
message = (TextView) findViewById(R.id.message);
progressBar = (ProgressBar) findViewById(R.id.progressbar);
magicNumDisplay = (TextView) findViewById(R.id.magic_num_display);
progressBar.setVisibility(View.VISIBLE);
IntentFilter filter = new IntentFilter("MAGIC_NUMBER");
BroadcastReceiver receiver = new MagicNumberReceiver();
registerReceiver(receiver, filter);
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
public void onStart(){
super.onStart();
Thread firstThread = new Thread(backgroundTask, "First");
Thread secondThread = new Thread(backgroundTask, "Second");
firstThread.start();
secondThread.start();
}
public boolean isMagic(int num) {
return (num % 7 == 0 && isLastDigitEqualTwo(num));
}
public boolean isLastDigitEqualTwo(int num) {
String numString = String.valueOf(num);
return Integer.parseInt(numString.substring(numString.length() - 1))==2;
}
Runnable backgroundTask = new Runnable() {
#Override
public void run() {
try {
while (!isFound) {
Thread.sleep(1000);
int number = (int) (Math.random() * 9999);
Message msg = handler.obtainMessage(number, Thread.currentThread().getName());
handler.sendMessage(msg);
Log.e(Thread.currentThread().getName(), "The number is :" + number);
}
} catch(InterruptedException e){
Log.e("Exception", e.getMessage());
}
}
};
public class MagicNumberReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context localContext, Intent callerIntent) {
String threadName = callerIntent.getStringExtra("THREAD_NAME");
String magicNum = callerIntent.getStringExtra("MAGIC_NUMBER");
Log.e("Magic", "Thread name:"+threadName+" Magic Number:"+magicNum);
int MAGIC_NUMBER_NOTIFICATION_ID=200;
notifyDetail = new Notification.Builder(getApplicationContext())
.setContentTitle("Magic Number")
.setContentText("Thread Name: " + threadName + ". Magic Number: " + magicNum+".")
.setSmallIcon(R.drawable.droid)
.setVibrate(new long[] {1000, 1000, 1000, 1000})
.setLights(Integer.MAX_VALUE, 500, 500)
.build();
notificationManager.notify(MAGIC_NUMBER_NOTIFICATION_ID,notifyDetail);
}
}
}
I have following problem :
My Android App is communicating via WLAN with a raspberry pi 3.
My Android App has a start button and a clear button and 2 textviews.
When the start button is pressed, it creates a sound and after that it sends a string a to the pi and the app starts a time counter, that is displayed on one of the textviews.
When the light barrier(connected with Pi) has been crossed, the pi sends a string back(end time) and this string gets received by the AsyncTask in my CLIENT Class and displayed on the second textview. But the counter is still running and that's the problem. In the moment the end time is received , i want the counter to be stopped. I need a a way for my code that these two processes communicate with each other just to stop the counter. When i press the clear button i manage it to stop the counter. My last try, that is included in the code beneath, was to set a variable to 1 in a extra class when the end time is received (in the section "on post execute" i try to set the value to 1). And a fixed timer looks up for that value "all the time", and if this value is 1 the Time counter shall be stopped. I tried this and several things but never have came to a solution. And i tried to debug the last try but it did not work. So please if you have an idea how to tell the counter to stop
The Class "Client" includes the implementation of the AsyncTask, that receives the end time and post it to the textview of the app.
The MainActivity Class includes the process for the counter and the timer that asks for the value in the counter class.
The Counter Class is there to set the variable (my try of a shared resource)
Main Activity
package com.client.androidsrc.client;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.os.Handler;
import android.os.SystemClock;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends Activity {
TextView timetext;
TextView response;
Button buttonConnect, buttonClear;
public long startTime = 0L;
public Handler customHandler = new Handler();
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//ImageView imageView = (ImageView) findViewById(R.id.imageView3);
//imageView.setImageResource(R.drawable.run);
buttonConnect = (Button) findViewById(R.id.connectButton);
buttonClear = (Button) findViewById(R.id.clearButton);
response = (TextView) findViewById(R.id.End_time);
timetext = (TextView) findViewById(R.id.Time);
timetext.setText("00:00:00");
final MediaPlayer mp = MediaPlayer.create(this, R.raw.go);
buttonConnect.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
mp.start();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
client myClient = new client(response);
myClient.execute();
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
//client_send send = new client_send();
//send.execute();
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
counter controller = new counter();
if(controller.stopper==1)
{
customHandler.removeCallbacks(updateTimerThread);
startTime = 0L;
timeInMilliseconds = 0L;
updatedTime = 0L;
timetext.setText("");
}
}
}, 0, 50);
}
});
buttonClear.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//timeSwapBuff += timeInMilliseconds;
customHandler.removeCallbacks(updateTimerThread);
startTime = 0L;
timeInMilliseconds = 0L;
updatedTime = 0L;
timetext.setText("00:00:00");
}
});
}
public Runnable updateTimerThread = new Runnable() {
public void run() {
timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
updatedTime = timeSwapBuff + timeInMilliseconds;
int secs = (int) (updatedTime / 1000);
int mins = secs / 60;
secs = secs % 60;
int milliseconds = (int) (updatedTime % 1000);
timetext.setText("" + mins + ":"
+ String.format("%02d", secs) + ":"
+ String.format("%03d", milliseconds));
customHandler.postDelayed(this, 0);
}
};
}
Client Class
package com.client.androidsrc.client;
import android.content.Context;
import android.os.AsyncTask;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;
import android.widget.TextView;
/**
* Created by Florian on 26.11.2016.
*/
public class client extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response ;
TextView textResponse;
client( TextView textResponse) {
dstAddress = "192.168.42.1";
dstPort = 51717;
this.textResponse = textResponse;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(
1024);
byte[] buffer = new byte[1024];
int bytesRead;
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.print("3");
//Log.d("Test","5 second test done");
InputStream inputStream = socket.getInputStream();
/*
* notice: inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
response = byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//response = "IOException: " + e.toString();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
counter mycounter = new counter();
mycounter.stop();
super.onPostExecute(result);
}
}
Counter Class
package com.client.androidsrc.client;
public class counter {
public int stopper = 0;
public void stop () {
stopper = 1;
}
public void setback() {
stopper = 0;
}
}
I've been having this issue for about a month now and I made a different question about it here: https://stackoverflow.com/questions/38005624/activity-stops-after-certain-time?noredirect=1#comment63454873_38005624
The issue appears to be a problem with the UI thread. After a seemingly random time of running, the UI thread appears to stop doing work. Any 'Runnable' objects passed to it with '.post()' or 'runOnUIThead()' do not get run. Even a simple log message. onClickListener objects also do not fire when the issue occurs. I've had runs where it starts happening within 2 seconds of starting, I've had runs where I make it through the entire game with no issue; all on the same code.
Here is my code if you need it:
The Activity:
package edu.rit.jacob.timeturner;
import android.app.ActivityManager;
import android.app.Application;
import android.app.Dialog;
import android.content.Intent;
import android.os.Looper;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.support.annotation.StringRes;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
public class UniverseActivity extends AppCompatActivity {
public static final String TAG = UniverseActivity.class.getSimpleName();
private UniverseThread thread;
public UniverseThread getThread(){ return thread; }
public static int SECTORS_HEIGHT = 3;
public static int SECTORS_WIDTH = 3;
private Galaxy player;
public Galaxy getPlayer() {
return player;
}
//components:
private UniverseView surfaceView;
private ImageView playerSprite;
private ImageView otherSprite;
private TextView testText;
private SeekBar speedBar;
private ProgressBar timebar;
//Pop ups
private Dialog infoPopUp;
private Dialog startScreen;
//other Galaxies
Galaxy[] galaxies = new Galaxy[SECTORS_HEIGHT * SECTORS_WIDTH];
#Override
protected void onCreate(Bundle savedInstanceState) {
//Setup Activity
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_universe);
Runnable init = new Runnable() {
#Override
public void run() {
initInfoPopUp();
initActivityComponents();
initPlayerAndSprites();
initOtherGalaxies();
initStartScreen();
}
};
runOnUiThread(init);
thread = new UniverseThread(surfaceView.getHolder(), surfaceView);
thread.setRunning(true);
thread.start();
startScreen.setTitle("The Beginning...");
startScreen.show();
Log.d(TAG, "App launched with " + ((ActivityManager)getSystemService(ACTIVITY_SERVICE)).getLargeMemoryClass() + "MB max");
}
#Override
protected void onDestroy() {
super.onDestroy();
boolean retry = true;
while(retry){
try{
thread.join();
retry = false;
}
catch (InterruptedException e){
//try again
}
}
}
private void initStartScreen(){
startScreen = new Dialog(this);
startScreen.setContentView(R.layout.new_game_start);
((TextView)startScreen.findViewById(R.id.textView4)).setText(getString(R.string.start_game_info));
startScreen.findViewById(R.id.buttonStart).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
player.setName("" + ((EditText)startScreen.findViewById(R.id.editText)).getText());
startScreen.dismiss();
}
});
}
private void initInfoPopUp(){
infoPopUp = new Dialog(this);
infoPopUp.setContentView(R.layout.info_popup);
Button infoOption1 = (Button) infoPopUp.findViewById(R.id.option1);
Button infoOption2 = (Button) infoPopUp.findViewById(R.id.option2);
infoOption1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Option 1 clicked");
//player.incrementGas(galaxies[player.getSector() - 1].getGas());
player.merge(galaxies[player.getSector() - 1], true);
galaxies[player.getSector() - 1] = null;
infoPopUp.dismiss();
}
});
infoOption2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Option 2 clicked");
//player.incrementGas(galaxies[player.getSector() - 1].getGas() / 2);
//galaxies[player.getSector() - 1].incrementGas(-galaxies[player.getSector() - 1].getGas() / 2);
player.merge(galaxies[player.getSector() - 1], false);
infoPopUp.dismiss();
}
});
}
private void initActivityComponents(){
surfaceView = (UniverseView) findViewById(R.id.surfaceView);
testText = (TextView) findViewById(R.id.testText);
speedBar = ((SeekBar)findViewById(R.id.seekBar));
timebar = ((ProgressBar)findViewById(R.id.progressBar));
}
private void initPlayerAndSprites(){
playerSprite = (ImageView) findViewById(R.id.playerGalaxy);
player = new Galaxy("Milky Way", true, new Velocity(), playerSprite, 25.0f, 1, this);
otherSprite = (ImageView) findViewById(R.id.otherGalaxy);
//Tapping on player galaxy
playerSprite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Player sprite clicked, stopping time and bringing up window...");
speedBar.setProgress(0);
infoPopUp.setTitle(player.getName());
infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.random_temp_galaxy_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.INVISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText(player.toString());
infoPopUp.show();
}
});
//Tapping on other galaxy
otherSprite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(otherSprite.getVisibility() == View.VISIBLE){
Log.d(TAG, "Other sprite clicked, stopping time and bringing up window...");
speedBar.setProgress(0);
infoPopUp.setTitle(galaxies[player.getSector() - 1].getName());
infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.random_temp_galaxy_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.INVISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText(galaxies[player.getSector() - 1].toString());
infoPopUp.show();
}
}
});
}
private void initOtherGalaxies(){
for(Galaxy g: galaxies) g = null;
int i = 0, galaxiesNum = 0;
Log.d(TAG, "Populating the universe...");
while(i < galaxies.length){
double rand = Math.random();
if(rand <= 0.25){
galaxies[i] = new Galaxy("Random galaxy", new Velocity(0,0), otherSprite, 25.0f, i + 1, (Math.random()), this);
galaxiesNum += 1;
}
i += 1;
}
Log.d(TAG, "Universe populated with " + galaxiesNum + " galaxies.");
}
public int getSpeed(){
return speedBar.getProgress();
}
public void setTimeProgress(int progress){
try {
if (timebar.getProgress() != progress) {
switch (progress) {
case 10:
//((ProgressBar) findViewById(R.id.progressBar)).getProgress()
progress += 1;
//bring up new popup
break;
case 50:
//do stuff
break;
case 100:
//do end game stuff
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
//try again
}
}
}
timebar.setProgress(progress);
}
}
catch (NullPointerException e){
Log.d(TAG, "Failed to grab progressBar");
e.printStackTrace();
}
}
public void changeBackground(){
Runnable changeBackground = new Runnable() {
#Override
public void run() {
//Set new background
Log.d(TAG, "Changing to background " + player.getSector());
//surfaceView.setBackgroundResource(R.drawable.background01 + (player.getSector() - 1));
testText.setText("Sector: " + player.getSector());
//Check for other galaxy
if(galaxies[player.getSector() - 1] != null){
otherSprite.setVisibility(View.VISIBLE);
}
else{
otherSprite.setVisibility(View.INVISIBLE);
}
synchronized (this) {
this.notify();
}
}
};
Log.d(TAG, "Passing background runnable to the UI thread");
synchronized (changeBackground){
runOnUiThread(changeBackground);
try {
changeBackground.wait();
}
catch (InterruptedException e){
e.printStackTrace();
}
}
}
public void checkForCollision(){
if(playerSprite.getX() + (playerSprite.getWidth() / 2) >= otherSprite.getX() &&
playerSprite.getX() + (playerSprite.getWidth() / 2) <= otherSprite.getX() + otherSprite.getWidth() &&
playerSprite.getY() + (playerSprite.getHeight() / 2) >= otherSprite.getY() &&
playerSprite.getY() + (playerSprite.getHeight() / 2) <= otherSprite.getY() + otherSprite.getHeight()){
if(otherSprite.getVisibility() == View.VISIBLE){
//switch (player.)
Runnable collide = new Runnable() {
#Override
public void run() {
speedBar.setProgress(0);
otherSprite.setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText("");
//infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.hubble_merger_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.VISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.VISIBLE);
infoPopUp.setTitle("Incoming!");
infoPopUp.show();
}
};
runOnUiThread(collide);
}
}
//Set gauge
Runnable setGauge = new Runnable() {
#Override
public void run() {
((GaugeView)findViewById(R.id.gaugeView)).setTargetValue(player.getGas());
}
};
runOnUiThread(setGauge);
}
}
The Thread:
package edu.rit.jacob.timeturner;
import android.content.Context;
import android.graphics.Canvas;
import android.hardware.*;
import android.hardware.SensorManager;
import android.provider.Settings;
import android.util.Log;
import android.view.SurfaceHolder;
import android.widget.ImageView;
public class UniverseThread extends Thread {
public static final String TAG = UniverseThread.class.getSimpleName();
private double time;
public double getTime(){
return time;
}
private double speed;
public double getSpeed(){
return speed;
}
private boolean running;
public void setRunning(boolean running){
this.running = running;
}
public boolean isRunning(){
return running;
}
//Reference to the UniverseActivity
private SurfaceHolder surfaceHolder;
//Reference to the UniverseView that is the background
private UniverseView universeView;
public UniverseThread(SurfaceHolder surfaceHolder, UniverseView universeView){
super();
this.surfaceHolder = surfaceHolder;
this.universeView = universeView;
running = false;
time = 0;
}
public static float x = 0, y = 0, z = 0;
#Override
public void run(){
Log.d(TAG, "Starting Game Loop");
time = 0.0;
speed = 0.0;
//SensorManager gets SENSOR_SERVICE from android
//Accesses gravity sensor
SensorManager sm = (SensorManager) this.universeView.getContext().getSystemService(Context.SENSOR_SERVICE);
sm.registerListener(new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
x = event.values[0];
y = event.values[1];
z = event.values[2];
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}, sm.getDefaultSensor(Sensor.TYPE_GRAVITY), SensorManager.SENSOR_DELAY_GAME);
//save player, velocity, and sprite
Galaxy player = ((UniverseActivity)universeView.getContext()).getPlayer();
Velocity vel = player.getVel();
ImageView sprite = player.getSprite();
boolean changeBackground;
float timesRun = 0f;
while(running){
//every 16 milliseconds (~60 Hz)
timesRun += 1;
final String testStr = "Thread has run for " + (timesRun) + " frames.";
Runnable test = new Runnable() {
#Override
public void run() {
Log.d(TAG, testStr);
}
};
if(timesRun % 60 == 0) ((UniverseActivity) universeView.getContext()).runOnUiThread(test);
//increment the time
speed = ((UniverseActivity)universeView.getContext()).getSpeed();
time += (speed / 7200.0);
((UniverseActivity)universeView.getContext()).setTimeProgress((int) time);
//update player's velocity
((UniverseActivity)universeView.getContext()).getPlayer().getVel().incrementXV(-x / 9.81f);
((UniverseActivity)universeView.getContext()).getPlayer().getVel().incrementYV(y / 9.81f);
//update player's position
//move sprite
sprite.setX((float)(sprite.getX() + (vel.getxV() * speed / 400)));
sprite.setY((float)(sprite.getY() + (vel.getyV() * speed / 400)));
changeBackground = false;
//bottom -> top
if (sprite.getY() + (sprite.getHeight() / 2) > universeView.getHeight()) {
sprite.setY(0 - (sprite.getHeight() / 2));
sprite.setX(universeView.getWidth() / 2);
player.updateSector("BOTTOM");
changeBackground = true;
}
//right -> left
if (sprite.getX() + (sprite.getWidth() / 2) > universeView.getWidth()) {
sprite.setY(universeView.getHeight() / 2);
sprite.setX(0 - (sprite.getWidth() / 2));
player.updateSector("RIGHT");
changeBackground = true;
}
//top -> bottom
if (sprite.getY() + (sprite.getHeight() / 2) < 0) {
sprite.setY(universeView.getHeight() - (sprite.getHeight() / 2));
sprite.setX(universeView.getWidth() / 2);
player.updateSector("TOP");
changeBackground = true;
}
//left -> right
if (sprite.getX() + (sprite.getWidth() / 2) < 0) {
sprite.setY(universeView.getHeight() / 2);
sprite.setX(universeView.getWidth() - (sprite.getWidth() / 2));
player.updateSector("LEFT");
changeBackground = true;
}
if(changeBackground)
{((UniverseActivity)universeView.getContext()).changeBackground();}
((UniverseActivity)universeView.getContext()).checkForCollision();
try{
this.sleep(16L);
}
catch (InterruptedException e){
e.printStackTrace();
}
}
Log.d(TAG, "Game Loop terminated");
}
}
To be clear, no exceptions or errors are being thrown during runtime. The only messages in logcat are my own and the system messages for registering a click, for example. The application does not crash and the sprite is still perfectly controllable. The main things that do not work is the changing of backgrounds, checking for a collision, and the onClickListeners.
Has anyone run into something like this before? Any help would be appreciated.
So after having narrowed the problem down to the Runnable objects I was passing to the UI thread, I took steps to minimize the amount of time I called runOnUIThread() at first it didn't seem to have any effect but eventually I stopped having this problem and that's the only thing I can contribute it to. I might eventually do some more testing to be more concrete that that was the problem and respective solution.