I have written the following code:
package com.shadow.handler;
import android.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class ServiceClick extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_item);
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
final long start = mStartTime;
long millis = SystemClock.uptimeMillis() - start;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
if (seconds < 10) {
mTimeLabel.setText("" + minutes + ":0" + seconds);
} else {
mTimeLabel.setText("" + minutes + ":" + seconds);
}
mHandler.postAtTime(this,
start + (((minutes * 60) + seconds + 1) * 1000));
}
};
public void startClicked(View view) {
if (mStartTime == 0L) {
mStartTime = System.currentTimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
public void stopClicked(View view) {
mHandler.removeCallbacks(mUpdateTimeTask);
}
}
I am getting the following errors:
mStartTime cannot be resolved to a variable
mHandler cannot be resolved
But I have already declared mStartTime and mHandler.
You haven't declared those variables. You need to declare them
Handler mHandler;
long mStartTime;
#Override
public void onCreate(Bundle savedInstanceState) {
Also you need to remove
import android.R;
Should be
import com.shadow.handler.R;
Also i don't see where you initialized mHandler.
Related
im working through my first app right now and i have a problem concerning an update of an Arraylist object.
This is the code:
package com.example.stopwatchmulti;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class Main2Activity extends AppCompatActivity {
//Define Variables and Arrays
String ergebnis;
String stopTime;
int anzahl;
int hours;
int minutes;
int seconds;
Chronometer chronometer;
long pauseOffset;
boolean running;
int arrayelements = anzahl - 1;
long timeElapsed;
ListView customListview;
ArrayList<UserIDs> userList;
ArrayList<String> stoppedTime;
CustomListview adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ergebnis = getIntent().getExtras().getString("Ergebnis");
anzahl = Integer.parseInt(ergebnis);
chronometer = findViewById(R.id.chronometer);
customListview = (ListView) findViewById(R.id.customListview);
userList = new ArrayList<>();
// Add Lines in favour of UserChoice in First activity
for (int i = 1; i <= anzahl; i++) {
UserIDs user = new UserIDs(String.valueOf(i), "Chronometer" + String.valueOf(i), stopTime);
userList.add(user);
}
stopTime = String.valueOf(hours)+":"+String.valueOf(minutes)+":"+String.valueOf(seconds);
// Run Custom ArrayAdapter
adapter = new CustomListview(this, R.layout.usertableobjects, userList);
customListview.setAdapter(adapter);
}
public void startChronometer(View v) {
if (!running) {
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
running = true;
new Thread(new updateStoptime()).start();
}
}
public void pauseChronometer(View v) {
if (running) {
chronometer.stop();
running = false;
}
}
public void resetChronometer(View v) {
chronometer.setBase(SystemClock.elapsedRealtime());
}
class updateStoptime implements Runnable {
#Override
public void run() {
chronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer chronometer) {
timeElapsed = SystemClock.elapsedRealtime() - chronometer.getBase();
hours = (int) (timeElapsed / 3600000);
minutes = (int) (timeElapsed - hours * 3600000 / 6000);
seconds = (int) (timeElapsed - hours * 3600000 - minutes * 60000) / 1000;
stopTime = String.valueOf(hours)+":"+String.valueOf(minutes)+":"+String.valueOf(seconds);
Log.i("Zeit:", String.valueOf(stopTime));
}
});
while(running == true){
for (int i = 1; i <= anzahl; i++) {
userList.get(arrayelements).setUserTime(stopTime);
Log.i("LoopNr:", String.valueOf(i));
}
}
}
}
}
The update of the arraylist in the while loop is the reason why the app is crashing when the user clicks the button. If I just loop through and print the number of the loop in the logs, everything is ok.
Is it too much dada? How can I fix it?
PS. Basically I just need the actual countdowntime, when the user clicks the button and then update the listview with the updated array. So if there's a better and smarter way to achieve this instead of using a while loop, i would appreciate a hint.
Thx in advance
Quick correction:
// Here anzahl is not initialized and is being referred to in the next line.
// Please initialize anzahl first;
int anzahl;
int arrayelements = anzahl - 1;
Then, change your while loop to something like this.
while(running == true){
for (int i = 1; i <= anzahl; i++) {
/* here, just call "i -1". this is basically equal to "arrayelements"
which is not properly referenced up in your code.*/
userList.get(i - 1).setUserTime(stopTime);
Log.i("LoopNr:", String.valueOf(i));
}
}
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 have set a timer and it display the time counted on the application screen.
When you tap the start button the timer is running and when you tap stop it stops, though when I'm trying to resume it, it restarts the existing time.
How can I resume the timer without refreshing/restarting the existed time?
import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class Timer extends AppCompatActivity {
TextView timerTextView;
long startTime = 0;
//runs without a timer by reposting this handler at the end of the runnable
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
int hours = minutes / 60;
seconds = seconds % 60;
timerTextView.setText(String.format("%d:%02d:%02d", hours, minutes, seconds));
timerHandler.postDelayed(this, 500);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
timerTextView = (TextView) findViewById(R.id.timerTextView);
Button b = (Button) findViewById(R.id.button);
b.setText(R.string.start);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button b = (Button) v;
if (b.getText().equals("Stop")) {
timerHandler.removeCallbacks(timerRunnable);
b.setText(R.string.resume);
} else {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
b.setText(R.string.stop);
}
}
});
}
#Override
public void onPause() {
super.onPause();
timerHandler.removeCallbacks(timerRunnable);
Button b = (Button)findViewById(R.id.button);
b.setText("start");
}
}
try this code:
long startTime = 0;
long elapsedTime ;
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button b = (Button) v;
if (b.getText().equals("Stop")) {
elapsedTime = System.currentTimeMillis() - startTime;
timerHandler.removeCallbacks(timerRunnable);
b.setText(R.string.resume);
} else {
startTime = System.currentTimeMillis() - elapsedTime;
timerHandler.postDelayed(timerRunnable, 0);
Calendar cs = Calendar.getInstance();
System.out.println("Current time => " + cs.getTime());
SimpleDateFormat df = new SimpleDateFormat("HH:mm");
String formattedDate = df.format(cs.getTime());
timerTextView.setText(formattedDate);
b.setText(R.string.stop);
}
}
});
it will calculate the elapsed time and show time after stop...
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.
So I'm trying to make a timer like a stopwatch but I'm a complete noob. I tried "combining" things from Here and Here.
The goal is to take user input for how long they want to set the timer for, then when the time is up it does stuff.
This is what I have so far:
package com.example.timer;
import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private CountDownTimer countDownTimer;
private boolean timerHasStarted = false;
public TextView text;
private final long interval = 1 * 1000;
EditText editTime1;
Button startButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTime1 = (EditText)findViewById(R.id.editTime1);
startButton = (Button)findViewById(R.id.startButton);
text = (TextView) this.findViewById(R.id.timer);
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//get the name from edittext and storing into string variable
long timeVal = Long.parseLong(editTime1.getText().toString());
countDownTimer = new MyCountDownTimer(timeVal, interval);
text.setText(text.getText() + String.valueOf(timeVal / 1000));
if (!timerHasStarted) {
countDownTimer.start();
timerHasStarted = true;
startButton.setText("STOP");
} else {
countDownTimer.cancel();
timerHasStarted = false;
startButton.setText("RESTART");
}
}
class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long timeVal, long interval) {
super(timeVal, interval);
}
#Override
public void onTick(long millisUntilFinished) {
text.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
text.setText("Times up");
}
}
});
}
#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;
}
}
Few things to note.
The Activity expects the start time to be in milliseconds. If an input value greater than 1000 is given (ex 10 seconds i.e. 10000), the app shows the count down.
The following two lines are placed incorrectly.
countDownTimer = new MyCountDownTimer(timeVal, interval);
text.setText(text.getText() + String.valueOf(timeVal / 1000));
They should be executed only when the count down is started. But in the given implementation, they are run both at start as well as stop.
As a result, a new MyCountDownTimer is created when the count down is stopped, and the countDownTimer.cancel(); is called in this new object rather than the original object. So the count down continues.
Since the setText is performed both on start and stop, the timeVal is appended to the output. That is causing "Times up0" observed.
The updated onClick method is as follows.
public void onClick(View v) {
// get the name from edittext and storing into string variable
long timeVal = Long.parseLong(editTime1.getText().toString());
if (!timerHasStarted) {
countDownTimer = new MyCountDownTimer(timeVal, interval);
text.setText(text.getText() + String.valueOf(timeVal / 1000));
countDownTimer.start();
timerHasStarted = true;
startButton.setText("STOP");
} else {
countDownTimer.cancel();
timerHasStarted = false;
startButton.setText("RESTART");
}
}
I found a way to do that.
basically I let user to input their own values.
layout : HH:MM:SS
then I get these values from layout then process like below :
EditText tv_hour = findViewById(R.id.timerHHValue);
EditText tv_minute = findViewById(R.id.timerMMValue);
EditText tv_second = findViewById(R.id.timerSSValue);
long inputTime = TimeUnit.MINUTES.toMillis(minute) + TimeUnit.HOURS.toMillis(hour) + TimeUnit.SECONDS.toMillis(second);
mCountDownTimer = new CountDownTimer(inputTime, 1000) {
public void onTick(long millisUntilFinished) {
DecimalFormat f = new DecimalFormat("00");
long hours = (millisUntilFinished / 3600000) % 24;
long minutes = (millisUntilFinished / 60000) % 60;
long second = (millisUntilFinished / 1000) % 60;
tv_hour.setText(f.format(hours)+"");
tv_minute.setText(f.format(minutes)+"");
tv_second.setText(f.format(second)+"");
}
#Override
public void onFinish() {
// timerFinish.setVisibility(View.VISIBLE);
tv_hour.setText("00");
tv_minute.setText("00");
tv_second.setText("00");
}
}.start();
}