фоновые службы останавливаются, когда приложение закрывается с помощью кнопки НАЗАД

Фоновая служба в Android перестает работать, когда пользователь выходит из приложения с помощью кнопки НАЗАД. Эта же служба отлично работает, если приложение находится на переднем или в фоновом режиме (при нажатии кнопки HOME).

есть 3 случая:

  1. Не выключайте приложение: каждые 15 секунд отображается уведомление (ОК).
  2. Переведите приложение в фоновый режим, нажав кнопку HOME: уведомления продолжают отображаться (ОК)
  3. Нажмите кнопку НАЗАД (приложение закрывается): фоновая служба останавливается, и уведомления больше не отображаются (ОШИБКА)

Ожидаемое поведение

Также в случае № 3 уведомления должны запускаться каждые 15 секунд.

весь мой источник находится ниже

MainActivity.java

    package com.example.service_demo;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

    private TextView timerValue;
    private Button startTimer;
    private Button cancleTimer;
    Intent i;

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

    }

    private void mapview() {

        timerValue = (TextView) findViewById(R.id.timertext);
        startTimer = (Button) findViewById(R.id.starttimer);
        cancleTimer = (Button) findViewById(R.id.cancletimer);
        startTimer.setOnClickListener(this);
        cancleTimer.setOnClickListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        i = new Intent(this, SimpleService.class);
        if (isMyServiceRunning()) {
            Toast.makeText(getBaseContext(), "Service is running,",
                    Toast.LENGTH_SHORT).show();
            registerReceiver(broadcastReceiver, new IntentFilter(
                    SimpleService.BROADCAST_ACTION));
            startTimer.setEnabled(false);
        } else {
            Toast.makeText(getBaseContext(), "There is no service running",
                    Toast.LENGTH_SHORT).show();
        }

    }

    @Override
    public void onClick(View v) {
        if (v == startTimer) {
            startTimer.setEnabled(false);
            i = new Intent(this, SimpleService.class);
            startService(i);
            registerReceiver(broadcastReceiver, new IntentFilter(
                    SimpleService.BROADCAST_ACTION));
        } else if (v == cancleTimer) {
            i = new Intent(this, SimpleService.class);
            stopService(i);
            timerValue.setText("00:00:00");
            startTimer.setEnabled(true);

        }
    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            updateUI(intent);
        }

    };

    private void updateUI(Intent intent) {
        String str = intent.getStringExtra("textval");
        timerValue.setText(str);

    }

    private boolean isMyServiceRunning() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager
                .getRunningServices(Integer.MAX_VALUE)) {
            if (SimpleService.class.getName().equals(
                    service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        i = new Intent(this, SimpleService.class);
        startService(i);
    }

    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        super.onBackPressed();
        System.exit(0); // system.exit(0) is mendatory for my app so it can't be
                        // removed
    }

}

SimpleService

    package com.example.service_demo;

import java.util.Timer;
import java.util.TimerTask;

