Подтвердить что ты не робот

Как мы можем запретить Службе убивать ОС?

Я использую Service в своем приложении и должен запускаться до тех пор, пока мое приложение не будет удалено, но проблема в том, что он уничтожается ОС.

Как мы можем предотвратить его уничтожение ОС? Или, если он будет убит, мы снова перезапустим эту службу программным путем?

4b9b3361

Ответ 1

Вы можете запустить службу в foreground, используя startForeground ( ).

Служба переднего плана - это сервис, который считается чем-то пользователь активно осознает и, следовательно, не является кандидатом на систему чтобы убить при низкой памяти.

Но имейте в виду, что служба переднего плана должна предоставлять уведомление для строки состояния (читать здесь) и что уведомление не может быть отклонено, если служба не является остановлен или удален с переднего плана.

Примечание. Это все еще не гарантирует, что служба не будет убита при чрезвычайно низких условиях памяти. Это лишь уменьшает вероятность его убийства.

Ответ 2

Я был озадачен той же самой проблемой для вас недавно. Но теперь я нашел хорошее решение. Прежде всего, вы должны знать, что даже ваша служба была убита ОС, метод onCreate вашей службы будет вызываться ОС за короткое время. Итак, вы можете использовать метод onCreate следующим образом:

@Override
public void onCreate() {
    Log.d(LOGTAG, "NotificationService.onCreate()...");
    //start this service from another class
    ServiceManager.startService();
}
@Override
public void onStart(Intent intent, int startId) {
    Log.d(LOGTAG, "onStart()...");
    //some code of your service starting,such as establish a connection,create a TimerTask or something else
}

содержимое "ServiceManager.startService()":

public static void startService() {
    Log.i(LOGTAG, "ServiceManager.startSerivce()...");
    Intent intent = new Intent(NotificationService.class.getName());
    context.startService(intent);
}

Однако это решение доступно только для того, чтобы ваша служба была убита GC. Иногда наша служба может быть убита пользователем с помощью Менеджера программ. В этой ситуации ваши пессимисты будут убиты, а ваша служба никогда не будет восстановлена -instantiated.So ваш сервис не может быть перезапущен. Но хорошая новость заключается в том, что, когда премьер-министр убивает вашу службу, он будет вызывать ваш метод onDestroy. Поэтому мы можем что-то сделать с помощью этого метода.

    @Override
public void onDestroy() {
    Intent in = new Intent();
    in.setAction("YouWillNeverKillMe");
    sendBroadcast(in);
    Log.d(LOGTAG, "onDestroy()...");
}

Строка "YouWillNeverKillMe" - это обычное действие. Самое главное в этом методе - не добавлять код перед отправкой трансляции. Поскольку система не будет ждать завершения onDestroy(), вы должны отправить рассылку как можно скорее. Затем зарегистрируйте приемник в файле manifestast.xml:

<receiver android:name=".app.ServiceDestroyReceiver" >
        <intent-filter>
            <action android:name="YouWillNeverKillMe" >
            </action>
        </intent-filter>
    </receiver>

Наконец, создайте BroadcastReceiver и запустите службу в методе onReceive:

@Override
public void onReceive(Context context, Intent intent) {
    Log.d(LOGTAG, "ServeiceDestroy onReceive...");
    Log.d(LOGTAG, "action:" + intent.getAction());
    Log.d(LOGTAG, "ServeiceDestroy auto start service...");
    ServiceManager.startService();
}

Надеюсь, это будет полезно для вас, и извините за мой бедный письменный английский.

Ответ 3

Переопределите метод onStartCommand() в своем классе обслуживания и просто верните START_STICKY (как предложено "Не пустым" ). Это все, что вам нужно. Если процесс, выполняющий вашу службу, будет убит (например, при низком уровне памяти), система Android перезапустит его автоматически (обычно с некоторой задержкой, например, 5 секунд).

