Как запустить CountDownTimer в службе на Android?

Мне нужна служба, которая запускает CountDownTimer, и в каждом тике я хочу показать обратный отсчет в Activity и после некоторого интервала воспроизвести звук.

Все процессы выполняются в одной операции, но во время входящего вызова обратный отсчет не работает, поэтому я хочу сделать это с помощью службы.

Может кто-нибудь мне помочь?

заблаговременно.

Обновление...

mCountDownTimer = new CountDownTimer(mTimerDuration, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                if (mTimerDuration > 0) {
                    mDurationCount += 1000;
                    showCountDown(
                            ActivityA.this,
                            (mSimpleDateFormat.format(mTimerDuration
                                    - mDurationCount)));
                    if (mDurationCount == mTimerDuration) {
                        if (mRepeatTime > 1) {
                            startRepeatTimer();
                        }
                        finishTimer();
                    }
                }
            }

            @Override
            public void onFinish() {
            }
        }.start();

Ответ 1

Самый простой способ - это, вероятно, использовать создание широковещательного приемника в вашей деятельности и передачу услуг для трансляции. Здесь полный список для класса обслуживания с упрощенным CountDownTimer.

package com.example.cdt;

import android.app.Service;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.util.Log;

public class BroadcastService extends Service {

    private final static String TAG = "BroadcastService";

    public static final String COUNTDOWN_BR = "your_package_name.countdown_br";
    Intent bi = new Intent(COUNTDOWN_BR);

    CountDownTimer cdt = null;

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

            Log.i(TAG, "Starting timer...");

            cdt = new CountDownTimer(30000, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {

                    Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
                    bi.putExtra("countdown", millisUntilFinished);
                    sendBroadcast(bi);
                }

                @Override
                public void onFinish() {
                    Log.i(TAG, "Timer finished");
                }
            };

            cdt.start();
        }

        @Override
        public void onDestroy() {

            cdt.cancel();
            Log.i(TAG, "Timer cancelled");
            super.onDestroy();
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {       
            return super.onStartCommand(intent, flags, startId);
        }

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

И вот соответствующие строки из основного вида деятельности:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    startService(new Intent(this, BroadcastService.class));
    Log.i(TAG, "Started service");
}

private BroadcastReceiver br = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {            
        updateGUI(intent); // or whatever method used to update your GUI fields
    }
};

@Override  
public void onResume() {
    super.onResume();        
    registerReceiver(br, new IntentFilter(BroadcastService.COUNTDOWN_BR));
    Log.i(TAG, "Registered broacast receiver");
    }

@Override
public void onPause() {
    super.onPause();
    unregisterReceiver(br);
    Log.i(TAG, "Unregistered broacast receiver");
}

@Override
public void onStop() {
    try {
        unregisterReceiver(br);
    } catch (Exception e) {
        // Receiver was probably already stopped in onPause()
    }
    super.onStop();
}
@Override
public void onDestroy() {        
    stopService(new Intent(this, BroadcastService.class));
    Log.i(TAG, "Stopped service");
    super.onDestroy();
}

private void updateGUI(Intent intent) {
    if (intent.getExtras() != null) {
        long millisUntilFinished = intent.getLongExtra("countdown", 0);
        Log.i(TAG, "Countdown seconds remaining: " +  millisUntilFinished / 1000);            
    }
}

Вам также необходимо определить службу между тегами приложения start/end в файле манифеста.

<service android:name=".BroadcastService" />

Ответ 2

Загрузить исходный код Таймер обратного отсчета Android в фоновом режиме

activity_main.xml

<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">


    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/et_hours"
        android:hint="Hours"
        android:inputType="time"
        android:layout_marginRight="5dp"
        />

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn_timer"
    android:layout_above="@+id/btn_cancel"
    android:text="Start Timer"/>

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:id="@+id/btn_cancel"
    android:text="cancel timer"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tv_timer"
    android:layout_centerInParent="true"
    android:textSize="25dp"
    android:textColor="#000000"
    android:text="00:00:00"/>

</RelativeLayout>

Timer_Service.java

package com.countdowntimerservice;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

public class Timer_Service extends Service {

public static String str_receiver = "com.countdowntimerservice.receiver";

private Handler mHandler = new Handler();
Calendar calendar;
SimpleDateFormat simpleDateFormat;
String strDate;
Date date_current, date_diff;
SharedPreferences mpref;
SharedPreferences.Editor mEditor;

private Timer mTimer = null;
public static final long NOTIFY_INTERVAL = 1000;
Intent intent;

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

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

    mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    mEditor = mpref.edit();
    calendar = Calendar.getInstance();
    simpleDateFormat = new SimpleDateFormat("HH:mm:ss");

