【问题标题】:Trying to start a service on boot on Android尝试在 Android 上启动服务
【发布时间】:2011-02-16 14:04:17
【问题描述】:

当设备在 android 上启动时,我一直在尝试启动服务,但我无法让它工作。我在网上查看了许多链接,但没有一个代码有效。我是不是忘记了什么?

AndroidManifest.xml

<receiver
    android:name=".StartServiceAtBootReceiver"
    android:enabled="true"
    android:exported="false"
    android:label="StartServiceAtBootReceiver" >
    <intent-filter>
        <action android:name="android.intent.action._BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<service
    android:name="com.test.RunService"
    android:enabled="true" />

广播接收器

public void onReceive(Context context, Intent intent) {
    if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
        Intent serviceLauncher = new Intent(context, RunService.class);
        context.startService(serviceLauncher);
        Log.v("TEST", "Service loaded at start");
    }
}

【问题讨论】:

  • 我不知道我做了什么,但我认为它现在可以工作了,它可能是接收器的 android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
  • 你检查过中多余的“_”
  • Exported 必须为真,这样系统才能调用接收方,不是吗?还是默认是真的?

标签: android broadcastreceiver android-service


【解决方案1】:

其他答案看起来不错,但我想我会将所有内容都打包成一个完整的答案。

您的AndroidManifest.xml 文件中需要以下内容:

  1. 在您的&lt;manifest&gt; 元素中:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
  2. 在您的&lt;application&gt; 元素中(确保为您的BroadcastReceiver 使用完全限定的[或相对] 类名):

    <receiver android:name="com.example.MyBroadcastReceiver">  
        <intent-filter>  
            <action android:name="android.intent.action.BOOT_COMPLETED" />  
        </intent-filter>  
    </receiver>
    

    (你不需要android:enabledexported等属性:Android默认是正确的)

    MyBroadcastReceiver.java:

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

来自原始问题:

  • 尚不清楚&lt;receiver&gt; 元素是否在&lt;application&gt; 元素中
  • 尚不清楚是否为 BroadcastReceiver 指定了正确的完全限定(或相对)类名
  • &lt;intent-filter&gt; 中有错字

【讨论】:

  • 这看起来不错。我会以此为基础,谢谢:)。遗憾的是,没有复选标记或赞成票或回复:(。有人验证吗?
  • 只是一个补充:确保您的应用安装在内存中
  • 在 Android Jellybean 4.2.2 中的 标记中,我必须使用类的相对名称而不是完全限定名称来启动服务,如 stackoverflow.com/questions/16671619/… 中所述跨度>
  • 如果接收器用于不同的东西:
    if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) { Intent serviceIntent = new Intent(context, Service_Location.class); // i.putExtra("KEY1", "服务使用的值"); context.startService(serviceIntent); }
  • 您应该改为扩展developer.android.com/reference/android/support/v4/content/…。它是实现广播接收器的常见模式的帮助器,接收设备唤醒事件,然后将工作传递给服务,同时确保设备在转换期间不会重新进入睡眠状态。此类负责为您创建和管理部分唤醒锁;您必须请求 WAKE_LOCK 权限才能使用它。
【解决方案2】:

作为附加信息:BOOT_COMPLETE 发送到应用程序之前外部存储被挂载。因此,如果应用程序安装到外部存储,它不会收到 BOOT_COMPLETE 广播消息。

更多细节here广播接收器监听“启动完成”部分

【讨论】:

  • 为了防止上述问题,开发人员可以在应用程序的清单中设置“android:installLocation="internalOnly"。这是个坏主意吗?对于智能手机应用程序,如果 99.9%(我猜) 的所有用户通过使用内部存储而不是外部存储来正常安装应用程序,那么清单中添加“internalOnly”似乎就可以了。如果您对此有任何想法或想法,我将不胜感激。
【解决方案3】:

如何在设备启动时启动服务(自动运行应用等)

首先:从 Android 3.1+ 版本开始,如果用户从未启动过您的应用程序至少一次或用户“强制关闭”应用程序,您不会收到 BOOT_COMPLETE。 这样做是为了防止恶意软件自动注册服务。此安全漏洞已在较新版本的 Android 中关闭。

解决方案:

创建带有活动的应用程序。当用户运行它一次应用程序可以接收 BOOT_COMPLETE 广播消息。

第二个:在挂载外部存储之前发送 BOOT_COMPLETE。如果应用安装到外部存储,它不会收到 BOOT_COMPLETE 广播消息。

在这种情况下有两种解决方案:

  1. 将您的应用安装到内部存储中
  2. 在内部存储中安装另一个小应用程序。此应用接收 BOOT_COMPLETE 并在外部存储上运行第二个应用。

如果您的应用已经安装在内部存储中,那么下面的代码可以帮助您了解如何在设备启动时启动服务。


在 Manifest.xml 中

权限:

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

注册您的 BOOT_COMPLETED 接收器:

<receiver android:name="org.yourapp.OnBoot">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

注册您的服务:

<service android:name="org.yourapp.YourCoolService" />

在接收器 OnBoot.java 中:

public class OnBoot extends BroadcastReceiver
{

    @Override
    public void onReceive(Context context, Intent intent) 
    {
        // Create Intent
        Intent serviceIntent = new Intent(context, YourCoolService.class);
        // Start service
        context.startService(serviceIntent);

    }

 }

对于 HTC,如果设备未捕获 RECEIVE_BOOT_COMPLETED,您可能还需要在清单中添加此代码:

<action android:name="android.intent.action.QUICKBOOT_POWERON" />

接收器现在看起来像这样:

<receiver android:name="org.yourapp.OnBoot">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

如何在不重启模拟器或真机的情况下测试 BOOT_COMPLETED? 这很容易。试试这个:

adb -s device-or-emulator-id shell am broadcast -a android.intent.action.BOOT_COMPLETED

如何获取设备ID?获取具有 id 的已连接设备列表:

adb devices

ADT 中的 adb 默认可以在以下位置找到:

adt-installation-dir/sdk/platform-tools

享受吧! )

