Dịch vụ khởi động Android lúc khởi động


109

Tôi cần bắt đầu một dịch vụ tại thời điểm khởi động. Tôi đã tìm kiếm rất nhiều. Họ đang nói về Broadcastreceiver. Vì tôi chưa quen với việc phát triển Android nên tôi chưa hiểu rõ về các dịch vụ trên Android. Vui lòng cung cấp một số mã nguồn.


25
@ user244540: Vui lòng không "bắt đầu một dịch vụ tại thời điểm khởi động" với ý định để nó chạy mãi mãi, trừ khi nó liên tục cung cấp giá trị (ví dụ: một ứng dụng khách VOIP). Trong những trường hợp đó, hãy sử dụng startForeground()dịch vụ của bạn. Nếu không, Android và người dùng của nó sẽ giết chết dịch vụ của bạn vì lãng phí dung lượng và bạn sẽ nhận được một số nhận xét khó chịu trong Android Market. Hầu hết các tình huống mà bạn nghĩ rằng bạn muốn một dịch vụ bắt đầu lúc khởi động, bạn được phục vụ tốt hơn khi sử dụng AlarmManagerđể dịch vụ của bạn có thể chạy định kỳ thay vì liên tục .
CommonsWare

2
@CommonsWare: Điểm tốt. Tuy nhiên, lưu ý rằng để bắt đầu chạy định kỳ AlarmManagersau khi khởi động lại, bạn cần phải làm theo các bước rất giống nhau (sự khác biệt nằm ở nội dung của onReceivephương pháp)
stanwise

1
@CommonsWare: Nhận xét rất hay, tôi tình cờ gặp câu hỏi này và gợi ý của bạn chính xác phù hợp với tình huống của tôi. Nếu đó là một câu trả lời tôi sẽ bình chọn nó lên :-)
chiccodoro

Câu trả lời:


95

2
còn khóa thức thì sao? trong khi dịch vụ đã được bắt đầu các thiết bị có thể quyết định đi ngủ ...
Marian Paździoch

Tôi có cần khởi động điện thoại di động của mình ít nhất một lần để bắt đầu dịch vụ không ??
pathe.kiran

@ MarianPaździoch nói đúng; bạn cần một khóa đánh thức. Xem câu trả lời của tôi dưới đây: stackoverflow.com/a/30970167/473201
phreakhead

@ pathe.kiran khi khởi động, vâng. Xem commonsware.com/blog/2011/07/05/boot-completed-regression.html
Tim

URL mới nhất của bạn đã lỗi thời
Prizoff

192

Người nhận của bạn:

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 của bạn:

<?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
Các liên kết đến bài viết là chết nhưng mã mẫu là tất cả các bạn cần anyway, do đó 1 :)
Alex

3
Trên thực tế, nó cần cải thiện một chút, bạn phải sử dụng wakelock trong bộ thu, nếu không sẽ có một chút khả năng dịch vụ của bạn không bắt đầu.
Vladimir Ivanov

Tôi có cần khởi động điện thoại di động của mình ít nhất một lần để làm việc này không ??
pathe.kiran

1
Nope, nhưng bạn phải chạy các ứng dụng ít nhất một từ android 3.0
Vladimir Ivanov

Điều này có hoạt động nếu ứng dụng bị buộc đóng khỏi cài đặt không? Ứng dụng vẫn sẽ thức dậy chứ?
Srihari Karanth

32

Có thể đăng ký dịch vụ ứng dụng của riêng bạn để tự động khởi động khi thiết bị đã được khởi động. Ví dụ, bạn cần điều này khi bạn muốn nhận các sự kiện đẩy từ máy chủ http và muốn thông báo cho người dùng ngay khi sự kiện mới xảy ra. Người dùng không phải bắt đầu hoạt động theo cách thủ công trước khi dịch vụ bắt đầu ...

Nó khá đơn giản. Trước tiên, hãy cấp cho ứng dụng của bạn quyền RECEIVE_BOOT_COMPLETED. Tiếp theo, bạn cần đăng ký BroadcastReveiver. Chúng tôi gọi nó là BootCompletedIntentReceiver.

Manifest.xml của bạn bây giờ sẽ trông giống như sau:

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

Bước cuối cùng bạn phải triển khai Bộ thu. Bộ thu này chỉ bắt đầu dịch vụ nền của bạn.

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);
  }
 }
}

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


3
Tương tự như trên nhưng thực sự đơn giản và nhanh chóng, hãy sử dụng cái này nếu bạn đến qua bài viết này.
dbkoren

Sự khác biệt duy nhất là điều này khai báo Dịch vụ trên Tệp kê khai, điều này là chính xác.
Joaquin Iurchuk

Việc khai báo dịch vụ của bạn trong bản kê khai không chỉ đúng mà còn bắt buộc phải có. Tương tự với các hoạt động
Tim