Не используйте onStart() больше, как предлагается в другом ответе, он устарел.

Ответ 4

использование

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //**Your code **
    // We want this service to continue running until it is explicitly
    // stopped, so return sticky.
    return START_STICKY;
} 

ref Документация жизненный цикл службы.

Изменить добавленный метод.

Ответ 5

Я нашел другое решение проблемы, которое гарантирует, что ваше обслуживание будет всегда живым. В моем случае эта схема также решает проблему с FileObserver, которая перестает работать после некоторого периода времени.

  • Для запуска службы (FileObserverService) в качестве службы Foreground выполните операцию (StartServicesActivity).
  • Используйте класс BroadcastReceiver (в примере CommonReceiver), чтобы перезапустить службу в некоторых особых ситуациях и в случае ее уничтожения.

Я использовал этот код в своем приложении "Автоматически отправлять фотографии по электронной почте" https://play.google.com/store/apps/details?id=com.alexpap.EmailPicturesFree

Вот класс CommonReceiver.

public class CommonReceiver extends BroadcastReceiver {

    public void onReceive(Context paramContext, Intent paramIntent)
    {
        paramContext.startService(new Intent(paramContext, FileObserverService.class));
    }
}

Вот его определение в AndroidManifest.xml непосредственно перед закрытием тега приложения.

<receiver android:name="com.alexpap.services.CommonReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.USER_PRESENT"/>
    </intent-filter>
</receiver>

Запустите службу в деятельности StartServicesActivity.

Intent iFileObserver = new Intent(StartServicesActivity.this, FileObserverService.class);
StartServicesActivity.this.startService(iFileObserver);

Здесь находится метод onStartCommand() службы.

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

    int res = super.onStartCommand(intent, flags, startId);

    /*** Put your code here ***/

    startServiceForeground(intent, flags, startId);

    return Service.START_STICKY;  
}

public int startServiceForeground(Intent intent, int flags, int startId) {

    Intent notificationIntent = new Intent(this, StartServicesActivity.class); 
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this)
        .setContentTitle("File Observer Service")
        .setContentIntent(pendingIntent)
        .setOngoing(true)
            .build();

    startForeground(300, notification);

    return START_STICKY;
}

Я тестировал этот код с помощью приложения Task Killer, и каждый раз, когда служба была убита, он был перезагружен снова почти сразу (выполняет onStartCommand()). Он также перезапускается при каждом включении телефона и после перезагрузки. Я использую этот код в своем приложении, который отправляет вам по электронной почте все изображения, которые вы берете с помощью своего телефона, для предварительного рассылки списка электронных писем. Отправляющее электронное письмо и список получателей электронной почты устанавливаются в другом действии и сохраняются в общих предпочтениях. Я потратил около 100 снимков за несколько часов, и все они были отправлены правильно, чтобы получать электронные письма.

Ответ 6

@Override
public void onDestroy() {

    super.onDestroy();
    startService(new Intent(this, YourService.class));

}

напишите выше код в своей службе, и ваш сервис никогда не остановит даже пользователя, который хочет его уничтожить, или они хотят его убить, он никогда не будет убивать, пока ваше приложение не будет удалено с вашего устройства.

Ответ 7

Вы можете попробовать начать свою службу повторно, например каждые 5 сек. Таким образом, когда ваша служба запущена, она будет выполнять onStartCommand() каждые 5 секунд. Я протестировал эту схему, и она очень надежна, но, к сожалению, она немного увеличивает накладные расходы телефона. Вот код в вашей деятельности, где вы запускаете службу.

Intent iFileObserver = new Intent(StartServicesActivity.this, FileObserverService.class);
PendingIntent pendingIntentFileObserver = PendingIntent.getService(StartServicesActivity.this, 0, iFileObserver, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Date now = new Date();

    //start every 5 seconds
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, now.getTime(), 5*1000, pendingIntentFileObserver);

А вот служба onStartCommand() службы.

