无法检查AlarmManager是不是设置了警报

Posted

技术标签:

【中文标题】无法检查AlarmManager是不是设置了警报【英文标题】:Unable to check if alarm has been set by AlarmManager无法检查AlarmManager是否设置了警报 【发布时间】:2015-08-20 17:23:44 【问题描述】:

我正在检查 AlarmManager 是否已经使用 this answer 设置了警报。

以下是我的代码 sn-p。

boolean alarmUp = (PendingIntent.getBroadcast(MainActivity.this, 0,
    new Intent(MainActivity.this, AlarmReceiver.class), PendingIntent.FLAG_NO_CREATE) != null);
if (alarmUp) 
    // alarm is set; do some stuff


Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10 * 1000, pendingIntent);

但是,alarmUp 始终设置为 true。也就是说,无论我是否设置了闹钟,每当我重新启动我的应用程序时,它都会告诉我alarmUp 是真的(我通过创建Toast 来检查它)。

请帮助我哪里出错了。

【问题讨论】:

我还没有发现 see-if-the-PendingIntent-exists 技术是可靠的。 能否请您详细说明,或者提供一个链接来说明如何做到这一点? 我指的是您问题中的代码。我还没有发现 FLAG_NO_CREATE 技巧是可靠的。 好的!你知道做我想做的事情的其他方法吗? 不,抱歉。 AlarmManager 需要更好的 API。 【参考方案1】:

为了使此检查起作用,您需要绝对确定PendingIntent 仅在设置警报时存在。您可以做 2 件事来确保做到这一点:

1) 测试代码时,请确保先卸载应用程序,然后重新安装应用程序,然后再进行测试。卸载您的应用将删除您的应用可能已创建但仍处于待处理状态的所有 PendingIntents。

2) 当您取消闹钟时,请确保您也取消了PendingIntent。您可以使用

Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
final PendingIntent pendingIntent = 
          PendingIntent.getBroadcast(MainActivity.this, 0, alarmIntent,
          PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null) 
    pendingIntent.cancel();

【讨论】:

【参考方案2】:

从 API 21 开始,您可以使用

public AlarmManager.AlarmClockInfo getNextAlarmClock ()

http://developer.android.com/reference/android/app/AlarmManager.html#getNextAlarmClock()


现在,您尝试使用的代码:

(PendingIntent.getBroadcast(MainActivity.this, 0,
    new Intent(MainActivity.this, AlarmReceiver.class), PendingIntent.FLAG_NO_CREATE) != null);

基本上,您要求的是以前存在的称为 AlarmReceiver 的意图。但是他的AlarmReceiver指的是你自己的BroadcastReceiver。

正如您在之前发布的答案的这一行中看到的那样:

boolean alarmUp = (PendingIntent.getBroadcast(context, 0, 
    new Intent("com.my.package.MY_UNIQUE_ACTION"), 
    PendingIntent.FLAG_NO_CREATE) != null);

他们使用“MY_UNIQUE_ACTION”来查看意图是否存在。

您还可以在这个网站上看到一个使用它的教程:

http://justcallmebrian.com/2010/04/27/using-alarmmanager-to-schedule-activities-on-android/


除非您能够访问 android-system AlarmReceiver 并查看意图是否存在,否则您将无法请求“通用”预定警报。那是你想要做的吗?如果是这种情况,您确定如果您没有任何预定的警报,android-system AlarmReceiver 意图不是由系统创建的吗? 似乎我们无法像我们喜欢的那样控制这些组件。


一个工作示例: 清单.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blablabla.testa" >
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <receiver
            android:name=".MySuperReceiver"
            android:label="MySuperReceiverName" />

    </activity>
</application>

MySuperReceiver.java

package com.blablabla.testa;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import java.util.Calendar;

public class MySuperReceiver extends BroadcastReceiver 
    public static final String TAG = MySuperReceiver.class.getSimpleName();
    public static final String ACTION_ALARM_RECEIVER = "ACTION_ALARM_RECEIVER";
    private Calendar c = Calendar.getInstance();

    @Override
    public void onReceive(Context context, Intent intent) 
        if (intent != null)
            if (ACTION_ALARM_RECEIVER.equals(intent.getAction())) 
                Log.d(TAG, new Exception().getStackTrace()[0].getMethodName() + " " + c.getTime());
                //do something here
            
    

还有 MainActivity.java:

package com.blablabla.testa;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;


public class MainActivity extends ActionBarActivity 

    public static final String TAG = "TEST APP:";

    AlarmManager alarmManager;


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

        GetAlarmService();
        CreateAlarm();
        CheckForAlarm();
        CancelAlarms();
        CheckForAlarm();
    

    private void GetAlarmService()
    
        alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        Log.d(TAG, " GET Alarm Service ! ");
    
    private void CreateAlarm()
    
        long aroundInterval = 1*60*1000; 

        Intent intent = new Intent(getApplicationContext(), MySuperReceiver.class);
        intent.setAction(MySuperReceiver.ACTION_ALARM_RECEIVER);//my custom string action name

        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//used unique ID as 1001
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), aroundInterval, pendingIntent);//first start will start asap

        Log.d(TAG, " CREATE Alarm ! ");
    

    private void CancelAlarms()
    
        Intent intent = new Intent(getApplicationContext(), MySuperReceiver.class);//the same as up
        intent.setAction(MySuperReceiver.ACTION_ALARM_RECEIVER);//the same as up
        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//the same as up
        alarmManager.cancel(pendingIntent);//important
        pendingIntent.cancel();//important

        Log.d(TAG, " Cancel Alarm ! ");
    

    private void CheckForAlarm()
    
        //checking if alarm is working with pendingIntent #3
        Intent intent = new Intent(getApplicationContext()  , MySuperReceiver.class);//the same as up
        intent.setAction(MySuperReceiver.ACTION_ALARM_RECEIVER);//the same as up
        boolean isWorking = (PendingIntent.getBroadcast(getApplicationContext() , 1001, intent, PendingIntent.FLAG_NO_CREATE) != null);//just changed the flag
        Log.d("TAG: TEST APP:  ", "alarm is " + (isWorking ? "" : "not") + " working...");

    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) 
            return true;
        

        return super.onOptionsItemSelected(item);
    

【讨论】:

21 之前的 API 有没有办法让它工作?我只想知道我的应用是否已经设置了闹钟。 mmm,所以如果您使用自己的 BroadcastReceiver 设置警报,您应该能够读取该寄存器。这是另一个示例的另一个链接:blog.mokrzycki.io/2015/01/… 我已经做了与您链接中 #2 中提到的相同的事情。这正是我的问题中提到的不起作用的原因。 您是否在清单中添加了这些行?如果您更改接收者的名称并检查您是否第一次在 getBroadcast 上也得到 null 怎么办? 是的,我做到了。我不明白更改名称有什么意义?不,当应用第一次启动时,闹钟没有响起。

以上是关于无法检查AlarmManager是不是设置了警报的主要内容,如果未能解决你的问题,请参考以下文章

Android AlarmClock() ,设置闹钟日期

AlarmManager 在同一天设置的时间过后发出警报,setRepeating

如何调试您的应用程序正在运行哪些 AlarmManager 警报?

手机睡着时无法显示活动(警报)

如何设置多个AlarmManager?

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