Pause and Resume timer made using handlers - android

Here is my code for an activity. In this I am printing the time elapsed on a text view. I want to put onPause and onResume method in this. It should work such that the time is paused while app is in background . And when again brought to forefront, should timer start from where it paused. I tried it using this code but the time is not paused. It continues to run in background. Can anybody help to find workaround for this.
package com.example.test;
import android.support.v7.app.ActionBarActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView tt1;
private Handler customHandler = new Handler();
long timeInMilliseconds = 0L,timeToGo=0L,startTime=0L;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tt1=(TextView) findViewById(R.id.textView1);
startTime=System.currentTimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public Runnable updateTimerThread=new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
long timeNow = System.currentTimeMillis();
timeToGo = 30 - (timeNow - startTime) / 1000;
tt1=(TextView) findViewById(R.id.textView1);
tt1.setText(timeToGo+"");
if(timeToGo<0L){
Intent intent=new Intent(MainActivity.this,Game.class);
finish();
startActivity(intent);
}
else
customHandler.postDelayed(this, 0);
}
};
#Override
public void onPause() {
super.onPause();
customHandler.removeCallbacksAndMessages(null);
}
#Override
public void onResume() {
super.onResume(); // Always call the superclass method first
customHandler.postDelayed(updateTimerThread, 0);
}
}

You need to update your startTime in onResume cause it hasn't changed...
#Override
public void onResume() {
startTime = System.currenTimeMillis() - timeToGo * 1000;
...
}
Or just use a Chronometer class http://developer.android.com/reference/android/widget/Chronometer.html

#Override
protected void onPause() {
customHandler.removeCallbacks(updateTimerThread);
super.onPause(); }

Related

App opens anyways even though it was closed previously

I am working on an app and while testing on my phone a noticed something weird: if I close the app while the splash screen is running, when the time of the before mention activity is over, the app opens again, even if I am in another app. Why does this happen?
package com.example.arlet.storemaps;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import java.util.Timer;
import java.util.TimerTask;
public class SplashScreenActivity extends AppCompatActivity {
//duration of splash screen in miliseconds
long delay = 6000;
private Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash_screen);
Timer RunSplash = new Timer();
TimerTask ShowSplash = new TimerTask() {
#Override
public void run() {
//finishing splash screen
finish();
//starting main activity
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
}
};
RunSplash.schedule(ShowSplash, delay);
}
#Override
protected void onDestroy(){
timer.cancel();
timer.purge();
super.onDestroy();
}
}
Here's the code updated #Badran
Override the onDestroy Method in SplashActivity:
#Override
protected void onDestroy() {
//remove the handler or thread or etc... that is opening the another activity
//call timer.cancel()
//call timer.purge ()
super.onDestroy();
}
So Your code will be now :
package com.example.arlet.storemaps;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import java.util.Timer;
import java.util.TimerTask;
public class SplashScreenActivity extends AppCompatActivity {
//duration of splash screen in miliseconds
long delay = 6000;
private Timer RunSplash;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash_screen);
RunSplash = new Timer();
TimerTask ShowSplash = new TimerTask() {
#Override
public void run() {
//finishing splash screen
finish();
//starting main activity
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
}
};
RunSplash.schedule(ShowSplash, delay);
}
#Override
protected void onDestroy(){
if(RunSplash != null){
RunSplash.cancel();
RunSplash.purge();
}
super.onDestroy();
}
#Override
protected void onPause() {
if(RunSplash != null){
RunSplash.cancel();
RunSplash.purge();
}
super.onPause();
}
}

Android: Stopwatch (Timer) in background Service

I want to make an android application that have punch in and punch out functionality. Scenario is when the user entered in an application it enters its task and press punch in button, When punch in button is press current date and time is saved in a local database and timer is running on background even i close an application but issue is it cannot run in background when i close an application and starts again timer starts from beginning.
How to figure out that my service is running and get that data?
MainActivity.java
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button startButton;
private Button pauseButton;
private TextView timerValue;
Intent intent;
long timeSwapBuff = 0L;
long updatedTime = 0L;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timerValue = (TextView) findViewById(R.id.timerValue);
startButton = (Button) findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(MyService.BROADCAST_ACTION));
}
});
pauseButton = (Button) findViewById(R.id.pauseButton);
pauseButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
unregisterReceiver(broadcastReceiver);
stopService(intent);
}
});
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
updateUI(intent);
}
};
private void updateUI(Intent intent) {
int time = intent.getIntExtra("time", 0);
Log.d("Hello", "Time " + time);
int mins = time / 60;
int secs = time % 60;
timerValue.setText("" + mins + ":" + String.format("%02d", secs));
}
#Override
protected void onStop() {
super.onStop();
intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(MyService.BROADCAST_ACTION));
}
}
MyService.java
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.widget.Toast;
public class MyService extends Service
{
private Intent intent;
public static final String BROADCAST_ACTION = "com.example.wajid.service";
private Handler handler = new Handler();
private long initial_time;
long timeInMilliseconds = 0L;
#Override
public void onCreate() {
super.onCreate();
initial_time = SystemClock.uptimeMillis();
intent = new Intent(BROADCAST_ACTION);
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 1000); // 1 seconds
}
};
private void DisplayLoggingInfo() {
timeInMilliseconds = SystemClock.uptimeMillis() - initial_time;
int timer = (int) timeInMilliseconds / 1000;
intent.putExtra("time", timer);
sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendUpdatesToUI);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Why do you want to run a timer? Instead, simply save the check-in time in shared preferences. On check-out, the two can be compared and the relevant time calculated.
If you are worried that the user might try to manipulate the local device clock, then instead of getting the local time, you can use network time.