【讨论】:

  • 你的第一段是大写的。我无法让它在我的调试器中运行。
【解决方案4】:

随着

<action android:name="android.intent.action.BOOT_COMPLETED" />  

也使用,

<action android:name="android.intent.action.QUICKBOOT_POWERON" />

HTC 设备似乎无法捕获 BOOT_COMPLETED

【讨论】:

  • 需要为 HTC 设备添加类似的权限吗?
  • 这在某些情况下可能很有用,但我知道 HTC 快速启动是一种休眠形式,系统状态会保存到文件系统中,android.intent.action.QUICKBOOT_POWERON 仅在从快速启动恢复时发送.这意味着在从快速启动恢复时无需执行诸如重置警报之类的操作,因为它们会被保留。因此,如果您想在用户认为设备已启动时执行某些操作,则只需要使用&lt;action android:name="android.intent.action.QUICKBOOT_POWERON" /&gt;
  • 从应用程序开发人员的角度来看,如果该行为仅存在于 HTC 设备上,我们不应该使用它。因为,根据文档,BOOT_COMPLETED 总是在设备打开时发送。其他一些制造商可能会想出另一种快速启动的方法,而我们最终会将我们的代码与每个人的规范相混淆。
  • @HexAndBugs 您是否能够确认快速启动是一种将系统状态保存到文件系统的休眠形式?如果系统状态未保存,我希望能够在快速启动后重置用于未来通知的警报...请告知。
【解决方案5】:

注意问题的开头,有一个错字:

&lt;action android:name="android.intent.action._BOOT_COMPLETED"/&gt;

而不是:

&lt;action android:name="android.intent.action.BOOT_COMPLETED"/&gt;

一个小“_”和所有这些麻烦:)

