0

How can I make a timer run even though the app is closed? I tried putting a countdowntimer on the onstartcommand of my service class but it's not working. I also added a simple vibrate feature to it so that I can check if the alarm is working. To properly show what I'm saying here are the codes:

mainActivity.java public class MainActivity extends AppCompatActivity {

    private SectionPageAdapter mSectionPageAdapter;

    private ViewPager mViewPager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSectionPageAdapter = new SectionPageAdapter(getSupportFragmentManager());

        mViewPager = (ViewPager) findViewById(R.id.container);
        setupViewPager(mViewPager);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);
    }

    private void setupViewPager(ViewPager viewPager){
        SectionPageAdapter adapter = new SectionPageAdapter(getSupportFragmentManager());
        adapter.addFragment(new page1(), "apps");
        adapter.addFragment(new page2(), "timer");
        adapter.addFragment(new page3(), "details");
        viewPager.setAdapter(adapter);
    }

}

page2_fragment (where the timer is located, the other fragment don't have functions as of now)

package com.softeng.applockerproject;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Vibrator;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import java.util.concurrent.TimeUnit;



public class page2 extends Fragment {
    private static final String TAG =   "page2";
private Button btntest;
private TextView timer,tv;
private Spinner spinner, spinner2;
public int hours, mins, duration;
private Vibrator v;

private static int myVariable;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.page2_fragment,container,false);

    btntest = (Button) view.findViewById(R.id.button2);
    timer = (TextView) view.findViewById(R.id.Timer);
    tv = (TextView) view.findViewById(R.id.textView3);

    //setting up spinners
    spinner = (Spinner) view.findViewById(R.id.spinner1);
    String [] values = {"00","01","02","03","04","05","06"};
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getActivity(), android.R.layout.simple_spinner_item, values);
    adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
    spinner.setAdapter(adapter);
    spinner2 = (Spinner) view.findViewById(R.id.spinner2);
    String [] values2 = {"00","01","10","20","30","40","50","60"};
    ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this.getActivity(), android.R.layout.simple_spinner_item, values2);
    adapter2.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
    spinner2.setAdapter(adapter2);

    //button start
    btntest.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            String spin=spinner.getSelectedItem().toString();
            hours = Integer.parseInt(spin);
            hours = hours*3600000;
            String spin2=spinner2.getSelectedItem().toString();
            mins = Integer.parseInt(spin2);
            mins = mins*60000;
            duration = hours+mins;
            setParam(duration);
            myVariable = duration;
            startService(duration);
        }
    });
    return view;
}


//timer part
public void setParam(int param){
     CountDownTimer countDownTimer = new CountDownTimer(param,    1000) {

        @Override
        public void onTick(long param) {
            long millis= param;
            String hms= String.format("%02d:%02d:%02d",

                    TimeUnit.MILLISECONDS.toHours(millis),
                    TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
                    //seconds
                    ,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
            );
            timer.setText(hms);
        }

        @Override
        public void onFinish() {
            timer.setText("00:00");
            //setVibrate();
            //stopService();
        }
    };
    countDownTimer.start();
}

//vibrate
/*private void setVibrate(){
    long n[] = {50,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000};
    v = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
    v.vibrate(n, -1);
}*/


//services part
public void startService(int duration)
{
    int n = duration;
    Intent intent = new Intent(getActivity(),MyService.class);
    getActivity().startService(intent);
    //Toast.makeText(getActivity(), "starting",Toast.LENGTH_SHORT).show();
}

/*public void stopService( )
{
    getActivity().stopService(new Intent(getActivity(),MyService.class));
    //Toast.makeText(getActivity(), "starting",Toast.LENGTH_SHORT).show();
}*/

public static int getVariable()
{
    return myVariable;
}

}

and lastly my attempt at making a service. MyService.java

package com.softeng.applockerproject;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.os.Vibrator;
import android.support.annotation.Nullable;
import android.widget.Toast;

import java.util.concurrent.TimeUnit;


