我创建了倒数计时器以显示超时,当用户最小化应用程序时它会正常工作但在用户关闭应用程序时会停止。我在下面添加了代码,请帮助我,这是一个紧急情况。
这是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;
}
提前致谢。
答案 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:使用Service
和SharedPreferences
用以下代码替换你的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