Android - запуск службы во время загрузки

109

Мне нужно запустить службу во время загрузки. Я много искал. Они говорят о Broadcastreceiver. Поскольку я новичок в разработке Android, у меня не было четкого представления об услугах на Android. Пожалуйста, предоставьте некоторый исходный код.

Хариш
источник
25
@ user244540: Пожалуйста, не «запускайте службу во время загрузки» с намерением, чтобы она работала вечно, если только она не доставляет значения постоянно (например, клиент VOIP). В таких случаях используйте startForeground()в своем сервисе. В противном случае Android и его пользователи убьют ваш сервис как пустую трату места, и вы получите неприятные комментарии в Android Market. В большинстве ситуаций, когда вы думаете, что хотите, чтобы служба запускалась во время загрузки, вам лучше использовать, AlarmManagerчтобы ваша служба могла запускаться периодически, а не постоянно .
CommonsWare
2
@CommonsWare: Хороший момент. Однако обратите внимание, что для запуска периодических запусков AlarmManagerпосле перезапуска вам необходимо выполнить очень похожие шаги (разница заключается в содержимомonReceive метода)
умолчанию
1
@CommonsWare: Очень хороший комментарий, я наткнулся на этот вопрос, и ваш намек точно соответствует моей ситуации. Если бы это был ответ, я бы проголосовал за него :-)
chiccodoro

Ответы:

95

Создайте BroadcastReceiverи зарегистрируйте его, чтобы получить ACTION_BOOT_COMPLETED . Вам также понадобится RECEIVE_BOOT_COMPLETED разрешение .

Читайте: Прослушивание и трансляция глобальных сообщений, а также установка сигналов тревоги

Петр Кнего
источник
2
как насчет блокировки пробуждения? пока служба запускается, устройство может решить перейти в
режим
Нужно ли мне загружать свой мобильный телефон хотя бы один раз, чтобы запустить службу?
pathe.kiran
@ MarianPaździoch прав; вам нужен wake lock. См. Мой ответ ниже: stackoverflow.com/a/30970167/473201
phreakhead
@ pathe.kiran при загрузке, да. См. Commonsware.com/blog/2011/07/05/boot-completed-regression.html
Тим,
Ваш последний URL-адрес устарел
Prizoff
192

Ваш приемник:

public class MyReceiver extends BroadcastReceiver {   

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

     Intent myIntent = new Intent(context, YourService.class);
     context.startService(myIntent);

    }
}

Ваш AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.broadcast.receiver.example"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">

        <activity android:name=".BR_Example"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    <!-- Declaring broadcast receiver for BOOT_COMPLETED event. -->
        <receiver android:name=".MyReceiver" android:enabled="true" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

    </application>

    <!-- Adding the permission -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

</manifest>
Владимир Иванов
источник
5
Ссылка на статью мертва, но пример кода - это все, что вам нужно, так что +1 :)
Alex
3
На самом деле, это нуждается в небольшом улучшении, вы должны использовать wakelock в приемнике, иначе есть небольшая вероятность, что ваша служба не запустится.
Владимир Иванов
Нужно ли мне загружать свой мобильный телефон хотя бы один раз, чтобы эта работа заработала?
pathe.kiran
1
Нет, но вы должны запустить хотя бы одно приложение с android 3.0
Владимир Иванов
Работает ли это, если приложение принудительно закрыто из настроек? Будет ли приложение просыпаться?
Шрихари Карант
32

Можно зарегистрировать собственную службу приложения для автоматического запуска при загрузке устройства. Это необходимо, например, когда вы хотите получать push-события от http-сервера и хотите информировать пользователя, как только произойдет новое событие. Пользователю не нужно запускать действие вручную до запуска службы ...

Все очень просто. Сначала дайте своему приложению разрешение RECEIVE_BOOT_COMPLETED. Далее вам нужно зарегистрировать BroadcastReveiver. Мы называем это BootCompletedIntentReceiver.

Теперь ваш Manifest.xml должен выглядеть так:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.jjoe64">
 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
 <application>
  <receiver android:name=".BootCompletedIntentReceiver">
   <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
   </intent-filter>
  </receiver>
  <service android:name=".BackgroundService"/>
 </application>
</manifest>

В качестве последнего шага вы должны реализовать Receiver. Этот приемник просто запускает вашу фоновую службу.

package com.jjoe64;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.jjoe64.BackgroundService;

public class BootCompletedIntentReceiver extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
  if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
   Intent pushIntent = new Intent(context, BackgroundService.class);
   context.startService(pushIntent);
  }
 }
}

С http://www.jjoe64.com/2011/06/autostart-service-on-device-boot.html

appsthatmatter
источник
3
То же, что и выше, но очень просто и быстро, используйте это, если вы зашли на этот пост.
dbkoren
Единственное различие состоит в том, что в Манифесте декларируется Служба, что верно.
Хоакин Юрчук
Заявить о своей услуге в манифесте не только правильно, это необходимо. То же, что и с мероприятиями
Тим
Где основная деятельность !? Неправильно делать приложение без активностей или android.intent.category.LAUNCHER!
ник
@ L'Esperanza наверняка, у вас могут быть приложения, в которых нет видимой активности!
appsthatmatter
15

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

