Android 当用户关闭应用程序时,倒计时计时器不运行

Android 当用户关闭应用程序时,倒计时计时器不运行,android,broadcastreceiver,android-service,countdowntimer,Android,Broadcastreceiver,Android Service,Countdowntimer,我已经创建了倒计时计时器来显示超时,当用户最小化应用程序时,它工作得很好,但当用户关闭应用程序时,它会停止。我在下面添加了代码,请帮助我,这是紧急情况 这是MainActivity.java public static final String TAG = "Demo"; TextView t1 ; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSt

我已经创建了倒计时计时器来显示超时,当用户最小化应用程序时,它工作得很好,但当用户关闭应用程序时,它会停止。我在下面添加了代码,请帮助我,这是紧急情况

这是MainActivity.java

public static final String TAG = "Demo";
    TextView t1 ;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        t1 = (TextView)findViewById(R.id.t1);
         startService(new Intent(this, count_servie.class));
    }
    private BroadcastReceiver br = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {            
            updateGUI(intent);
        }
    };
    public void onResume() {
        super.onResume();        
        registerReceiver(br, new IntentFilter(count_servie.COUNTDOWN_BR));
        }
    private void updateGUI(Intent intent) {
        if (intent.getExtras() != null) {
            long millisUntilFinished = intent.getLongExtra("countdown", 0);
            t1.setText("Countdown seconds remaining: " +  millisUntilFinished / 1000);
        }
    }
这是我的count_servi.java

public class count_servie extends Service {
    public static final String COUNTDOWN_BR = "com.demo.DSemo.countdown_br";
    Intent bi = new Intent(COUNTDOWN_BR);
    CountDownTimer cdt = null;
        public void onCreate() {       
            super.onCreate();
            cdt = new CountDownTimer(30000, 1000) {
                public void onTick(long millisUntilFinished) {
                    bi.putExtra("countdown", millisUntilFinished);
                    sendBroadcast(bi);
                }
                public void onFinish() {
                }
            };
            cdt.start();
        }
        public int onStartCommand(Intent intent, int flags, int startId) {   
            return super.onStartCommand(intent, flags, startId);
        }
        public IBinder onBind(Intent arg0) {       
            return null;
        }

提前感谢。

您需要在
onStartCommand()
方法中返回
START\u STCKY
,以便即使在应用程序关闭时也能运行该服务

 ....
 public int onStartCommand(Intent intent, int flags, int startId) {   
     return START_STCKY;
 } 
 ....
您可以参考链接以正确实现服务

或者,你也可以这样问

更新 使用
前台服务
,以避免您的服务被终止。为了使您的服务成为前台,请将您的
onStartCommand
代码替换为以下代码

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Intent notificationIntent = new Intent(this, MainActivity.class);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
            notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("Timer")
            .setContentText("Doing some work...")
            .setContentIntent(pendingIntent).build();

    startForeground(1337, notification);

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

            bi.putExtra("countdown", millisUntilFinished);
            sendBroadcast(bi);
        }

        public void onFinish() {
            stopForeground(true);
        }
    };
    cdt.start();
    return START_STICKY;
}
Udpate 2:使用
Service
SharedReferences的计数器

用以下代码替换活动的代码:

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.support.v4.os.ResultReceiver;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.util.Calendar;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();
private static final String SHARED_PREF = "MyPref";
private final static int MAX_COUNTER = 30;

public static final String KEY_COUNTER_SECONDS = "seconds";
public static final String KEY_SAVED_COUNTER = "saved_counter";
public static final String KEY_SAVED_TIME_MILLI = "saved_time_milli";

MyResultReceiver mReceiver;
TextView mTvCounter;
SharedPreferences mSharedPref;
long mMaxCounterValueInSeconds = MAX_COUNTER;
long mCurCounterValue = 0;
boolean mShouldSaveValues;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTvCounter = (TextView) findViewById(R.id.tv_counter);
    mReceiver = new MyResultReceiver(null);
    mSharedPref = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
}

@Override
protected void onResume() {
    super.onResume();

    //register listener
    MyService.registerReceiver(mReceiver);

    //get values from shared pref
    long savedCounter = mSharedPref.getLong(KEY_SAVED_COUNTER, -1);
    long savedTime = mSharedPref.getLong(KEY_SAVED_TIME_MILLI, -1);

    //if -1 counter was running when app was closed, get saved values from shared pref
    if (savedTime != -1) {
        //elapsedTime is the time spent in seconds while the app was in background
        long elapsedTime = (getCurrentTimeInMilli() - savedTime)/1000; //convert to sec

        mCurCounterValue = savedCounter + elapsedTime;

        if(mCurCounterValue < MAX_COUNTER){
            //calculate current counter value from values retrieved from shared pref
            mMaxCounterValueInSeconds = MAX_COUNTER - mCurCounterValue;
            //start the value with updated max count value
            startService(mMaxCounterValueInSeconds);
        }else{
            mCurCounterValue = MAX_COUNTER;
        }
    }else{
        //if counter was not running, start the service with max count value = MAX_COUNTER
        startService(mMaxCounterValueInSeconds);
    }

    //update text view
    mTvCounter.setText("" + mCurCounterValue);
}

