Android -Starting Service at Boot Time


109

ฉันต้องเริ่มบริการในเวลาบูต ฉันค้นหามาก พวกเขากำลังพูดถึง Broadcastreceiver เนื่องจากฉันยังใหม่กับการพัฒนา Android ฉันไม่ได้รับภาพที่ชัดเจนเกี่ยวกับบริการบน Android โปรดระบุซอร์สโค้ด


25
@ user244540: โปรดอย่า "เริ่มบริการในเวลาบูต" โดยตั้งใจให้บริการทำงานตลอดไปเว้นแต่จะมีการส่งมอบคุณค่าอย่างต่อเนื่อง (เช่นไคลเอนต์ VOIP) ในกรณีดังกล่าวให้ใช้startForeground()ในบริการของคุณ มิฉะนั้น Android และผู้ใช้จะฆ่าบริการของคุณเนื่องจากเป็นการสิ้นเปลืองพื้นที่และคุณจะได้รับความคิดเห็นที่ไม่พึงประสงค์ใน Android Market สถานการณ์ส่วนใหญ่ที่คุณคิดว่าคุณต้องการบริการที่จะเริ่มต้นในเวลาบูตคุณจะได้บริการที่ดีขึ้นโดยใช้AlarmManagerเพื่อให้บริการของคุณสามารถทำงานเป็นระยะ ๆมากกว่าอย่างต่อเนื่อง
CommonsWare

2
@CommonsWare: จุดดี อย่างไรก็ตามโปรดทราบว่าในการเริ่มการทำงานเป็นระยะโดยAlarmManagerหลังจากรีสตาร์ทคุณต้องทำตามขั้นตอนที่คล้ายกันมาก (ความแตกต่างที่อยู่ในเนื้อหาของonReceiveวิธีการ)
แตน

1
@CommonsWare: ความคิดเห็นที่ดีมากฉันเจอคำถามนี้และคำใบ้ของคุณตรงกับสถานการณ์ของฉัน ถ้าเป็นคำตอบฉันจะโหวตให้ :-)
chiccodoro

คำตอบ:


96

สร้างBroadcastReceiverและลงทะเบียนจะได้รับACTION_BOOT_COMPLETED คุณต้องได้รับอนุญาตRECEIVE_BOOT_COMPLETEDด้วย

อ่าน: การฟังและการเผยแพร่ข้อความส่วนกลาง และการตั้งค่าการเตือน


2
Wake Lock ล่ะ ในขณะที่กำลังเริ่มบริการอุปกรณ์อาจตัดสินใจเข้าสู่
โหมดสลีป

ฉันต้องบูตมือถืออย่างน้อยหนึ่งครั้งเพื่อเริ่มบริการหรือไม่?
pathe.kiran

@ MarianPaździochถูกแล้ว; คุณต้องล็อคปลุก ดูคำตอบของฉันด้านล่าง: stackoverflow.com/a/30970167/473201
phreakhead

@ pathe.kiran ในการบูตใช่ ดูcommonsware.com/blog/2011/07/05/boot-completed-regression.html
Tim

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 ในเครื่องรับมิฉะนั้นจะมีโอกาสเล็กน้อยที่บริการของคุณจะไม่เริ่มต้น
Vladimir Ivanov

ฉันต้องบูตมือถืออย่างน้อยหนึ่งครั้งเพื่อให้ใช้งานได้หรือไม่?
pathe.kiran

1
ไม่ แต่คุณต้องเรียกใช้แอปพลิเคชันอย่างน้อยหนึ่งแอปตั้งแต่ android 3.0
Vladimir Ivanov

จะได้ผลหรือไม่หากบังคับปิดแอปจากการตั้งค่า แอปจะยังคงปลุกอยู่หรือไม่
Srihari Karanth

32

เป็นไปได้ที่จะลงทะเบียนบริการแอปพลิเคชันของคุณเองเพื่อเริ่มต้นโดยอัตโนมัติเมื่อบูตอุปกรณ์แล้ว ตัวอย่างเช่นคุณต้องการสิ่งนี้เมื่อคุณต้องการรับเหตุการณ์พุชจากเซิร์ฟเวอร์ 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