Unable to call new intent using Handler

I am new to android. I have used handler to run timer in my code. I was trying to make a timer which calls a new intent when time is less than zero or it is negative. This program is giving Runtime errors. I tried with 0L in if condition. But program doesnt work. If i use 0 instead of 0L in if condition then the value timeToGo continue to decrease in negative. There is no error in Game.java as it has default android page. i think there is a different way to call intent in handler. Please help to solve this problem. Thank you
The activity_main file is as follows
package com.example.test;
import android.support.v7.app.ActionBarActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView tt1;
private Handler customHandler = new Handler();
long timeInMilliseconds = 0L,timeToGo=0L,startTime=0L;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tt1=(TextView) findViewById(R.id.textView1);
startTime=System.currentTimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public Runnable updateTimerThread=new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
long timeNow = System.currentTimeMillis();
timeToGo = 30 - (timeNow - startTime) / 1000;
tt1=(TextView) findViewById(R.id.textView1);
tt1.setText(timeToGo+"");
if(timeToGo<0L){
Intent intent=new Intent(MainActivity.this,Game.class);
finish();
startActivity(intent);
}
customHandler.postDelayed(this, 0);
}
};
}
To do that, you have to call startActivity() on the application's main thread. And not from the background thread. To do so change your handler:
private Handler customHandler = new Handler(Looper.getMainLooper());

Main Activity not opening

My app seems to start up properly, with the splash screen and stuff. But when it sleeps for 6 secs and when it supposed to get into the main activity the app crashes any help please?
Here is me code (android.intent.action1.MAINACTIVIVTY, the "action" was purposely changed to "action1")
package com.hellhogone.multitools;
import com.hellhogone.multitools.R;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Window;
import android.view.WindowManager;
public class Splash extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.splash);
MediaPlayer yo = MediaPlayer.create(Splash.this, R.raw.smusic);
yo.start();
Thread timer = new Thread(){
public void run(){
try{
sleep(6000);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
Intent h1 = new Intent("android.intent.action1.MAINACTIVITY");
startActivity(h1);
}
}
};
timer.start();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
}
You cannot start an activity from another thread than the UI thread. To avoid this problem you can use runOnUiThread() :
}finally{
runOnUiThread(new Runnable() {
public void run() {
Intent h1 = new Intent("android.intent.action1.MAINACTIVITY");
startActivity(h1);
}
});
}

Possible memory leak in android. Might be using the wrong cleanup method, or missing something

I have a memory leak. Here's the code
package fourguys.testing.IntentTest;
import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.media.MediaPlayer; import android.media.AudioManager; import android.content.Context;
public class CanvasDrawingActivity extends Activity {
private static final int FIRE = 0;
private int initVolume = 0;
private Handler handler;
private MyCanvas v;
private MediaPlayer mp;
private AudioManager am;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
am = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
// this method gets the current volume setting for music
initVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,100,AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
mp = MediaPlayer.create(this, R.raw.test);
makeHandler();
v =new MyCanvas(this);
new Thread(new Runnable(){
#Override
public void run() {
while(true)
handler.sendEmptyMessage(FIRE);
}}).start();
setContentView(v);
mp.setLooping(true);
mp.start();
}
private void makeHandler()
{
handler = new Handler(){
#Override
public void handleMessage(Message msg) {
switch(msg.what)
{
case FIRE:
{
v.invalidate();
break;
}
}
}
};
}
protected void onPause() {
super.onPause();
mp.stop();
}
protected void onFinish() {
mp.stop();
}
}
and this:
package fourguys.testing.IntentTest;
import android.app.Activity; import android.content.Intent; import android.media.MediaPlayer; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.view.WindowManager;
public class IntentTest extends Activity { /** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//reciever intentReceiver = new reciever();
// IntentFilter intentFilter = new IntentFilter("com.app.REC");
//registerReceiver(intentReceiver, intentFilter);
Button b = (Button)this.findViewById(R.id.endButton);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(IntentTest.this,CanvasDrawingActivity.class);
startActivity(i);
}
});
}
// the onPause method get called when the app is either being hidden or being closed so this the place where we would want to clean anything up like stoping the media player.
#Override
protected void onPause()
{
super.onPause();
}
}
I run the app and it gets wonky on exit. It locks the handset and causes the battery to run hot. I need to pull the battery physically to reboot. Any thoughts as to why that might be? It runs fantastically on the emulator. Should I be using onFinish instead, or am I not cleaning something up and I'm missing it?
It is this part of your code:
new Thread(new Runnable(){
#Override
public void run() {
while(true)
handler.sendEmptyMessage(FIRE);
}}).start();
You're doing three obvious things wrong here. 1) You're not killing it and/or pausing it in Activity#onPause. 2) You're not calling setDaemon(true); this will cause the process to continue and not die while this thread is running. 3) you're using a hot loop, i.e., you're not calling Thread#sleep() or some other type of equivalent method there to pause and stop fully using the cpu.

Categories

Resources