【问题标题】:Countdown Timer that still runs when the phone is off or app is killed当手机关闭或应用程序被杀死时仍然运行的倒数计时器
【发布时间】:2014-08-21 06:26:24
【问题描述】:

我正在尝试创建一个倒数计时器,即使在应用程序被终止或手机关闭时也会运行。例如,假设我运行倒数计时器从 5 小时开始倒计时。当我关闭它时,它会重置为零。我想要它,这样当我从 5 小时开始倒计时并将手机转一小时并重新打开时,计时器显示剩余时间为 4 小时。我正在研究服务和多线程,但无法生成或找到适合我的解决方案。

In Android i want to run countdown timer who can run in background also

Implementing a Count down timer using Service in the background

这是我的代码段:

start_timer.setOnClickListener(new View.OnClickListener() {


    @Override
    public void onClick(View view) {

        new AlertDialog.Builder( MainActivity.this )
                .setMessage( "Are you sure you want to block the selected apps for the set amount of time?" )
                .setPositiveButton( "Yeah man!", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Log.d( "AlertDialog", "Positive" );

                        hourint = Integer.valueOf(number_text.getText().toString());

                        minuteint = Integer.valueOf(minute_text.getText().toString());

                        secondint = Integer.valueOf(second_text.getText().toString());

                        Log.i("YourActivity", "Hours: " + hourint);

                        Log.i("YourActivity", "Minutes: " + minuteint);

                        Log.i("YourActivity", "Seconds: " + secondint);

                        totalTimeCountInMilliseconds = ((hourint*60*60) +(minuteint*60) + (secondint)) * 1000;      // time count
                        timeBlinkInMilliseconds = 30*1000;

                        countDownTimer = new CountDownTimer(totalTimeCountInMilliseconds, 500) {
                            // 500 means, onTick function will be called at every 500 milliseconds

                            @Override
                            public void onTick(long leftTimeInMilliseconds) {
                                long seconds = leftTimeInMilliseconds / 1000;
                                mSeekArc.setVisibility(View.INVISIBLE);
                                start_timer.setVisibility(View.INVISIBLE);
                                block_button1.setVisibility(View.INVISIBLE);



                                if ( leftTimeInMilliseconds < timeBlinkInMilliseconds ) {
                                    // textViewShowTime.setTextAppearance(getApplicationContext(), R.style.blinkText);
                                    // change the style of the textview .. giving a red alert style

                                    if ( blink ) {
                                        number_text.setVisibility(View.VISIBLE);
                                        minute_text.setVisibility(View.VISIBLE);
                                        second_text.setVisibility(View.VISIBLE);


                                        // if blink is true, textview will be visible
                                    } else {
                                        number_text.setVisibility(View.INVISIBLE);
                                        minute_text.setVisibility(View.INVISIBLE);
                                        second_text.setVisibility(View.INVISIBLE);


                                    }

                                    blink = !blink;         // toggle the value of blink
                                }

                                second_text.setText(String.format("%02d", seconds % 60));
                                minute_text.setText(String.format("%02d", (seconds / 60) % 60));
                                number_text.setText(String.format("%02d", seconds / 3600));                     // format the textview to show the easily readable format
                            }


                            @Override
                            public void onFinish() {
                                // this function will be called when the timecount is finished
                                //textViewShowTime.setText("Time up!");
                                number_text.setVisibility(View.VISIBLE);
                                minute_text.setVisibility(View.VISIBLE);
                                second_text.setVisibility(View.VISIBLE);
                                mSeekArc.setVisibility(View.VISIBLE);
                                start_timer.setVisibility(View.VISIBLE);
                                block_button1.setVisibility(View.VISIBLE);


                            }

                        }.start();
                    }
                })
                .setNegativeButton( "Nope!", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Log.d( "AlertDialog", "Negative" );
                        dialog.cancel();
                    }
                } )
                .show();

我怎样才能做到这一点,我必须对我的代码进行哪些修改?

编辑:这是我的完整代码:

http://pastebin.com/pth9KZWP

编辑 2:这里是修改后的代码:

我的应用程序无法启动。而且我没有收到任何 logcat 语句,所以我不知道该怎么办......

http://pastebin.com/L8HgGtsy

