Android - Служба запуску під час завантаження


109

Мені потрібно запустити послугу під час завантаження. Я багато шукав. Вони говорять про Broadcastreceiver. Оскільки я новачок у розробці андроїдів, я не отримав чіткого уявлення про сервіси на 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 має рацію; вам потрібен замок для неспання. Дивіться мою відповідь нижче: 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
Насправді це потребує незначного вдосконалення, ви повинні використовувати функцію "зворотній будинок" у приймачі, інакше є невеликий шанс, що ваша послуга не запускається.
Володимир Іванов

Чи потрібно мені хоча б раз завантажувати мобільний телефон, щоб зробити цю роботу ??
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>

В якості останнього кроку вам належить реалізувати приймач. Цей приймач тільки починає ваш фоновий сервіс.

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


3
Як і вище, але дуже просто і швидко, використовуйте цей, якщо ви приїжджаєте по цій публікації.
dbkoren

Єдина відмінність полягає в тому, що це оголошує Сервіс на Маніфесті, що є правильним.
Хоакін Юрчук

Не лише правильно заявляти про свою послугу в маніфесті, це потрібно. Те саме, що і з діяльністю
Тім

Де основна діяльність !? Неправильно робити додаток без діяльності або android.intent.category.LAUNCHER!
псевдонім

@ L'Esperanza точно, ви можете мати програми, які не мають видимих ​​дій!
appsthatmatter

15

У більшості розміщених тут рішень пропущено важливий фрагмент: виконувати це без блокування блокування, це ризикує вбити Вашу Службу до її завершення. Побачили це рішення в іншій нитці, відповідаючи і тут.

Оскільки в WaifulBroadcastReceiver застаріло в 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>

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

Також зареєструйте створену послугу в Manifest і використовуйте дозвіл як

<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"/>

а потім в браді віддавав Reciever зателефонуйте до вашої служби

public class MyBroadcastReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Intent myIntent = new Intent(context, MyService.class);
        context.startService(myIntent);
    }
}

Чому фільтр намірів всередині послуги?
Хоакін Юрчук

тому що, коли завантаження завершиться, тоді MyService буде називатися
SoftEye

У такому випадку ваш клас обслуговування поширить послугу та трансляцію приймача. Маю рацію?
Хоакін Юрчук

Клас буде розширювати клас обслуговування.
SoftEye

2
Тут щось не так. Службу, як передбачається, дзвонять із приймача мовлення. Але ви говорите, що ваша послуга є приймачем широкомовної передачі, і після цього ви кажете мені, що клас обслуговування не поширює приймач широкомовної передачі. Таким чином, він не отримає завершений завантаження завантаження. Що ви переважаєте, коли оголошуєте метод onReceive?
Хоакін Юрчук

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або більше, тобто ОС> 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) Заявіть у такому файлі Manifest як тег програми

<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 на apis вище 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 планує роботу, і це не вимагає, щоб програма тримала функцію блокування будильника, роблячи це (система піклується про те, щоб увімкнути функцію замикання на роботу).

так що, як йдеться, косидер JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

якщо це зробити щось, ніж почати і зберегти це, ви можете отримувати трансляцію ACTION_BOOT_COMPLETED

Якщо мова йде не про pls переднього плану, перевірте, чи може послуга доступності

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.