Hoạt động chính ở đâu !? Không đúng khi tạo ứng dụng mà không có hoạt động hoặc android.intent.category.LAUNCHER!
nick

@ L'Esperanza chắc chắn, bạn có thể có các ứng dụng không có hoạt động hiển thị!
appsthatmatter

15

Hầu hết các giải pháp được đăng ở đây đều thiếu một phần quan trọng: làm điều đó mà không có khóa đánh thức có nguy cơ Dịch vụ của bạn bị giết trước khi xử lý xong. Xem giải pháp này trong một chủ đề khác, trả lời ở đây.

WakefulBroadcastReceiver không được dùng nữa trong api 26 nên bạn nên sử dụng các Cấp API dưới 26

Bạn cần phải có khóa đánh thức. May mắn thay, thư viện Hỗ trợ cung cấp cho chúng tôi một lớp học để làm điều này:

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);
    }
}

sau đó, trong Dịch vụ của bạn, hãy đảm bảo mở khóa đánh thức:

    @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);
    }

Đừng quên thêm quyền WAKE_LOCK và đăng ký bộ thu của bạn trong tệp kê khai:

<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
Trong tệp kê khai, SimpleWakefulReceiver không phải là một dịch vụ.
Desmond Lua

1
WakefulBroadcastReceiver bị phản đối
Amin Pinjari

5

bạn nên đăng ký BOOT_COMPLETE cũng như 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
Văn học nói rằng 'android.intent.action.REBOOT' chỉ có thể được sử dụng bởi ứng dụng / mã đặc quyền. Điều này có lợi gì khác?
XMAN

1

Đồng thời đăng ký dịch vụ đã tạo của bạn trong Tệp kê khai và sử dụng quyền với tư cách

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

và sau đó trong braod cast Reciever gọi dịch vụ của bạn

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

Tại sao Bộ lọc Ý định bên trong dịch vụ?
Joaquin Iurchuk

bởi vì khi khởi động hoàn tất thì MyService sẽ được gọi
SoftEye

Trong trường hợp đó, hạng dịch vụ của bạn sẽ mở rộng dịch vụ và bộ thu phát sóng. Tôi nói đúng chứ?
Joaquin Iurchuk

Lớp sẽ mở rộng lớp Dịch vụ.
SoftEye

2
Có gì đó không ổn ở đây. Dịch vụ được cho là được gọi từ Bộ thu phát sóng. Nhưng bạn đang nói rằng dịch vụ của bạn là bộ thu phát sóng và sau đó bạn nói với tôi rằng lớp dịch vụ không mở rộng Bộ thu phát sóng. Do đó, nó sẽ không nhận được chương trình phát sóng đã hoàn thành khởi động. Bạn đang ghi đè điều gì khi khai báo phương thức onReceive?
Joaquin Iurchuk

0

Trước tiên, hãy đăng ký một bộ nhận trong tệp manifest.xml của bạn:

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

và sau đó viết một chương trình phát sóng cho bộ thu này như:

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

Để khởi động lại dịch vụ trong Android Ohoặc hơn thế, tức là OS> 28 Sử dụng mã này KOTLIN VERSION 1) Thêm quyền trong tệp kê khai

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

2) Tạo Classvà mở rộng nó vớiBroadcastReceiver

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) Khai báo trong tệp Manifest như thế này dưới thẻ ứng dụng

<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

Vui lòng kiểm tra JobScheduler cho apis trên 26

WakeLock là lựa chọn tốt nhất cho việc này nhưng nó không được chấp nhận ở api cấp 26. Vui lòng kiểm tra liên kết này nếu bạn cho rằng cấp api trên 26
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html# startWakefulService (android.content.Context,% 20android.content.Intent)

Nó nói rằng

Kể từ Android O, các hạn chế kiểm tra nền khiến lớp này nói chung không còn hữu ích nữa. (Nói chung là không an toàn khi bắt đầu một dịch vụ từ khi nhận được chương trình phát sóng, bởi vì bạn không có bất kỳ đảm bảo nào rằng ứng dụng của bạn đang ở nền trước và do đó được phép làm như vậy.) Thay vào đó, các nhà phát triển nên sử dụng android. app.job.JobScheduler để lên lịch công việc và điều này không yêu cầu ứng dụng phải giữ khóa đánh thức trong khi làm như vậy (hệ thống sẽ đảm nhận việc giữ khóa thức cho công việc).

như nó nói cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

nếu bạn phải làm điều gì đó hơn là bắt đầu và giữ nó, bạn có thể nhận được ACTION_BOOT_COMPLETED phát sóng

Nếu nó không phải về nền trước, xin hãy kiểm tra xem dịch vụ Trợ năng có thể làm được không

một tùy chọn khác là bắt đầu một hoạt động từ bộ thu phát sóng và kết thúc nó sau khi bắt đầu dịch vụ trong onCreate (), vì các phiên bản android mới hơn không cho phép bắt đầu dịch vụ từ bộ thu

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.