【问题讨论】:

  • 当手机即将关机时,您需要将当前时间(日期也更好)写入一些持久存储中。手机重启后,检查current time - the time phone was shut down。然后检查countdownTime - ( current time - the time phone was shut down)。如果这是正数,您可以设置 countDownTime 的新值
  • 感谢您的想法,我在这里得到了一些指导。所以我现在正在尝试构建它。我有点理解你要去哪里。您是否可以澄清条件语句:“一旦手机重新启动,请检查当前时间 - 手机关闭的时间”。为什么会是当前时间减去关机时间?它不会总是积极的吗?可能需要更多解释。
  • 假设您的手机关机后倒计时还剩 10 小时。现在,如果您在下午 1 点关闭手机并在下午 5 点打开它。那么,5-1=4。您必须从 10 中减去 4。即 6 将是当前倒计时时间。
  • 手机关机时如何存储值?我可以使用 SharedPreferences 存储其他所有内容,但我将如何实现呢?是否考虑到时区变化?
  • @Hereisthehelpfullink 使用格林威治标准时间的时间戳——那时时区将不相关。但是,您应该考虑访问 NTP 服务器以获得准确的时间(因为 System.currentTimeMillis() 根据用户的日期/时间设置而变化,这可能是不正确的)

标签: java android multithreading timer android-service


【解决方案1】:

输入倒计时时间后,计算倒计时结束的时间并将其写入持久存储。然后,每当应用程序重新启动时,读取该时间并计算从现在开始还剩下多少时间。

【讨论】:

  • 我究竟应该使用什么来实现这一目标?
  • developer.android.com/training/basics/data-storage/files.html。按照“内部文件”的说明进行操作
  • 如果你只想写一个日期,你可以把它写成long。最简单的方法可能是使用 SharedPreferences,例如:stackoverflow.com/a/3624358/1137118
  • 所以当应用程序被终止时,我将日期写入 SharedPreferences。编写代码来计算自上次重新打开应用程序以来已经过去了多少时间。然后在那里定时间?当实施不是时,你们让它听起来很简单。哈哈。嗯,但我应该使用 SharedPreferences 还是内部文件存储?
  • 我不会等待应用程序关闭来编写它。我会在输入后立即编写它,因此您不必在关闭时挂钩任何东西。此外,如果您正在编写 END 时间,那么您不需要计算已经过去了多少时间。您将拥有足够的信息来知道要向用户显示什么。
【解决方案2】:

我想给遇到同样问题的人;)

这里是在 onCreate 中检索类顶部的 SharedPreferences

startimerPreferences = getPreferences(MODE_APPEND);

Date startDate = new Date(startimerPreferences.getLong("time", 0));
timerstarted = startDate.getTime();
Log.e("This is the start time!!!!!:  ", timerstarted + "");


endTimerPreferences = getPreferences(MODE_APPEND);
Date endDate = new Date(endTimerPreferences.getLong("time", 0));
timerends = endDate.getTime();
Log.e("This is the end time!!!!!:  ", timerends + "");


Date openagain = new Date(System.currentTimeMillis());
reopened = openagain.getTime();

如果还有剩余时间,则在此处启动剩余时间的计时器:

    if(timerstarted > 0)
    {
        if(reopened <timerends){
            //start countdown timer with new time.
            //set countdowntime to timerends-reopen.

            newtotalTimeCountInMilliseconds = timerends-reopened;
            countDownTimer = new CountDownTimer(newtotalTimeCountInMilliseconds, 500) {
                // 500 means, onTick function will be called at every 500 milliseconds

                @Override
                public void onTick(long leftTimeInMilliseconds) {

                    long seconds = leftTimeInMilliseconds / 1000;
                    mSeekArc.setVisibility(View.INVISIBLE);
                    start_timer.setVisibility(View.INVISIBLE);
                    block_button1.setVisibility(View.INVISIBLE);


                    if (leftTimeInMilliseconds < timeBlinkInMilliseconds) {
                        // textViewShowTime.setTextAppearance(getApplicationContext(), R.style.blinkText);
                        // change the style of the textview .. giving a red alert style

                        if (blink) {
                            number_text.setVisibility(View.VISIBLE);
                            minute_text.setVisibility(View.VISIBLE);
                            second_text.setVisibility(View.VISIBLE);


                            // if blink is true, textview will be visible
                        } else {
                            number_text.setVisibility(View.INVISIBLE);
                            minute_text.setVisibility(View.INVISIBLE);
                            second_text.setVisibility(View.INVISIBLE);


                        }

                        blink = !blink;         // toggle the value of blink
                    }

                    second_text.setText(String.format("%02d", seconds % 60));
                    minute_text.setText(String.format("%02d", (seconds / 60) % 60));
                    number_text.setText(String.format("%02d", seconds / 3600));                     // format the textview to show the easily readable format
                }


                @Override
                public void onFinish() {
                    // this function will be called when the timecount is finished
                    //textViewShowTime.setText("Time up!");
                    number_text.setVisibility(View.VISIBLE);
                    minute_text.setVisibility(View.VISIBLE);
                    second_text.setVisibility(View.VISIBLE);
                    mSeekArc.setVisibility(View.VISIBLE);
                    start_timer.setVisibility(View.VISIBLE);
                    block_button1.setVisibility(View.VISIBLE);


                }

            }.start();



        }
    }