public class MyService extends Service {

private Vibrator v;
int i = page2.getVariable();
@Override
public void onCreate() {
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //setParam(i);
    Toast.makeText(this,"%02d"+i,Toast.LENGTH_LONG).show();
    return START_STICKY;

}

@Override
public void onDestroy() {
    long n[] = {50,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000};
    v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    v.vibrate(n, -1);
    Toast.makeText(this,"service stopped!",Toast.LENGTH_LONG).show();
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

//private void setVibrate(){

//timer
public void setParam(int param){
    CountDownTimer countDownTimer = new CountDownTimer(param,    1000) {

        @Override
        public void onTick(long param) {
            long millis= param;
            /*String hms= String.format("%02d:%02d:%02d",

                    TimeUnit.MILLISECONDS.toHours(millis),
                    TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
                    //seconds
                    ,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
            );*/
            //timer.setText(hms);
        }

        @Override
        public void onFinish() {
            //timer.setText("00:00");
            //setVibrate();
            onDestroy();
        }
    };
    countDownTimer.start();
}

}

can someone one show how to do it properly?

neo73
  • 434
  • 5
  • 20
jnrx gaming
  • 93
  • 1
  • 1
  • 8

3 Answers3

0

I think what you are needing is AlarmManager since it provides timing services even when you app is not running. See this:

Will AlarmManager work if my application is not running?

From your question, this looks like it will work - unless you need to do processing in the background. That can also be done when your app is "closed" as long as it is not "killed." But that means your service continues to run.

Jim
  • 10,172
  • 1
  • 27
  • 36
0

If you use a static Handler object with a static Runnable in your Activity it's possible to make a timer that continues working even if the activity is closed, without a Service. I can post some code example later, if you want.

UPDATE: In your MainActivity class fields :

   private static Handler handler;
   private static Runnable runnable ;
   private static final TIMER_DELAY = 60000; // 1 minute in milliseconds

in your MainActivity onCreate

 if (handler == null) {
            handler = new Handler();
            runnable = new Runnable() {
                @Override
                public void run() {
                  // do some delayed work
                    handler.postDelayed(runnable, TIMER_DELAY); // repeat again
                }
            };
            handler.postDelayed(runnable, TIMER_DELAY);
        }

Of course any method called inside run() must be static too.

But if the phone enters Sleep mode the timer will stop, for avoid this then you should try the following:

  • Acquire a Partial WAKE_LOCK

  • Start a foreground Service, that means a Service that calls startForeground

  • Show a non dismissable Notification in the Status Bar.

from56
  • 3,976
  • 2
  • 13
  • 23
  • that would be helpful – jnrx gaming Jan 03 '18 at 11:50
  • how can i show the timer on the notification? and what's the reason of using a foreground service – jnrx gaming Jan 04 '18 at 13:27
  • In the Notification you can show any icon you want. The foreground service minimizes the chances of your application being killed by the system. The wake lock prevents the phone from enter deep sleep mode, that's to stop CPU and stopping your timer, but for Android 6 and newer the wake lock is ignored without the foreground service. – from56 Jan 04 '18 at 14:21
0

well I don'y know if this is the best way to tackle this problem. I'm a bit new to this so sorry if this answer will look stupid.

I change some areas in my MyService.java:

package com.softeng.applockerproject;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.os.Vibrator;
import android.support.annotation.Nullable;
import android.widget.Toast;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;


public class MyService extends Service {

    private Vibrator v;
    long i = page2.getVariable();
    //private static Timer timer = new Timer();

    @Override
    public void onCreate() {
        super.onCreate();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        CountDownTimer countDownTimer = new CountDownTimer(60000,    1000) {

            @Override
            public void onTick(long param) {

            }

            @Override
            public void onFinish() {
                //timer.setText("00:00");
                //setVibrate();
                //onDestroy();
                long n[] = {1,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000};
                v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                v.vibrate(n, -1);
                onDestroy();
            }
        };
        countDownTimer.start();
        return START_STICKY;

    }


    public void onDestroy() {
        stopSelf();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

please comment below if you have some suggestions. It will really help me.

jnrx gaming
  • 93
  • 1
  • 1
  • 8