private void startService(long maxCounter){
    mShouldSaveValues = true;

    Intent intent = new Intent(this, MyService.class);
    Bundle bundle = new Bundle();
    bundle.putLong(KEY_COUNTER_SECONDS, maxCounter);
    intent.putExtras(bundle);
    startService(intent);
}
@Override
protected void onPause() {
    super.onPause();

    //stop the service
    stopService(new Intent(this, MyService.class));
    //unregister listener
    MyService.unregisterReceiver();

    if(mShouldSaveValues) {//save the values only when counter has started
        //save values in the shared preference
        SharedPreferences.Editor editor = mSharedPref.edit();
        Log.d(TAG, "saving counter: " + Long.parseLong(mTvCounter.getText().toString()));
        editor.putLong(KEY_SAVED_COUNTER, Long.parseLong(mTvCounter.getText().toString()));
        editor.putLong(KEY_SAVED_TIME_MILLI, getCurrentTimeInMilli());
        editor.apply();
    }
}

/**
 * This method returns current time in milli seconds
 *
 * @return time in milliseconds
 */
private long getCurrentTimeInMilli() {
    Calendar cal = Calendar.getInstance();
    Date date = cal.getTime();
    long timeInMilli = date.getTime();
    return timeInMilli;
}

/**
 * ResultReceiver is used to get values from MyService.class
 * It is registered in onResume() &
 * unregistered in onPause()
 */
class MyResultReceiver extends ResultReceiver {

    public MyResultReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        String strMilliFinished = resultData.getString(MyService.KEY_MSG);
        updateUI(Long.parseLong(strMilliFinished));
    }

    private void updateUI(final long milliFinished) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {

                mCurCounterValue++;
                mTvCounter.setText("" + mCurCounterValue);

                if(milliFinished == 0) {
                    //resetting counter values

                    mShouldSaveValues = false;
                    mMaxCounterValueInSeconds = MAX_COUNTER;
                    mCurCounterValue = 0;

                    SharedPreferences.Editor editor = mSharedPref.edit();
                    editor.putLong(KEY_SAVED_COUNTER, -1);
                    editor.putLong(KEY_SAVED_TIME_MILLI, -1);
                    editor.apply();

                }
            }
        });
    }
}
}
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.os.ResultReceiver;
import android.util.Log;

public class MyService extends Service {

public static final String KEY_MSG = "msg";

CountDownTimer cdt = null;
private static ResultReceiver mReceiver;

public MyService() {
}

public static void registerReceiver(ResultReceiver receiver) {
    mReceiver = receiver;
}

public static void unregisterReceiver() {
    mReceiver = null;

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Bundle bundle = intent.getExtras();
    long maxCounterValueInSeconds = bundle.getLong(MainActivity.KEY_COUNTER_SECONDS);
    long maxCounter = maxCounterValueInSeconds * 1000;
    cdt = new CountDownTimer(maxCounter, 1000) {
        public void onTick(long millisUntilFinished) {

            sendMessage(1, "" + millisUntilFinished);
        }

        public void onFinish() {
            sendMessage(1, "" + 0);
            stopSelf();
        }
    };
    cdt.start();
    return START_STICKY;
}

private void sendMessage(int resultCode, String message) {

    if (mReceiver != null) {
        Bundle bundle = new Bundle();
        bundle.putString(KEY_MSG, message);
        mReceiver.send(resultCode, bundle);
    }
}

@Override
public void onDestroy() {
    super.onDestroy();
    cdt.cancel();
}

@Override
public IBinder onBind(Intent intent) {
    throw new UnsupportedOperationException("Not yet implemented");
}
}

注意:我使用的是
ResultReceiver
而不是
BroadcastReceiver

如果您不知道答案,请不要停止。任何人对此有任何想法,请帮助我。请帮助我,我没有得到正确的o/p,您是说“重新启动应用程序”吗?我是指重新启动计时器,我还将代码放在启动命令方法中,它正在工作完全但显示通知您能告诉我如何删除它吗?您不能删除前台服务的通知。这是一种告诉用户某些东西正在后台运行的方式,我看到在某个地方计时器正在运行,但不显示通知也在后台天气用户关闭应用程序中运行。