无法停止使用 alarmManager 启动的服务

Posted

技术标签:

【中文标题】无法停止使用 alarmManager 启动的服务【英文标题】:Can't stop a service started with alarmManager 【发布时间】:2011-11-28 04:10:01 【问题描述】:

我在取消警报和使用它启动的服务时遇到问题。

我在一个活动中设置了闹钟:

public class AlarmStarter extends Activity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
      super.onCreate(savedInstanceState);

      Intent locationPollerIntent = new Intent(this, LocationPoller.class);     
      PendingIntent pendingIntent = PendingIntent.getBroadcast
                (getApplicationContext(), REQUEST_CODE, locationPollerIntent, 0);

      alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
      alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                             SystemClock.elapsedRealtime(), 6000, pendingIntent);
    

LocationPoller Intent 将启动一个服务来获取设备的位置。 所以我使用alarmManager以一定的频率重复这个搜索。

之后,当我在 BroadcastReceiver 上获取我的位置时,我会调用另一个 Activity 来显示位置并发出通知。

此时,我想停止搜索该位置。 所以我尝试取消alarmManager。

public class Notifier extends Activity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.alarm_notifier);

        findViewById(R.id.btTurnOffAlarm).
                               setOnClickListener(new View.OnClickListener() 
            public void onClick(View v) 
                Intent intentToStop = new Intent(this, LocationPoller.class);
                PendingIntent pendingIntentToStop = PendingIntent.getBroadcast 
                       (getApplicationContext(), REQUEST_CODE, intentToStop, 0);

                AlarmManager alarmManager = (AlarmManager)
                                getSystemService(ALARM_SERVICE);
                alarmManager.cancel(pendingIntentToStop);
            
        );
    

但这不起作用,它会继续搜索位置。

有什么线索吗?

谢谢。

【问题讨论】:

【参考方案1】:

您必须使意图独一无二。

类似于:

locationPollerIntent.setData((Uri.parse("YOUR UNIQUE ID FOR THIS INTENT")));

AlarmManager 会在为您返回正确的警报时检查意图的数据字段。 只需为意图的数据设置一个唯一的 Uri。

所以当你恢复闹钟时,做某事:

intentToStop.setData((Uri.parse("YOUR SAME UNIQUE ID FOR THIS INTENT")));

警报应该在之后取消。

【讨论】:

每次测试前你都擦掉你的模拟器了吗?也许您以前的警报仍在获取位置。并确保每个警报都使用唯一的 ID。因此,如果您发出 5 次警报,则需要 5 个不同的 ID....只是猜测...【参考方案2】:

REQUEST_CODE 需要在两个地方都一样;您没有显示代码清单中定义的位置。

另外,这里不需要getApplicationContext() -- this 可以正常工作。

【讨论】:

是的,REQUEST_CODE 是一样的。我想知道如果取消警报,它应该停止服务。因为在调用alarmManager.cancel()之后,它会继续搜索位置。谢谢。 @blui:“我想知道如果取消警报,它应该停止服务。” - 没有。所有取消警报都会阻止您的PendingIntent 被调用。【参考方案3】:

你必须传递同一个实例。

public static final Uri MYURI = Uri.parse("Some_Uri");
[...]
locationPollerIntent.setData(MyClass.MYURI);
[...]
intentToStop.setData(MyClass.MYURI);

如果您每次创建 Intent 时都有两个不同的引用,则它将不起作用。

这里有更详细的例子:

http://malubu.wordpress.com/2012/06/05/take-your-time-widgets-and-alarmmanager/

【讨论】:

我有同样的问题,我为意图创建了一个单例,但仍然无法正常工作......【参考方案4】:

我遇到了同样的问题,它不是关于 Intent “locationPollerIntent”和“intentToStop”的相同实例,而是 PendingIntent 必须具有相同的实例。

AlarmManager 停止后,服务也停止。

    static PendingIntent instance;

public static PendingIntent getInstance(Context context) 

    if (instance == null)
    
        Intent intent = new Intent(context, LocationPoller.class); 
        instance = PendingIntent.getService(context, REQUEST_CODE, intent, 0);
    

    return instance;

【讨论】:

以上是关于无法停止使用 alarmManager 启动的服务的主要内容,如果未能解决你的问题,请参考以下文章

在特定时间停止服务

OracleXETNSListener无法启动或启动停止怎么办

停止Android alarmmanager的setrepeat

OracleXETNSListener无法启动或启动停止怎么办

BroadcastReceiver - 无法从关闭或后台应用程序启动活动

K3CloudMQ服务无法启动,提示:本地计算机上的k3cloudmq 服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止