用户关闭应用程序时不会运行倒数计时器

时间:2016-10-12 06:42:16

标签: android broadcastreceiver android-service countdowntimer

我创建了倒数计时器以显示超时,当用户最小化应用程序时它会正常工作但在用户关闭应用程序时会停止。我在下面添加了代码,请帮助我,这是一个紧急情况。

这是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_servie.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;
        }

提前致谢。

1 个答案:

答案 0 :(得分:0)

您需要在START_STCKY方法中返回onStartCommand(),才能在应用关闭时运行服务。

 ....
 public int onStartCommand(Intent intent, int flags, int startId) {   
     return START_STCKY;
 } 
 ....

您可以参考this链接以正确实施服务。

或者,您可以参考this SO问题。

<强>更新 使用Foreground Service可以避免服务被杀。为了使您的服务前景化,请将此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:使用ServiceSharedPreferences

的计数器

用以下代码替换你的Actvity代码:

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代替BroadcastReciver