Поскольку WakefulBroadcastReceiver устарел в api 26, он рекомендуется для уровней API ниже 26

Вам нужно получить блокировку следа. К счастью, библиотека поддержки дает нам класс для этого:

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Intent service = new Intent(context, SimpleWakefulService.class);

        // Start the service, keeping the device awake while it is launching.
        Log.i("SimpleWakefulReceiver", "Starting service @ " + SystemClock.elapsedRealtime());
        startWakefulService(context, service);
    }
}

затем в вашем Сервисе не забудьте снять блокировку пробуждения:

    @Override
    protected void onHandleIntent(Intent intent) {
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  We can do whatever we need to here and then tell it that
        // it can release the wakelock.

...
        Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }

Не забудьте добавить разрешение WAKE_LOCK и зарегистрировать получатель в манифесте:

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

...

<service android:name=".SimpleWakefulReceiver">
    <intent-filter>
        <action android:name="com.example.SimpleWakefulReceiver"/>
    </intent-filter>
</service>
phreakhead
источник
1
В файле манифеста SimpleWakefulReceiver не является службой.
Десмонд Луа
1
WakefulBroadcastReceiver устарел
Амин Пинджари
5

вы должны зарегистрироваться как для BOOT_COMPLETE, так и для REBOOT

<receiver android:name=".Services.BootComplete">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.REBOOT"/>
        </intent-filter>
    </receiver> 
Раафат Альхмиди
источник
2
В литературе говорится, что android.intent.action.REBOOT может использоваться только привилегированным приложением / кодом. Какое в этом преимущество иначе?
XMAN
1

Также зарегистрируйте созданный вами сервис в манифесте и используйте права доступа как

<application ...>
   <service android:name=".MyBroadcastReceiver">
        <intent-filter>
            <action android:name="com.example.MyBroadcastReciver"/>
        </intent-filter>
   </service>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

а затем в braod cast Reciever позвоните в вашу службу

public class MyBroadcastReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Intent myIntent = new Intent(context, MyService.class);
        context.startService(myIntent);
    }
}
SoftEye
источник
Почему фильтр намерений внутри службы?
Хоакин Юрчук
потому что когда загрузка завершится, MyService будет вызван
SoftEye
В этом случае ваш класс обслуживания расширит сервис и широковещательный приемник. Я прав?
Хоакин Юрчук
Класс расширит класс обслуживания.
SoftEye
2
Здесь что-то не так. Предполагается, что услуга вызывается из приемника вещания. Но вы говорите, что ваш сервис - это широковещательный приемник, и после этого вы говорите мне, что класс обслуживания не расширяет широковещательный приемник. Таким образом, он не получит широковещательную передачу о завершении загрузки. Что вы переопределяете при объявлении метода onReceive?
Хоакин Юрчук 06
0

Сначала зарегистрируйте получатель в файле manifest.xml:

    <receiver android:name="com.mileagelog.service.Broadcast_PowerUp" >
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
        </intent-filter>
    </receiver>

а затем напишите трансляцию для этого приемника, например:

public class Broadcast_PowerUp extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();

    if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
        Toast.makeText(context, "Service_PowerUp Started",
                Toast.LENGTH_LONG).show();


    } else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {



        Toast.makeText(context, "Service_PowerUp Stoped", Toast.LENGTH_LONG)
        .show();
    }
  }
}
Манодж Таркар
источник
0

Чтобы перезапустить службу в Android Oили более, т.е. OS> 28 Используйте этот код KOTLIN VERSION 1) Добавьте разрешение в манифест

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

2) Создайте Classи расширите его с помощьюBroadcastReceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.content.ContextCompat



class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, arg1: Intent?) {
        Log.d("BootCompletedReceiver", "starting service...")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ContextCompat.startForegroundService(context, Intent(context, YourServiceClass::class.java))
        } else {
            context.startService(Intent(context, YourServiceClass::class.java))
        }
    }
}

3) Объявите в файле манифеста, подобном этому, в теге приложения

<receiver android:name=".utils.BootCompletedReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>
Способный ученик
источник
-1

Пожалуйста, проверьте JobScheduler на предмет API выше 26

WakeLock был лучшим вариантом для этого, но он устарел на уровне api 26. Пожалуйста, проверьте эту ссылку, если вы считаете, что уровни api выше 26
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html# startWakefulService (android.content.Context,% 20android.content.Intent)

Это говорит

Начиная с Android O, ограничения на проверку данных делают этот класс более бесполезным. (Как правило, запускать службу после получения широковещательной передачи небезопасно, потому что у вас нет никаких гарантий, что ваше приложение находится на переднем плане в этот момент и, следовательно, ему разрешено это делать.) Вместо этого разработчики должны использовать android. app.job.JobScheduler, чтобы запланировать задание, и это не требует, чтобы приложение удерживало блокировку пробуждения при этом (система позаботится о блокировке пробуждения для задания).

так как он говорит cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

если он должен что-то сделать, а не начать и сохранить его, вы можете получить широковещательную передачу ACTION_BOOT_COMPLETED

Если речь не идет о переднем плане, пожалуйста, проверьте, может ли служба доступности

другой вариант - запустить действие из широковещательного приемника и завершить его после запуска службы в onCreate (), поскольку более новые версии Android не позволяют запускать службы из приемников

Суровый
источник