import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class SimpleService extends Service {

    private NotificationManager mNM;
    private long startTime = 0L;
    long timeInMilliseconds = 0L;
    long timeSwapBuff = 0L;
    long updatedTime = 0L;
    long basestart = System.currentTimeMillis();
    Timer timer = new Timer();
    long timeswap = 0L;
    int secs = 0;
    int mins = 0;
    int hour = 0;
    Intent intent;
    String s;
    public static final String BROADCAST_ACTION = "com.example.service_demo.MainActivity";
    private int NOTIFICATION = 1;

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

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

        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        intent = new Intent(BROADCAST_ACTION);
        Toast.makeText(this, "Service Started", 2000).show();

    }

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

        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                timer.schedule(new RemindTask(), 0, 1000);
            }
        });
        t.start();

        return Service.START_NOT_STICKY;

    }

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

        mNM.cancel(NOTIFICATION);

        if (timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
        }
        Toast.makeText(this, "Service Stoped", 2000).show();
    }

    class RemindTask extends TimerTask {

        @Override
        public void run() {

            timeInMilliseconds = System.currentTimeMillis() - basestart;
            timeSwapBuff = timeswap;
            updatedTime = timeSwapBuff + timeInMilliseconds;

            secs = (int) (updatedTime / 1000);
            mins = secs / 60;
            hour = mins / 60;

            secs = secs % 60;
            mins = mins % 60;

            s = "" + String.format("%02d", hour) + ":" + ""
                    + String.format("%02d", mins) + ":"
                    + String.format("%02d", secs);
            if (s.equalsIgnoreCase("00:00:15")) {
                showNotification();
            }
            intent.putExtra("textval", s);
            sendBroadcast(intent);
        }
    }

    private void showNotification() {
        // In this sample, we'll use the same text for the ticker and the
        // expanded notification
        CharSequence text = s;

        // Set the icon, scrolling text and timestamp
        @SuppressWarnings("deprecation")
        Notification notification = new Notification(R.drawable.ic_launcher,
                text, System.currentTimeMillis());

        // The PendingIntent to launch our activity if the user selects this
        // notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, "Notification Label", text,
                contentIntent);

        // Send the notification.
        mNM.notify(NOTIFICATION, notification);
    }

}

person Jigar    schedule 01.04.2014    source источник
comment
Привет, почему вы используете System.exit (0); можно удалить, а потом попробовать.   -  person MPG    schedule 11.03.2016
comment
Вместо того, чтобы показывать тост, можете ли вы попробовать распечатать журнал и посмотреть, работает ли он даже после выхода из приложения.   -  person Ruchira Randana    schedule 11.03.2016


Ответы (3)


В методе onStartCommand() службы верните START_STICKY. Служба будет продолжать работать до тех пор, пока вы явно не вызовете stopSelf() в службе или не вызовете stopService() из своей операции.

person elmorabea    schedule 01.04.2014
comment
В методе onStartCommand () службы, если я использую START_STICKY, тогда, если я нажму кнопку возврата и снова запущу приложение, оно запустит таймер с 00:00:00. Но я хочу, чтобы мой таймер работал непрерывно, пока я не нажму кнопку остановки таймера. - person Jigar; 01.04.2014
comment
START_STICKY создает новый таймер с 00:00:00 каждый раз, когда я перезапускаю свое приложение, вместо непрерывного таймера - person Jigar; 01.04.2014
comment
Похоже, что метод onCreate () вашего приложения запускает вашу службу снова каждый раз, вы можете иметь логическое значение в службе, чтобы указать, работает она или нет ... если она работает, не запускайте счетчик - person elmorabea; 01.04.2014

Попробуйте реализовать службу переднего плана. служба переднего плана

Служба переднего плана отображает уведомление и никогда не останавливается.

Реализуйте этот фрагмент кода в onCreate () вашей службы.

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
person Adhikari Bishwash    schedule 01.04.2014
comment
Я могу поставить задачу уведомления на передний план, но я хочу, чтобы мой таймер продолжал работать, пока я не нажму кнопку таймера остановки. Я хочу сказать, что я должен получать уведомление, когда моя строка таймера 00:00:15, и мой таймер должен продолжать работать всякий раз, когда я перезапускаю свое приложение, которое было убито нажатием кнопки возврата - person Jigar; 01.04.2014
comment
вы можете запустить свой таймер в классе обслуживания, чтобы он не останавливался, когда вы вернетесь. И когда будет нажата кнопка, остановите вашу службу. - person Adhikari Bishwash; 01.04.2014
comment
Мой таймер работает в самом классе обслуживания. просто проверьте код еще раз - person Jigar; 01.04.2014
comment
Я имею в виду, что если вы показываете простое уведомление в onCreate () службы, а затем используете фрагмент кода выше, ваша служба не будет убита. - person Adhikari Bishwash; 01.04.2014

Это работает для меня:

notifyIntent.setAction(Intent.ACTION_MAIN);
notifyIntent.addCategory(Intent.CATEGORY_LAUNCHER);
person Khushbu Sharma    schedule 11.03.2016