使用START_STICKY或START_NOT_STICKY保持后台服务无效

时间:2018-06-26 04:25:12

标签: android service countdowntimer

我使用服务在后台运行CountDownTimer来创建应用程序。

但是,当应用程序关闭/终止时,后台服务有时会自行失败或停止。

我尝试使用START_STICKYSTART_NOT_STICK,但仍然无法正常工作,无法使服务CountDownTimer保持活动状态。 (this the different of them

我也尝试了我在stackoverflow上发现的所有建议,但同样没有用。

这是我的代码:

SessionTimerService.java

public class SessionTimerService extends Service{

    private CountDownTimer countDownTimer;
    public static boolean isServiceRunning = false;

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

    @Override
    public void onDestroy() {
        isServiceRunning = false;
        super.onDestroy();
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if(intent!=null && intent.getAction().equals(Constant.ACTION_START_SERVICE)){
            startTimer();
        }else{
            stopTimer();
        }
        return START_STICKY;
    }

    private void stopTimer(){
        stopForeground(true);
        stopSelf();
        isServiceRunning = false;
    }

    private void startTimer(){
        if(isServiceRunning)return;
        isServiceRunning = true;

        String formatCountDown = "%02d:%02d:%02d";
        countDownTimer = new CountDownTimer(TimeUnit.MINUTES.toMillis(1), 1000){

            @Override
            public void onTick(long millisUntilFinished) {
                String time = ""+String.format(formatCountDown,
                        TimeUnit.MILLISECONDS.toHours(millisUntilFinished),
                        TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(
                                TimeUnit.MILLISECONDS.toHours(millisUntilFinished)),
                        TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(
                                TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)));
                Timber.d("The Time : " + time);
                Intent broadcast = new Intent(Constant.EVENT_SESSION_TIMER);
                broadcast.putExtra(Constant.BROADCAST_TIMER, time);
                LocalBroadcastManager.getInstance(App.getInstance().getApplicationContext()).sendBroadcast(broadcast);

            }

            @Override
            public void onFinish() {
                Toast.makeText(SessionTimerService.this, "Timer ended!", Toast.LENGTH_SHORT).show();
            }
        };
        countDownTimer.start();
    }


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

App.java

我从应用程序启动CountDownTimer。这里的代码:

public class App extends Application {

    private ApplicationComponent applicationComponent;
    private static boolean isChatActivityOpen = false;
    private static boolean isSendChat = false;
    private static App instanceApp;
    private CountDownTimer countDownTimer;
    private Handler handler = new Handler();

    @Override
    public void onCreate() {
        super.onCreate();
        Fabric.with(this, new Crashlytics());

        Timber.plant(new Timber.DebugTree());

        instanceApp = this;

        // TODO: Add this project to your fabric.io
        /*Crashlytics crashlyticsKit = new Crashlytics.Builder()
                .core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
                .build();
        Fabric.with(this, crashlyticsKit);*/

        if (applicationComponent == null) {
            applicationComponent = DaggerApplicationComponent.builder()
                    .applicationModule(new ApplicationModule(App.get(this)))
                    .build();
        }
    }

    public static App get(Context context){
        return (App) context.getApplicationContext();
    }

    public ApplicationComponent getComponent(){
        return applicationComponent;
    }

    public static boolean isChatActivityOpen() {
        return isChatActivityOpen;
    }

    public static boolean isSendChat(){
        return isSendChat;
    }

    public static synchronized App getInstance(){
        return instanceApp;
    }

    public void setConnectivityListener(ConnectivityReceiver.ConnectivityReceiverListener listener){
        ConnectivityReceiver.connectivityReceiverListener = listener;
    }

    public static void setChatActivityOpen(boolean isChatActivityOpen) {
        App.isChatActivityOpen = isChatActivityOpen;
    }

    public static void setSendChatStatus(boolean isSendChat){
        App.isSendChat = isSendChat;
    }

    public void startTimer(){
        Intent intent = new Intent(getInstance().getApplicationContext(), SessionTimerService.class);
        intent.setAction(Constant.ACTION_START_SERVICE);
        startService(intent);
    }

    public void stopTimer(){
        Intent intent = new Intent(getInstance().getApplicationContext(), SessionTimerService.class);
        intent.setAction(Constant.ACTION_STOP_SERVICE);
        stopService(intent);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
    }
}

要在我的活动中启动计时器,请按以下步骤操作:

App.startTimer()App.stopTimer()

注意:我在一个活动中致电App.startTimer()

请帮助修复此错误。我谢谢你。

3 个答案:

答案 0 :(得分:0)

如果您要定位的是Android 8+,则this is an intended behaviour

您的后台服务将在几分钟后被杀死。

如果您定位的版本早于8:

您应该在Application类的onCreate中使用startTimer。

如果您将服务置为粘性,则该服务一旦被终止,将重新启动Application上下文,并且仅执行Application类的onCreate内的内容。

如果将startTimer保留在Activity中,则它将按前台意图启动,一旦终止,它将不会重新创建自身。

答案 1 :(得分:0)

这取决于您要如何使用服务。

如果您希望在应用被终止时运行服务,这将会发生:

应用正在运行->被杀死->上下文被破坏->服务在被杀死时重新启动应用,从那里开始,只有应用上下文是有效的,因此,您的应用中唯一会发生的事情就是onCreate事件的发生应用类别。 一旦您杀死了您的应用程序,所有内容都会被销毁,然后它将尝试重新创建它的一部分。

因此,一旦您终止应用程序,它将不会重新创建活动,也不会重新创建服务。

因此,如果您希望某项服务在特定的活动中启动,那么一旦您终止了该应用程序,该服务将无法正常工作。

public class App extends Application {

private ApplicationComponent applicationComponent;
private static boolean isChatActivityOpen = false;
private static boolean isSendChat = false;
private static App instanceApp;
private CountDownTimer countDownTimer;
private Handler handler = new Handler();

@Override
public void onCreate() {
    super.onCreate();
    Fabric.with(this, new Crashlytics());

    Timber.plant(new Timber.DebugTree());

    instanceApp = this;

    startTimer();

    // TODO: Add this project to your fabric.io
    /*Crashlytics crashlyticsKit = new Crashlytics.Builder()
            .core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
            .build();
    Fabric.with(this, crashlyticsKit);*/

    if (applicationComponent == null) {
        applicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(App.get(this)))
                .build();
    }
}

答案 2 :(得分:0)

您可以执行以下操作:

  1. 仅在不将其绑定到活动的情况下启动服务
  2. 还启动一个通知服务,即使强制关闭该应用程序,该服务也将继续运行