Android长时间运行服务,带有报警管理器和内部广播接收器

Android长时间运行服务,带有报警管理器和内部广播接收器,android,service,broadcastreceiver,alarmmanager,Android,Service,Broadcastreceiver,Alarmmanager,我有一个使用自定义连接类(扩展线程)到硬件控制器的服务。当用户愿意时,我希望永久保持此连接。我已经有了当Android设备失去互联网连接、在wi-fi之间切换等时需要处理的代码 为了保持连接,控制器要求您每5分钟与它通话一次。目前,我在Connection类中启动一个线程,该线程在while()中运行,并检查系统时间和上次通信时间,以及当>4分钟时请求状态。由于某些原因,在不同的时间,沟通没有及时发生。i、 例如,5分钟后发生。据我所知,这项服务并没有消亡,但对控制器的“Ping”已经晚了。当我

我有一个使用自定义连接类(扩展线程)到硬件控制器的服务。当用户愿意时,我希望永久保持此连接。我已经有了当Android设备失去互联网连接、在wi-fi之间切换等时需要处理的代码

为了保持连接,控制器要求您每5分钟与它通话一次。目前,我在Connection类中启动一个线程,该线程在while()中运行,并检查系统时间和上次通信时间,以及当>4分钟时请求状态。由于某些原因,在不同的时间,沟通没有及时发生。i、 例如,5分钟后发生。据我所知,这项服务并没有消亡,但对控制器的“Ping”已经晚了。当我将手机插入充电器(或调试器)时,不会发生这种情况。此外,当我将服务移动到前台时,行为是相同的

当手机进入睡眠状态时,它的处理器会变慢吗

有更好的办法吗

我认为这是AlarmManger,但我很难让它与服务中的内部类一起工作。我尝试使用API演示作为起点,但似乎不知道如何注册广播接收器。我试图以编程方式注册接收方,而不更改清单

public class DeviceConnectionService extends Service {

    @Override
    public void onCreate() {
        Intent intent = new Intent(this, PingConnection.class);
        intent.setAction("KEEP_CONNECTION_ALIVE");
        PendingIntent sender = PendingIntent.getBroadcast(this,
            0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // We want the alarm to go off 30 seconds from now.
        long firstTime = SystemClock.elapsedRealtime();
        firstTime += 15*1000;
        // Schedule the alarm!
        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                firstTime, 15*1000, sender);
        // register to listen to the Alarm Manager
        if (mPingConnectionReceiver == null) {
            mPingConnectionReceiver = new PingConnection();
            getApplicationContext().registerReceiver(mPingConnectionReceiver,
             new IntentFilter("KEEP_CONNECTION_ALIVE"));
        }
    }

    // ...

    public class PingConnection extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (dBug) Log.i("PingConnection", "Pinging Controller");
            // do real work here
        }
    }
}
当手机进入睡眠状态时,它的处理器会变慢吗

手机进入睡眠状态时会关闭处理器。这就是“睡眠”的定义

我认为这是AlarmManger,但我很难让它与服务中的内部类一起工作。我尝试使用API演示作为起点,但似乎不知道如何注册广播接收器。我正在尝试以编程方式注册接收者,而不更改清单

public class DeviceConnectionService extends Service {

    @Override
    public void onCreate() {
        Intent intent = new Intent(this, PingConnection.class);
        intent.setAction("KEEP_CONNECTION_ALIVE");
        PendingIntent sender = PendingIntent.getBroadcast(this,
            0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // We want the alarm to go off 30 seconds from now.
        long firstTime = SystemClock.elapsedRealtime();
        firstTime += 15*1000;
        // Schedule the alarm!
        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                firstTime, 15*1000, sender);
        // register to listen to the Alarm Manager
        if (mPingConnectionReceiver == null) {
            mPingConnectionReceiver = new PingConnection();
            getApplicationContext().registerReceiver(mPingConnectionReceiver,
             new IntentFilter("KEEP_CONNECTION_ALIVE"));
        }
    }

    // ...

    public class PingConnection extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (dBug) Log.i("PingConnection", "Pinging Controller");
            // do real work here
        }
    }
}
对于
AlarmManager
,这是一种不同寻常的方法。话虽如此,由于您拒绝详细描述“遇到麻烦”,因此很难帮助您

摆脱
getApplicationContext()
(在这种情况下,您不需要它,也确实不想要它)。我会在触摸
AlarmManager
之前注册接收器。在开始生产之前,请选择一个包含包名的操作名称(例如,
com.something.myapp.KEEP_CONNECTION_ALIVE

除此之外,检查LogCat是否有警告


更新

在日志猫中,您应该收到来自
AlarmManager
的警告,抱怨无法与您的
BroadcastReceiver
通话

替换:

Intent intent = new Intent(this, PingConnection.class);
intent.setAction("KEEP_CONNECTION_ALIVE");
与:


您可能会有更好的运气。

您不能在服务中注册AlarmManager。 您所能做的就是在Manifest.xml中将其声明为全局。 您可以通过在Manifest.xml中声明警报,以这种方式从服务启动警报

如果您有一个远程服务,并且关闭了启动程序活动,AlarmManager仍将运行,但不要忘记在服务的onDestroy()方法上停止它

我尝试只在AlarmManager服务中注册,因为我没有将其用于主要活动,但没有成功! 它不像普通的广播接收机那样进行注册


事情就是这样的,你必须在Manifest.xml中将它声明为全局的

我知道时间已经晚了,但可能对其他人有用

你可以注册它,问题是当意图试图调用它时

而不是这样称呼它:

Intent intent = new Intent(this, PingConnection.class);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("the value you used before");
getApplicationContext().registerReceiver(pingConnection, filter);
创建一个空的意图,并添加一个要侦听的操作:

Intent intent = new Intent();
intent.setAction("value you want to register");
然后创建挂起的意图并发送广播,就像您拥有它一样

为receiver创建一个属性,以便您可以在整个类中访问它,并在必要时取消注册(如果PendingEvent也是一个属性,则您可以随时取消注册):

按如下方式注册:

Intent intent = new Intent(this, PingConnection.class);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("the value you used before");
getApplicationContext().registerReceiver(pingConnection, filter);

现在,您将不会得到任何错误,并且该类不是静态的,它是一个内部类。

@tunneling:您的第一个构造函数将仅适用于清单中注册的
BroadcastReceiver
。如果您指定了一个组件,Android将尝试传递到该组件,而忽略您的操作。警报正在触发。在您的回答中,您表示这对于AlarmManager来说是一种不同寻常的方法。有没有更常见的方法来完成我想做的事情?@tunneling:
AlarmManager
主要用于您没有一直运行的服务的情况,这就是为什么您找到的大多数示例都是针对清单注册的
BroadcastReceivers
等。在您的情况下,只要用户选择让您的服务一直运行,您所描述的方法就和您将得到的一样好,特别是从功耗的角度来看。