public void startGameButtonClicked(View view) {
final TextView shadow = (TextView) findViewById(R.id.main_menu_start_game_button_shadow);
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.main_menu);
shadow.startAnimation(animation);
/** Ugly prototype pausing */
final long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < 600) {
Log.i("test", Boolean.toString(animation.hasEnded()));
}
final Intent intent = new Intent();
intent.putExtra(EXTRA_BUTTON_ID, START_GAME_BUTTON);
setResult(RESULT_OK, intent);
finish();
}
My animation has duration = 400, how can i pause everything except animation after calling shadow.startAnimation(animation); ?
I asking becouse, as you can see - animation is set for button click action, which kills current activity, so animation isnt shown completely.
You must define "pause everything" to get an answer for it.
What I'll propose is to implement AnimationListener in your Activity, and point it to the Animation. Then in onAnimationEnd() simply call finish().
Related
There are a lot of answers on "Clicking the back button twice to exit an activity" and similar things but what I am trying to do with my project is that I want to do different things for single and double click of back button
For example in my case I want to go to Home screen / Main activity of my app if the back button is pressed once and simultaneously show a toast " Press Back Again To Exit " and if the user do that the app does just that .
I am really struggling to write a code for this
I have tried this but it doesn't work as intended , with this even on double press the app doesnt exit .
Any help is appreciated .
My code
enter code here
private static final int TIME_INTERVAL = 2000;
private long mBackPressed;
public void onBackPressed() {
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
super.onBackPressed();
return;
}
else {
Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
mBackPressed = System.currentTimeMillis();
You are on the right track, however its because you are setting mBackPressed = System.currentTimeMillis(); every time the back button is pressed, so it will never pass the first if statement you have. It seems also as if you want to track how many times they've clicked the back button.
Try this,
private static final int TIME_INTERVAL = 2000;
private long mBackPressed = -1;
private int clicks = 0;
public void onBackPressed() {
if (mBackPressed == -1) //checks if the time hasnt been set yet
mBackPressed = System.currentTimeMillis();
clicks++; //or you can put this in the if statement below
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
super.onBackPressed();
return;
} else {
Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
mBackPressed = -1; //resets the time the click was made
clicks = 0; //resets the clicks
}
}
this method might be a simple solution :
#Override
public void onBackPressed() {
private final static int TIME_INTERVAL = 500;
long backPressed = 0L;
if ((System.currentTimeMillis() - backPressed < TIME_INTERVAL))
System.exit(0); // do what you want on double click
else {
backPressed = System.currentTimeMillis();
getSnackbar(R.string.double_back_press_message,Snackbar.LENGTH_SHORT).show();
super.onBackPressed();
}
}
I am trying to make one of the views in android widget visible for a second, but so far no success. Can someone point me in the right direction, please?
I've tried to do it with animation, timer but so far I got the nearest with runnable. Well, kind of as I get System.out.println("run test") executed but views are not updated.
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (MinutesClicked.equals(intent.getAction())){
//your onClick action is here
///////////////////////////////////////////////////////////
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final RemoteViews views;
ComponentName appWidget;
views = new RemoteViews(context.getPackageName(), R.layout.nixie_clock);
appWidget = new ComponentName(context, NixieClock.class);
final Runnable r = new Runnable() {
public void run() {
views.setViewVisibility(R.id.textDateDay, VISIBLE);
System.out.println("run test");
}
};
handler.postDelayed(r, 1000);
/////////////////////////////////////////////////////////
appWidgetManager.updateAppWidget(appWidget, views);
}
}
So far I am getting System.out.println("run test") printed but expected views are not made VISIBLE. I can make the view visible after a click but I cannot make it appear only for a second and disappear. Thank you in advance for any help.
You are updating the RemoteViews, but you are not sending the updated RemoteViews anywhere. You need to call updateAppWidget() again after updating the RemoteViews.
Note that your process might be terminated before the one-second delay elapses, in which case your view will not become visible.
The purpose of the service is to keep track of time since a button was pressed. If the menuactivity is showing, it updates some values on the menuactivity every minute using a timer, otherwise, it just updates itself.
It seems to work fine when the application is open or closed, but when the phone is off it slows down to less than half of what it should be (only showing like 10 minutes have passed after 21 real minutes have passed).
int startTime; //time at which the button is pressed
int time; //the current time, relative to startTime
#Override
public int onStartCommand(Intent intent, int flags, int startId){
startTime = (int)(System.nanoTime()/1000000000.0);
UpdateTimeTask updateTimeTask = new UpdateTimeTask();
timer = new Timer();
timer.schedule(updateTimeTask, 0, UPDATE_PERIOD); //update period is 60,000 (60 seconds)
return START_STICKY;
}
public class UpdateTimeTask extends TimerTask {
public void run() {
updateMenu();
}
}
public void updateMenu(){
time = (int) Math.round((System.nanoTime() / 1000000000.0) - startTime);
if(serviceCallbacks != null){ //it wont be null if its on menuactivity
serviceCallbacks.updateTimeElapsed(time/3600, time/60 - (time/3600) * 60);
}
}
If I have my phone off for a while and then go back in to menuactivity, it doesn't "fix itself" after a few cycles. I thought onStartCommand might be called more than once, but the only time the service can possibly be started is when the button is pressed.
but the only time the service can possibly be started is when the
button is pressed
That is not true. When your app go into the background (is no longer visible) it becomes a candidate to be killed if the system needs memory for other higher ranked apps. Also, the user can kill your app by swiping it from the task list. Because the service returns START_STICKY from onStartCommand(), the system will restart the service after some period of time, calling onStartCommand() with a null intent. This behavior makes a service unsuitable as the home for a data item you want to retain, such as startTime.
An alternative is to persist the value in SharedPreferences. A service is not needed and the periodic update processing can be done in your activity using the postDelayed() method of any view.
This sample activity outlines the basic logic:
public class ButtonActivity extends Activity {
private static final String TIME_KEY = "time";
private static final long PERIOD = 60*1000; // 60 seconds
private SharedPreferences mPrefs;
private Button mButton;
private TextView mTimeView;
private Runnable mDisplayTask = new Runnable() {
#Override
public void run() {
// show the time elapsed since button press in milliseconds
long elapsed = System.currentTimeMillis() - mPrefs.getLong(TIME_KEY, 0);
mTimeView.setText(""+elapsed);
// schedule next display update
mTimeView.postDelayed(mDisplayTask, PERIOD);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPrefs = getPreferences(MODE_PRIVATE);
// clear the button press time
setPressTime(0);
setContentView(R.layout.activity_demo);
mButton = (Button)findViewById(R.id.button);
mTimeView = (TextView)findViewById(R.id.time);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// save the button press time
setPressTime(System.currentTimeMillis());
// start the display updates
mDisplayTask.run();
}
});
}
#Override
protected void onPause() {
super.onPause();
// activity no longer visible; stop the updates
mTimeView.removeCallbacks(mDisplayTask);
}
#Override
protected void onResume() {
super.onResume();
// activity is visible
// if the button has been pressed, start the display updates
if (mPrefs.getLong(TIME_KEY, 0) > 0) {
mDisplayTask.run();
}
}
private void setPressTime(long time) {
// persist the button press time
SharedPreferences.Editor ed = mPrefs.edit();
ed.putLong(TIME_KEY, time);
ed.commit();
}
}
The accepted answer is correct, but only solved part of the problem. The other problem was that I was using System.nanoTime() instead of .currentTimeMillis(); .nanoTime() stops when the screen is off. Putting this here for possible future googlers.
I have a seekbar in my fragment that I use to show the progress of a MediaPlayertrack that is playing. Everything works as expected until I change orientation of the device. I save my fragment instance and load it back, and all of the other views are repopulated as they should be, and the music keeps right on playing as it should, but the seekbar goes right to the max, as if the track has reached it's max duration. The runnable that is updating the seekbar based on the mediaplayer's position keeps running after the orientation change as well, and logging the currentPos value in the runnable shows that it stays in sync with the mMediaPlayer.getCurrentPosition() as it should, even after the orientation change...So basically, it continues to feed the correct position to the seekbar; the seekbar just isn't updating after the orientation change. It makes me wonder if the seekbar instance stays the same after the change. If it doesn't stay the same instance, I can't figure out why or how to fix it.
The onCLick method of my play button calls the following to start the track and hook up the seekbar to it:
private void startPlayer(String url){
try {
mMediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
playerState = PlayerState.PLAYING;
setButtonsForPlayerState();
setSeekBarValues();
mHandler = new Handler();
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (mMediaPlayer != null ) {
int currentPos = mMediaPlayer.getCurrentPosition();
Log.e(LOG_TAG, "Current pos is " + currentPos);
seekBar.setProgress(currentPos);
if (currentPos<10000){
seekBarStartTime.setText("0:0" + currentPos / 1000);
}else{
seekBarStartTime.setText("0:" + currentPos / 1000);
}
}
if (mMediaPlayer.isPlaying()){
mHandler.postDelayed(this, 50);
}
}
}
);
}
});
}
and here is the setSeekBarValues() method that is called in the above method:
private void setSeekBarValues() {
seekBar.setMax(mMediaPlayer.getDuration());
seekBarFinishTime.setText("0:" + seekBar.getMax()/1000);
seekBar.setProgress(0);
}
seekBarStartTime and seekBarFinishTime are just TextViews that show the current position and end time of the track, respectivily.
Since all of my other views, streaming music, etc. seems to be working as it should on the re-creation of Activity and Fragment, I don't think it's an issue with saving instance state, but if you want me to post that code as well please let me know.
Any ideas are appreciated.
my class MainActivity starts the Activity "GameActivity" by user interaction (button). My class GameView is the view for my class GameActivity and has an implementation of the Runnable interface. Inside I've implemented a Handler as timer, that runs the trigger() method continuously. When gameIsOver == true the game stops and starts the GameOverActivity. Inside the GameOverActivity I've added a Button to commit the score. If you press the Button you get back to the MainView and you can start a new game.
Now to the problem: After I've played the game the GameOverActivity gets started, I commit the score and start a new Game or I end the Game and exit (not kill) the app.
In both ways, sometimes the GameOverActivity starts again and shows me that the Game is over. How could that be? Where is it called from? I guess the timer or the Runnable wasn't stopped correctly, but I really don't know what to do to prevent that problem...
PS: If the GameOverActivity gets started during the game, the game doesn't really end. If I press the back button on my phone, I'm just back in game.
GameView.java
private Handler timerHandler;
private boolean gameIsOver;
private long triggerTime, counter;
public void init() {
gameIsOver = false;
triggerTime = 1000;
counter = 0;
timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
if (gameIsOver) {
return;
}
long millis = System.currentTimeMillis() - startTime;
invalidate();
if (millis > (triggerTime * counter)) {
counter++;
GameView.this.trigger();
}
timerHandler.postDelayed(this, 250);
}
};
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 250);
}
inside the trigger() method:
if (gameIsOver) {
timerHandler.removeCallbacks(timerRunnable);
invalidate();
Intent intent = new Intent(this.context, GameOverActivity.class);
intent.putExtra("EXTRA_SCORE", score);
// some more extras...
((Activity) this.context).startActivity(intent);
((Activity) this.context).finish();
}
EDIT:
GameActivity.java
public class GameActivity extends Activity {
private GameView game;
private int level;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_game);
Intent intent = getIntent();
level = intent.getExtras().getInt("EXTRA_LEVEL");
game = (GameView) findViewById(R.id.game);
game.setLevel(level);
}
}