安卓如何保持 IntentService 运行并监听广播

3
我正在尝试追踪“SCREEN_ON”触发的次数,而不需要用户启动应用程序。该应用程序仅显示一个包含一些图表和信息的活动。我创建了一个小测试,但我认为这不是正确的方法,因为它会耗费我的电池。
我使用了一个广播接收器“BOOT_COMPLETED”,它启动了一个粘性的IntentService,并注册了“SCREEN_ON”广播接收器来捕获广播(这会导致电池耗尽的问题)。
是否可能在没有服务的情况下监听“SCREEN_ON”广播?
Jur 清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
    android:name=".Application"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:hardwareAccelerated="true">

    <activity
        android:name=".activities.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <service android:enabled="true" android:name=".services.ScreenOnService" />

    <receiver android:name=".broadcast.receivers.AutoStartReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <receiver android:name=".broadcast.receivers.ScreenOnReceiver">
        <intent-filter>
            <action android:name="android.intent.action.SCREEN_ON" />
        </intent-filter>
    </receiver>
</application>

AutoStartReceiver自启动接收器
public class AutoStartReceiver extends BroadcastReceiver
{
    public void onReceive(Context aContext, Intent anIntent)
    {
        Log.i("[AutoStartReceiver]", "onReceive");
        aContext.startService(new Intent(aContext, ScreenOnService.class));
    }
}

ScreenOnReceiver

public class ScreenOnReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Log.i("[ScreenOnReceiver]", "onReceive");
    }
}

ScreenOnService

public class ScreenOnService extends IntentService
{
    private ScreenOnReceiver theReceiver;

    public ScreenOnService()
    {
        super(ScreenOnService.class.getName());
        theReceiver = new ScreenOnReceiver();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.v("[ScreenOnService]", "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        Log.i("[ScreenOnService]", "onHandleIntent");
        registerReceiver(theReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
        while(true);
    }

    @Override
    public void onDestroy()
    {
        Log.i("[ScreenOnService]", "onDestroy");
        unregisterReceiver(theReceiver);
        super.onDestroy();
    }
}
3个回答

3

您使用 IntentService 的特定原因是什么,而不是使用常规启动的 Service

您应该能够使用常规启动的 Service 来实现这一点。将接收器注册为 onStartCommand 的一部分。

类似于以下内容:

public class MyService extends Service {
    private ScreenOnReceiver mReceiver;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mReceiver == null) {
            mReceiver = new ScreenOnReceiver();
            registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
        }
        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

    // remember to unregister receiver in onDestroy...
}

这样可以避免繁忙循环。 IntentService 是设计用于执行后台操作的短寿命服务。您的使用方式不符合 IntentService 的目的。


太棒了!我使用IntentService,因为我只想运行一个活动的ScreenOnService。我没有完全阅读有关Service和IntentService的文档..谢谢! - Jurdefur

0
我有一个广播接收器“BOOT_COMPLETED”,它启动了一个粘性的IntentService,该服务使用无限循环来注册“SCREEN_ON”广播接收器以捕获广播(电池耗尽问题)。
这对于IntentService来说完全不适合。你的问题是IntentService在onHandleIntent()返回后会关闭,强制你进入这个繁忙的等待状态。
相反,使用常规的Service。
能否在没有Service的情况下监听“SCREEN_ON”广播呢?
据我所知,在清单中仍然不能注册ACTION_SCREEN_ON,因此,是的,您需要一个Service。但是你需要一个Service,而不是IntentService。

0
我有一个广播接收器"BOOT_COMPLETED",它启动了一个粘性IntentService,该服务使用永不结束的循环来注册"SCREEN_ON"广播接收器以捕获广播(电池耗尽问题)。
这是不正确的。Intent Service不适用于长时间运行的操作。实际上,在onHandleIntent()之后,它不再保持运行。
如果您想要持续监听设备开启,则服务将确保帮助您监听每个触发器。
public class ScreenOnService extends Service
{
...........
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接