【讨论】:

    【解决方案6】:

    我认为你的清单需要添加:

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

    【讨论】:

    【解决方案7】:

    我刚刚发现这可能是因为Settings中的Fast Boot选项> Power

    当我关闭此选项时,我的应用程序会收到此广播,但不会收到其他消息。

    顺便说一句,我在HTC Incredible S 上有Android 2.3.3

    希望对你有帮助。

    【讨论】:

    • 问题的绝对可能原因。在运行 Android 4.0.3 的 HTC Desire C 上也观察到。
    【解决方案8】:

    在尝试了所有提到的答案和技巧之后,我终于找到了为什么代码在我的手机中不起作用。部分安卓手机如“华为荣耀3CAndroid 4.2.2”在设置中有Statup Manager菜单,你的应用必须在列表中勾选。 :)

    【讨论】:

      【解决方案9】:

      我还有一个&lt;category&gt;-tag,不知道这是否有什么不同。

      <receiver android:name="BootIntentReceiver">  
              <intent-filter>  
                  <action android:name="android.intent.action.BOOT_COMPLETED" />  
                  <category android:name="android.intent.category.HOME" />  
              </intent-filter>  
      </receiver>
      

      您是否尝试过省略 if 子句 "android.intent.action.BOOT_COMPLETED".equals(intent.getAction(),因为接收方可能只会收到该意图?

      【讨论】:

      • 试过了,但没用,顺便说一句我忘了提到我也有
      • 以防万一:将 android.intent.category.HOME 添加到 AndroidManifest 中的任何标签都会导致三星 Galaxy Tab 以兼容模式运行应用程序,即使在使用 hack 关闭兼容模式后也是如此.不确定其他选项卡是否相同。我建议根本不要设置 HOME 类别。这是不必要的。
      【解决方案10】:

      这就是我所做的

      1.我做了 Receiver 类

      public class BootReceiver extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
              //whatever you want to do on boot
             Intent serviceIntent = new Intent(context, YourService.class);
             context.startService(serviceIntent);
          }
      }
      

      2.在清单中

      <manifest...>
          <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
          <application...>
              <receiver android:name=".BootReceiver" android:enabled="true" android:exported="false">
                  <intent-filter>
                      <action android:name="android.intent.action.BOOT_COMPLETED" />
                  </intent-filter>
              </receiver>
          ...
      

      3.毕竟你需要在 MainActivity 中“设置”接收器,它可能在 onCreate 内

      ...
       final ComponentName onBootReceiver = new ComponentName(getApplication().getPackageName(), BootReceiver.class.getName());
              if(getPackageManager().getComponentEnabledSetting(onBootReceiver) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
              getPackageManager().setComponentEnabledSetting(onBootReceiver,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
      ...
      

      我从 ApiDemos 学到的最后一步

      【讨论】:

      • 你应该检查你的onReceive方法(BOOT_COMPLETED)的传入意图,否则,你的应用会被安装在你设备上的可疑应用调用。
      【解决方案11】:

      参考此链接http://khurramitdeveloper.blogspot.in/2013/06/start-activity-or-service-on-boot.html 在服务上使用引导的分步过程

      【讨论】:

        【解决方案12】:

        在安装外部存储 BOOT_COMPLETE 之前执行。如果您的应用程序安装到外部存储,它将不会收到 BOOT_COMPLETE 广播消息。为了防止这种情况,您可以将应用程序安装在内部存储中。你可以在menifest.xml中添加这一行

        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        android:installLocation="internalOnly"
        ... >
        

        某些 HTC 设备可以启用“快速启动”功能,该功能更像是深度休眠而不是真正的重新启动,因此不应给出 BOOT_COMPLETE 意图。要恢复它,您可以在接收器中添加此意图过滤器:

                    <intent-filter>
                        <action android:name="android.intent.action.BOOT_COMPLETED" />
                        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                    </intent-filter>
        

        【讨论】:

        • 按照您的建议,为防止出现上述问题,开发人员可以在应用程序的清单中设置“android:installLocation="internalOnly"。这是个坏主意吗?对于智能手机应用程序,如果 99.9 %(我的猜测)所有用户通过使用内部存储而不是外部存储正常安装应用程序,那么清单中的“internalOnly”似乎就可以了。我将不胜感激您对此有任何想法或想法。- AJW
        【解决方案13】:

        如果您使用的是 Android Studio 并且非常喜欢自动完成,那么我必须通知您,我使用的是 Android Studio v 1.1.0,并且我使用自动完成来获得以下权限

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

        Android Studio Auto-completedRECEIVE_BOOT_COMPLETED 都是小写的,比如receive_boot_completed,我一直在拔头发,因为我已经勾选了我的清单,以便在启动时启动服务。我刚刚再次确认

        Android Studio 会以小写形式自动完成此权限。

        【讨论】:

          【解决方案14】:

          正如@Damian 评论的那样,这个线程中的所有答案都做错了。像这样手动执行此操作可能会导致您的服务因设备进入睡眠状态而在中间停止。您需要先获得唤醒锁。幸运的是,Support library gives us a class 做到了这一点:

          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 权限添加到您的 mainfest:

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

          【讨论】:

          • 小问题我有一个疑问。如果我的 serviceService 而不是 IntentService 我不能使用这种方式,因为 onHandleIntend 方法不能override 在简单的 Service?
          • 我也有同样的问题。你介意帮助我吗?谢谢! stackoverflow.com/questions/35373525/starting-my-service
          • 也许使用onNewIntent()?或者你可以查看 IntentService 的源代码,看看你需要为你的服务做些什么来使它匹配......
          【解决方案15】:

          事实上,我不久前就遇到了这个问题,而且它真的很容易解决,如果你设置了"android.intent.action.BOOT_COMPLETED"权限和意图过滤器,你实际上并没有做错。

          请注意,如果您在 Android 4.X 上,您必须在启动服务之前运行广播侦听器,这意味着您必须先添加一个活动,一旦您的广播接收器运行,您的应用程序应该像你预料到了,但是,在 Android 4.X 上,我还没有找到一种在没有任何活动的情况下启动服务的方法,我认为谷歌是出于安全原因这样做的。

          【讨论】:

            【解决方案16】:

            如果我将空构造函数留在接收器类中,我会遇到这个问题。删除空构造函数后,onRreceive 方法开始正常工作。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-04-03
              • 2014-02-12
              • 2020-10-06
              • 2019-08-24
              • 1970-01-01
              • 2014-07-28
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多