Implementing a Count down timer using Service in the background
Asked Answered
D

1

7

What I want to do in my app: 1. When the user opens the app, he will be able to see an already running countdown timer. So in that case I want to show the countdown numbers in a textview that will always update each second. 2. The user will be able to stop it. 3. The user can leave the application, but the countdown should still go on and show updated time when he comes back to the application UI.

So based on the above points, I understand I need to implement Service that does work in the background. I have read this link but my problem is with the implementation. I am quite at a lost about how to implement that way. That being said, I also cannot think of a way as to showing the time in the UI once the user comes back to the application. I have also seen this link as well, but I am not sure if only implementing CountDownTimer makes it a running Service. So how should I proceed and implement it? Any links to specific tutorials/codes are appreciated. Thanks.

UPDATES: I have so far been able to do the following: MainActivity.java

public class MainActivity extends Activity {

Button btnStart,btnStop;
Intent serviceIntent;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btnStart = (Button) findViewById(R.id.btnStart);
    btnStop = (Button) findViewById(R.id.btnStop);
    tv = (TextView) findViewById(R.id.timeView);

    //final MyCounter timer = new MyCounter(100000,1000);
    //tv.setText("100"); 
    //timer.start();
    serviceIntent = new Intent(MainActivity.this,MyService.class);

    btnStart.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            startService(serviceIntent);
        }
    });

    btnStop.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            stopService(serviceIntent);
        }
    });
}
@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;
}

MyService.java:

public class MyService extends Service {

MyCounter timer;
@Override
public void onCreate() {
    // TODO Auto-generated method stub
    timer = new MyCounter(100000,1000);
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // TODO Auto-generated method stub
    timer.start();
    return super.onStartCommand(intent, flags, startId);
}
private class MyCounter extends CountDownTimer{

    public MyCounter(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
    }

    @Override
    public void onFinish() {
        Toast.makeText(getApplicationContext(), "death", Toast.LENGTH_LONG).show();
        stopSelf();
    }

    @Override
    public void onTick(long millisUntilFinished) {

        Toast.makeText(getApplicationContext(), (millisUntilFinished/1000)+"", Toast.LENGTH_SHORT).show();
    }
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    timer.cancel();
    //stopSelf();
    super.onDestroy();

}

@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}

    }

The problem is: 1. I don't know how to show the countdown on the MainActivity UI apart from this Toast. 2. It doesn't stop counting when I press Stop Button.

Dermal answered 5/5, 2013 at 7:0 Comment(6)
I think you can use broadcast as a communication, this will help you.Tribade
@GhalebKhaled could you please explain about implementation? I have seen a tutorial from vogella vogella.com/articles/AndroidServices/article.html and couldn't help myself understanding how broadcast receivers are called.Dermal
check vogella.com/articles/AndroidBroadcastReceiver/article.html and edureka.in/blog/android-tutorials-broadcast-receivers hoping this will help youTribade
You can use LocalBroadcastManager, its the easiest way see this tutorial intertech.com/Blog/Post/…Fronde
@RogerGarzonNieto the link isn't working :(Dermal
Possible duplicate of Android count down timer in backgroundBudworth
S
1

use bindService(Intent service, ServiceConnection conn, int flag) to bind your countdown service, then in your service, return your binder that contain your count, and in your activity, a instantiated ServiceConnection object can handle the binder. AIDL can do this as well, suggest have a look at how to bind service firstly, wish can help you.

demo

public class BindService extends Service{
private int count;
private boolean quit;
private MyBinder binder = new MyBinder();
// My Binder
public class MyBinder extends Binder
{
    public int getCount()
    {
        // get the counting status:count
        return count;
    }
}

@Override
public IBinder onBind(Intent intent)
{
    System.out.println("Service is Binded");
    // return the binder instance
    return binder;
}

@Override
public void onCreate()
{
    super.onCreate();
    System.out.println("Service is Created");
    // counting work
    new Thread()
    {
        @Override
        public void run()
        {
            while (!quit)
            {
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                }
                count++;
            }
        }
    }.start();      
}
// invoke when the service unbind
@Override
public boolean onUnbind(Intent intent)
{
    System.out.println("Service is Unbinded");
    return true;
}

@Override
public void onDestroy()
{
    super.onDestroy();
    this.quit = true;
    System.out.println("Service is Destroyed");
}

@Override
public void onRebind(Intent intent) 
{
    super.onRebind(intent);
    this.quit = true;
    System.out.println("Service is ReBinded");
}   

}

and then the activity

public class MainActivity extends Activity{
Button bind , unbind , getServiceStatus;
BindService.MyBinder binder;
// define a ServiceConnection object
private ServiceConnection conn = new ServiceConnection()
{
    // then the Activity connected with the Service, this will be called
    @Override
    public void onServiceConnected(ComponentName name
        , IBinder service)
    {
        System.out.println("--Service Connected--");
        // achieve MyBinder instance
        binder = (BindService.MyBinder) service;
    }
    // then the connection break off
    @Override
    public void onServiceDisconnected(ComponentName name)
    {
        System.out.println("--Service Disconnected--");         
    }
};
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    bind = (Button) findViewById(R.id.bind);
    unbind = (Button) findViewById(R.id.unbind);
    getServiceStatus = (Button) findViewById(R.id.getServiceStatus);

    final Intent intent = new Intent();

    intent.setAction("org.crazyit.service.BIND_SERVICE");       
    bind.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View source)
        {
            //bind Serivce
            bindService(intent , conn , Service.BIND_AUTO_CREATE);  
        }
    });
    unbind.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View source)
        {
            //unbind Serivce
            unbindService(conn);
        }
    }); 
    getServiceStatus.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View source)
        {
            // Toast to show the conut value
            Toast.makeText(MainActivity.this
                , "Serivce's count value is:" + binder.getCount()
                , 4000)
                .show();
        }
    });
}}
Stanwood answered 5/5, 2013 at 8:45 Comment(8)
tried using bindService. the thing is I am new in android and things aren't always quite clear when it comes to implementation. could you please make it clear a bit more by showing it in the code?Dermal
when i click on service status button, the app crashes :(Dermal
i don't know how and i hope you can show me the log, but i don't think you can run my demo directly, for example, you need to add intent filter to filtrate the action "org.crazyit.service.BIND_SERVICE" when you registe the service in the manifest.xmlStanwood
it now works, but, the main problem still persists. when I press the back button, it unbinds, and the counter doesn't continue after I get back at the UI. I happen to to come through the same thing with bindings, and I get a feeling that bindings can't solve this problem. or can it?Dermal
of course, bind means that the service's life circle will depend on who call it, so, when you finish the activity, the service will be unbind and then destory, and the counting work will stop absolutely. And then, for you problem, i think you need a Context counting work so you can call it anytime before you exits your app, how about trying to start your service and then use the broadcast to handle your count value?Stanwood
startService() can be called for as many times as you want if the service still living, you can send you count value in onStartCommand(), which will be called every time you invoke the startService(), send a broadcast, and then receive and handle it in your activity.Stanwood
okay let me look into that and i will get back to you again. thanksDermal
my pleasure! May you succeed.Stanwood

© 2022 - 2024 — McMap. All rights reserved.