Android-在启动时启动服务


109

我需要在启动时启动服务。我搜了很多。他们正在谈论Broadcastreceiver。由于我是android开发的新手,所以我对Android的服务一无所知。请提供一些源代码。


25
@ user244540:请不要“在启动时启动服务”以使其永远运行,除非该服务正在不断传递价值(例如VOIP客户端)。在这种情况下,请startForeground()在您的服务中使用。否则,Android及其用户会因为浪费空间而终止您的服务,并且您会在Android Market中收到一些不愉快的评论。在大多数情况下,您认为希望服务在引导时启动,最好使用来AlarmManager服务,以便服务可以定期运行而不是连续运行。
CommonsWare 2010年

2
@CommonsWare:好点。但是请注意,要通过AlarmManager重新启动后开始定期运行,您需要遵循非常相似的步骤(区别在于onReceive方法的内容)
不变,2012年

1
@CommonsWare:非常好的评论,我偶然发现了这个问题,您的提示完全符合我的情况。如果是答案,我会投票赞成:-)
chiccodoro

Answers:


95

2
那唤醒锁呢?当服务开始时,设备可能会决定要入睡...
MarianPaździoch2015年

我需要至少启动一次手机才能启动服务吗?
pathe.kiran 2015年

@MarianPaździoch是正确的;您需要唤醒锁。请参阅下面的答案:stackoverflow.com/a/30970167/473201
phreakhead 2015年


您最新的网址已过时
Prizoff '17

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

1
不会,但是您必须自android 3.0起至少运行一个应用程序
Vladimir Ivanov 2015年

如果从设置中强制关闭了应用程序,这是否可行?该应用程序仍会唤醒吗?
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>

作为最后一步,您必须实现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


3
与上述相同,但确实非常简单快捷,如果您来自这篇文章,请使用此内容。
dbkoren

唯一的不同是,这声明了清单上的服务,这是正确的。
Joaquin Iurchuk 2015年

在清单中声明您的服务不仅是正确的,而且是必需的。与活动相同
蒂姆

主要活动在哪里!制作没有活动的应用程序是不正确的android.intent.category.LAUNCHER
尼克

@ L'Esperanza当然,您可以使用没有可见活动的应用程序!
appsthatmatter 2016年

15

此处发布的大多数解决方案都缺少重要的一环:在没有唤醒锁的情况下执行此操作可能会导致服务在完成处理之前被杀死。在另一个线程中看到了该解决方案,也在此处回答。

以来 api 26中已弃用WakefulBroadcastReceiver,因此建议 将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不是服务。
Desmond Lua

1
不推荐使用WakefulBroadcastReceiver
Amin

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

然后在大声疾呼中接收人致电您的服务

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

为什么在服务内部使用Intent筛选器?
Joaquin Iurchuk

因为当启动完成后,将调用MyService
SoftEye

在这种情况下,您的服务类别将扩展服务和广播接收器。我对吗?
Joaquin Iurchuk 2015年

该类将扩展Service类。
SoftEye

2
这里出事了 该服务应该从广播接收器中调用。但是,您是说您的服务是广播接收器,然后您告诉我服务类不会扩展广播接收器。因此,它将不会收到引导完成广播。声明onReceive方法时,您要重写的内容是什么?
Joaquin Iurchuk'3

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是否有26以上的api

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版本不允许从接收器启动服务

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.