这是用户提交操作的初始计时器。我将当前时间和结束时间提交并保存在 SharedPreferences 中。

start_timer.setOnClickListener(new View.OnClickListener() {


            @Override
            public void onClick(View view) {

                new AlertDialog.Builder( MainActivity.this )
                        .setMessage( "Are you sure you want to block the selected apps for the set amount of time?" )
                        .setPositiveButton("Yeah man!", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                Log.d("AlertDialog", "Positive");

                                hourint = Integer.valueOf(number_text.getText().toString());

                                minuteint = Integer.valueOf(minute_text.getText().toString());

                                secondint = Integer.valueOf(second_text.getText().toString());

                                Log.i("YourActivity", "Hours: " + hourint);

                                Log.i("YourActivity", "Minutes: " + minuteint);

                                Log.i("YourActivity", "Seconds: " + secondint);

                                Date currenttime = new Date(System.currentTimeMillis());

                                timerstarted = currenttime.getTime();
                                Log.e("This is the current time:  ", timerstarted + "");
                                startimerPreferences = getPreferences(MODE_APPEND);
                                SharedPreferences.Editor starteditor = startimerPreferences.edit();
                                starteditor.putLong("time", timerstarted);
                                starteditor.commit();


                                Date endtime = new Date(System.currentTimeMillis());

                                timerends = endtime.getTime() + (((hourint * 60 * 60) + (minuteint * 60) + (secondint)) * 1000);
                                Log.e("This is the end time:  ", timerends + "");
                                endTimerPreferences = getPreferences(MODE_APPEND);
                                SharedPreferences.Editor endeditor = endTimerPreferences.edit();
                                endeditor.putLong("time", timerends);
                                endeditor.commit();









                                totalTimeCountInMilliseconds = (((hourint * 60 * 60) + (minuteint * 60) + (secondint)) * 1000);      // time count
                                timeBlinkInMilliseconds = 30 * 1000;

                                countDownTimer = new CountDownTimer(totalTimeCountInMilliseconds, 500) {
                                    // 500 means, onTick function will be called at every 500 milliseconds

                                    @Override
                                    public void onTick(long leftTimeInMilliseconds) {

                                        long seconds = leftTimeInMilliseconds / 1000;
                                        mSeekArc.setVisibility(View.INVISIBLE);
                                        start_timer.setVisibility(View.INVISIBLE);
                                        block_button1.setVisibility(View.INVISIBLE);


                                        if (leftTimeInMilliseconds < timeBlinkInMilliseconds) {
                                            // textViewShowTime.setTextAppearance(getApplicationContext(), R.style.blinkText);
                                            // change the style of the textview .. giving a red alert style

                                            if (blink) {
                                                number_text.setVisibility(View.VISIBLE);
                                                minute_text.setVisibility(View.VISIBLE);
                                                second_text.setVisibility(View.VISIBLE);


                                                // if blink is true, textview will be visible
                                            } else {
                                                number_text.setVisibility(View.INVISIBLE);
                                                minute_text.setVisibility(View.INVISIBLE);
                                                second_text.setVisibility(View.INVISIBLE);


                                            }

                                            blink = !blink;         // toggle the value of blink
                                        }

                                        second_text.setText(String.format("%02d", seconds % 60));
                                        minute_text.setText(String.format("%02d", (seconds / 60) % 60));
                                        number_text.setText(String.format("%02d", seconds / 3600));                     // format the textview to show the easily readable format
                                    }


                                    @Override
                                    public void onFinish() {
                                        // this function will be called when the timecount is finished
                                        //textViewShowTime.setText("Time up!");
                                        number_text.setVisibility(View.VISIBLE);
                                        minute_text.setVisibility(View.VISIBLE);
                                        second_text.setVisibility(View.VISIBLE);
                                        mSeekArc.setVisibility(View.VISIBLE);
                                        start_timer.setVisibility(View.VISIBLE);
                                        block_button1.setVisibility(View.VISIBLE);


                                    }

                                }.start();
                            }
                        })
                        .setNegativeButton("Nope!", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                Log.d("AlertDialog", "Negative");
                                dialog.cancel();
                            }
                        })
                        .show();

【讨论】:

    猜你喜欢
    • 2018-03-18
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 2016-12-27
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    相关资源
    最近更新 更多