    mTimer = new Timer();
    mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);
    intent = new Intent(str_receiver);
}


class TimeDisplayTimerTask extends TimerTask {

    @Override
    public void run() {
        mHandler.post(new Runnable() {

            @Override
            public void run() {

                calendar = Calendar.getInstance();
                simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
                strDate = simpleDateFormat.format(calendar.getTime());
                Log.e("strDate", strDate);
                twoDatesBetweenTime();

            }

        });
    }

}

public String twoDatesBetweenTime() {


    try {
        date_current = simpleDateFormat.parse(strDate);
    } catch (Exception e) {

    }

    try {
        date_diff = simpleDateFormat.parse(mpref.getString("data", ""));
    } catch (Exception e) {

    }

    try {


        long diff = date_current.getTime() - date_diff.getTime();
        int int_hours = Integer.valueOf(mpref.getString("hours", ""));

        long int_timer = TimeUnit.HOURS.toMillis(int_hours);
        long long_hours = int_timer - diff;
        long diffSeconds2 = long_hours / 1000 % 60;
        long diffMinutes2 = long_hours / (60 * 1000) % 60;
        long diffHours2 = long_hours / (60 * 60 * 1000) % 24;


        if (long_hours > 0) {
            String str_testing = diffHours2 + ":" + diffMinutes2 + ":" + diffSeconds2;

            Log.e("TIME", str_testing);

            fn_update(str_testing);
        } else {
            mEditor.putBoolean("finish", true).commit();
            mTimer.cancel();
        }
    }catch (Exception e){
        mTimer.cancel();
        mTimer.purge();


    }

    return "";

}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.e("Service finish","Finish");
}

private void fn_update(String str_time){

    intent.putExtra("time",str_time);
    sendBroadcast(intent);
}
}

MainActivity.java

package com.countdowntimerservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Calendar;


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private Button btn_start, btn_cancel;
private TextView tv_timer;
String date_time;
Calendar calendar;
SimpleDateFormat simpleDateFormat;
EditText et_hours;

SharedPreferences mpref;
SharedPreferences.Editor mEditor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    init();
    listener();


}

private void init() {
    btn_start = (Button) findViewById(R.id.btn_timer);
    tv_timer = (TextView) findViewById(R.id.tv_timer);
    et_hours = (EditText) findViewById(R.id.et_hours);
    btn_cancel = (Button) findViewById(R.id.btn_cancel);



    mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    mEditor = mpref.edit();

    try {
        String str_value = mpref.getString("data", "");
        if (str_value.matches("")) {
            et_hours.setEnabled(true);
            btn_start.setEnabled(true);
            tv_timer.setText("");

        } else {

            if (mpref.getBoolean("finish", false)) {
                et_hours.setEnabled(true);
                btn_start.setEnabled(true);
                tv_timer.setText("");
            } else {

                et_hours.setEnabled(false);
                btn_start.setEnabled(false);
                tv_timer.setText(str_value);
            }
        }
    } catch (Exception e) {

    }



}

private void listener() {
    btn_start.setOnClickListener(this);
    btn_cancel.setOnClickListener(this);

}

@Override
public void onClick(View v) {

    switch (v.getId()) {
        case R.id.btn_timer:


            if (et_hours.getText().toString().length() > 0) {

                int int_hours = Integer.valueOf(et_hours.getText().toString());

                if (int_hours<=24) {


                    et_hours.setEnabled(false);
                    btn_start.setEnabled(false);


                    calendar = Calendar.getInstance();
                    simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
                    date_time = simpleDateFormat.format(calendar.getTime());

                    mEditor.putString("data", date_time).commit();
                    mEditor.putString("hours", et_hours.getText().toString()).commit();


                    Intent intent_service = new Intent(getApplicationContext(), Timer_Service.class);
                    startService(intent_service);
                }else {
                    Toast.makeText(getApplicationContext(),"Please select the value below 24 hours",Toast.LENGTH_SHORT).show();
                }
/*
                mTimer = new Timer();
                mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);*/
            } else {
                Toast.makeText(getApplicationContext(), "Please select value", Toast.LENGTH_SHORT).show();
            }
            break;


        case R.id.btn_cancel:


         Intent intent = new Intent(getApplicationContext(),Timer_Service.class);
         stopService(intent);

            mEditor.clear().commit();

            et_hours.setEnabled(true);
            btn_start.setEnabled(true);
            tv_timer.setText("");


            break;

    }

}

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String str_time = intent.getStringExtra("time");
        tv_timer.setText(str_time);

    }
};

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(broadcastReceiver,new IntentFilter(Timer_Service.str_receiver));

}

@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(broadcastReceiver);
}
}