//class variable
public static boolean isStarted = false;

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

    int res = super.onStartCommand(intent, flags, startId);

    //check if your service is already started
    if (isStarted){      //yes - do nothing
        return Service.START_STICKY;
    } else {             //no 
        isStarted = true;
    }


    /**** the rest of your code  ***/

    return Service.START_STICKY;

}

Ответ 8

Насколько я знаю, onDestroy() будет вызываться только тогда, когда служба явно остановлена ​​(Force Stop). Но этот метод не будет вызван в случае, если служба будет убита ОС/прокруткой списка Recent Apps. В этих случаях вызывается другой обработчик событий с именем onTaskRemoved(Intent). Это связано с дефектом в Android 4.3-4.4 по ссылке здесь. Попробуйте использовать приведенный ниже код: -

public void onTaskRemoved(Intent intent){
super.onTaskRemoved(intent);
Intent intent=new Intent(this,this.getClass()); 
startService(intent); 
}

Ответ 9

Сначала создайте службу в другом процессе и напишите вещатель, который работает в рекурсии через временные интервалы

protected CountDownTimer rebootService = new CountDownTimer(9000, 9000) {


    @Override
    public void onTick(long millisUntilFinished) {


    }

    @Override
    public void onFinish() {

        sendBroadcast(reboot);
        this.start();
        Log.d(TAG, "rebootService sending PREVENT AUTOREBOT broadcast");


    }

};

После этого регистр широковещательного приемника в основном процессе также с рекурсией таймера, которая запускается после первой трансляции из службы, прибыла

protected static class ServiceAutoRebooter extends BroadcastReceiver {

    private static   ServiceAutoRebooter instance = null;
    private  RebootTimer rebootTimer = null;

    private static ServiceAutoRebooter getInstance() {

        if (instance == null) {

            instance = new ServiceAutoRebooter();

        }
        return instance;

    }





    public class RebootTimer extends CountDownTimer {

        private Context _context;
        private Intent _service;


        public RebootTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }


        @Override
        public void onTick(long millisUntilFinished) {

        }


        @Override
        public void onFinish() {

            _context.startService(_service);
            this.cancel();
            Log.d(TAG, "Service AutoRebooted");


        }


    }


    @Override
    public void onReceive(Context context, Intent intent) {

        if (rebootTimer == null) {
            Log.d(TAG, "rebootTimer == null");

            rebootTimer = new RebootTimer(10000, 10000);
            rebootTimer._context = context;

            Intent service = new Intent(context, SomeService.class);
            rebootTimer._service = service;
            rebootTimer.start();

        } else {

            rebootTimer.cancel();
            rebootTimer.start();
            Log.d(TAG, "rebootTimer is restarted");

        }


    }


}

Служба будет автоматически перезагружена, если время на RebootTimer (основной процесс) истечет, что означает, что передача "ПРЕДОСТЕРЕЖЕНИЕ АВТОРЕФОНА" из службы не прибыла

Ответ 10

Я нашел решение... поздний ответ, но я хотел ответить...

мы можем отправить широковещательную рассылку в ondestroy службы и создать приемник, который получает широковещательную передачу, и снова запускает сервис... когда он уничтожен по каким-либо причинам...

Ответ 11

Попробуйте выполнить следующие действия:

final Messenger mMessenger = new Messenger(new IncomingHandler()); 
class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            default:
                super.handleMessage(msg);
            }
        }
}

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


@Override
public IBinder onBind(Intent arg0) {
    return mMessenger.getBinder();
}


private void makeServiceForeground() {
    IActivityManager am = ActivityManagerNative.getDefault();
    try {
        am.setProcessForeground(onBind(null), android.os.Process.myPid(), true);
    } catch (RemoteException e) {
        Log.e("", "cant set to foreground" + e.toString());
    }
}

также нужно добавить в manifest.xml

<uses-permission android:name="android.permission.SET_PROCESS_LIMIT"/>