首页 文章

尝试在Android上启动服务

提问于
浏览
317

当设备在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" />

BroadcastReceiver

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

16 回答

  • 66

    其他答案看起来不错,但我想我会把所有内容都包含在一个完整的答案中 .

    您需要在 AndroidManifest.xml 文件中包含以下内容:

    • <manifest> 元素中:
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
    • <application> 元素中(确保为 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);
        }
    }
    

    从原来的问题:

    • 不清楚 <receiver> 元素是否在 <application> 元素中

    • 不清楚是否指定了 BroadcastReceiver 的正确的完全限定(或相对)类名

    • <intent-filter> 中有一个拼写错误

  • 2

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

    更多细节hereBroadcast Receivers listening for "boot completed" 部分

  • 34

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

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

    解:

    使用活动创建应用 . 当用户运行它时,应用程序可以接收BOOT_COMPLETE广播消息 .

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

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

    • 将您的应用安装到内部存储

    • 在内部存储中安装另一个小应用程序 . 此应用程序接收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,您可能还需要添加Manifest此代码:

    <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
    

    请享用! )

  • 1

    随着

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

    也用,

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

    HTC设备似乎没有 grab BOOT_COMPLETED

  • 6

    请注意,在问题的开头,有一个拼写错误:

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

    代替 :

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

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

  • 5

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

    当我关闭此选项时,我的应用程序会收到此广播,但不是 .

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

    希望能帮助到你 .

  • 12

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

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

    在尝试了所有提到的答案和技巧之后,我终于找到了为什么代码在我的手机中不起作用 . 某些Android手机如“Huawei Honor 3C Android 4.2.2 ”在其设置中有一个 Statup Manager 菜单,您的应用必须在列表中进行检查 . :)

  • 3

    我有一个额外的 <category> -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-clause "android.intent.action.BOOT_COMPLETED".equals(intent.getAction() ,因为接收器可能只接收到该意图?

  • 13
  • 591

    在挂载外部存储器之前,执行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>
    
  • 2

    如果你正在使用Android Studio并且你非常喜欢自动完成,那么我必须告诉你,我正在使用Android Studio v 1.1.0并且我使用自动完成以获得以下许可

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

    并且Android Studio自动完成了 RECEIVE_BOOT_COMPLETED 所有小写,如 receive_boot_completed ,我一直在拉我的头发,因为我已经勾选了我的检查表,以便在启动时启动服务 . 我刚刚再确认一下

    Android Studio DOES以小写形式自动完成此权限 .

  • 0

    正如@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 permssion添加到你的主要节日中:

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

    这就是我做的

    1. I made the Receiver class

    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.in the manifest

    <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.and after ALL you NEED to "set" the receiver in your MainActivity, it may be inside the 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学到的最后一步

  • 83

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

    请注意,如果你在Android 4.X上,你必须在启动服务之前运行广播监听器,这意味着你必须首先添加一个活动,一旦你的广播接收器运行,你的应用程序应该按照你的预期运行,但是,在Android 4.X上,我没有找到一种方法来启动服务而没有任何活动,我认为google是出于安全原因这样做的 .

  • 2

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

相关问题