ข้อแตกต่างเพียงอย่างเดียวคือการประกาศบริการในรายการซึ่งถูกต้อง
Joaquin Iurchuk

การประกาศบริการของคุณในไฟล์ Manifest ไม่ถูกต้องเท่านั้น แต่ยังจำเป็นต้องมี เช่นเดียวกับกิจกรรม
Tim

กิจกรรมหลักอยู่ที่ไหน!? ไม่ถูกต้องหากจะสร้างแอปโดยไม่มีกิจกรรมหรือandroid.intent.category.LAUNCHER!
ชื่อเล่น

@ L'Esperanza แน่นอนคุณสามารถมีแอพที่ไม่มีกิจกรรมที่มองเห็นได้!
appsthatmatter

15

โซลูชันส่วนใหญ่ที่โพสต์ไว้ที่นี่ขาดส่วนสำคัญ: การทำโดยไม่ล็อกการปลุกจะเสี่ยงต่อการที่บริการของคุณจะถูกฆ่าก่อนที่จะดำเนินการเสร็จสิ้น เห็นวิธีแก้ปัญหานี้ในกระทู้อื่นตอบที่นี่เช่นกัน

เนื่องจากWakefulBroadcastReceiverเลิกใช้งานแล้วใน api 26 จึงขอแนะนำ สำหรับระดับ API ที่ต่ำกว่า 26

คุณต้องได้รับ Wake Lock โชคดีที่ไลบรารี Support ให้ชั้นเรียนทำสิ่งนี้:

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 ไม่ใช่บริการ
Desmond Lua

1
WakefulBroadcastReceiver เลิกใช้แล้ว
Amin Pinjari

5

คุณควรลงทะเบียน BOOT_COMPLETE และรีบูต

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

จากนั้นใน 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);
    }
}

ทำไมต้องใช้ Intent Filter ภายในบริการ
Joaquin Iurchuk

เพราะเมื่อบูตเสร็จแล้ว MyService จะถูกเรียกว่า
SoftEye

ในกรณีนั้นชั้นบริการของคุณจะขยายบริการและเครื่องรับสัญญาณออกอากาศ ฉันถูกไหม?
Joaquin Iurchuk

ชั้นเรียนจะขยายชั้นบริการ
SoftEye

2
มีบางอย่างผิดปกติที่นี่ ควรเรียกใช้บริการจากเครื่องรับสัญญาณออกอากาศ แต่คุณกำลังบอกว่าบริการของคุณคือเครื่องรับสัญญาณออกอากาศและหลังจากนั้นคุณก็บอกฉันว่าชั้นบริการไม่ขยายตัวรับสัญญาณออกอากาศ ดังนั้นจะไม่ได้รับการออกอากาศที่เสร็จสมบูรณ์ของการบูต คุณกำลังลบล้างอะไรเมื่อคุณประกาศเมธอด onReceive?
Joaquin Iurchuk

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 OOS> 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เพื่อกำหนดเวลางานและสิ่งนี้ไม่จำเป็นต้องให้แอปล็อคการปลุกขณะดำเนินการ (ระบบจะดูแลการล็อกการปลุกสำหรับงาน)

อย่างที่บอก cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

หากต้องทำอะไรบางอย่างมากกว่าที่จะเริ่มต้นและรักษาไว้คุณสามารถรับการออกอากาศ ACTION_BOOT_COMPLETED

หากไม่เกี่ยวกับเบื้องหน้าโปรดตรวจสอบว่าบริการการเข้าถึงสามารถทำได้หรือไม่

อีกทางเลือกหนึ่งคือการเริ่มต้นกิจกรรมจากเครื่องรับสัญญาณออกอากาศและเสร็จสิ้นหลังจากเริ่มบริการภายใน onCreate () เนื่องจาก Android เวอร์ชันใหม่กว่าไม่อนุญาตให้เริ่มบริการจากเครื่องรับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.