首页 > 解决方案 > Android:警报未通过 AlarmManager 触发

问题描述

我正在编写一个简单的 Android 程序,它会在应用程序初始化(播放默认铃声并推送通知)后 15 秒触发警报AlarmManager。下面是我的代码:

MainActivity.java

package com.example.basicalarmsetter;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;

public class MainActivity extends AppCompatActivity {
    private int uniqueId = 0;

    // Schedules a notification in the future given the delay
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void scheduleNotification(int matchId, long delay) {
        // Construct the PendingIntent which will trigger our alarm to go off
        Intent notificationIntent = new Intent();
        notificationIntent.setAction("com.example.basicalarmsetter.MatchNotification");

        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), matchId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT) ;
        long futureInMillis = SystemClock.elapsedRealtime() + delay;

        // Set off our PendingIntent
        AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, futureInMillis, pendingIntent);
        assert alarmManager != null;
        alarmManager.setExact(AlarmManager. ELAPSED_REALTIME_WAKEUP, futureInMillis, pendingIntent);
    }

    // Sets an Alarm at a future specified date
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void setAlarm(long notificationDelay) {
        try {
            System.out.println("Setting alarm at " + notificationDelay + " seconds");

            // Sets off a notification after 5 seconds
            scheduleNotification(uniqueId, notificationDelay);

            uniqueId++;

        } catch (Exception ex) {
            System.out.println("Cannot print alarm!");
            System.out.println("Exception: " + ex.toString());
        }
    }

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

        setAlarm(15000);
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.basicalarmsetter">

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

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

        <receiver
            android:name="com.example.basicalarmsetter.MatchNotification"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                ...
                <action android:name="com.example.notificationtest.MatchNotification" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

MatchNotification.kt

package com.example.basicalarmsetter

import android.app.Notification
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.media.MediaPlayer
import android.media.RingtoneManager
import android.net.Uri
import androidx.core.app.NotificationCompat

class MatchNotification : BroadcastReceiver() {
    var NOTIFICATION_ID = "notification-id"
    var NOTIFICATION_CHANNEL_ID = "10001";

    private lateinit var player: MediaPlayer;
    private lateinit var context: Context;

    // Construct the notification to push to the user given the teams in the match
    private fun getNotification(
        content: String
    ): Notification? {
        val builder = NotificationCompat.Builder(
            context,
            "default"
        )

        builder.setContentTitle("NBA Alarm")
        builder.setStyle(NotificationCompat.BigTextStyle().bigText(content))
        builder.setContentText(content)
        builder.setSmallIcon(R.drawable.ic_launcher_foreground)
        builder.setAutoCancel(true)
        builder.setChannelId(NOTIFICATION_CHANNEL_ID)

        return builder.build()
    }

    override fun onReceive(context: Context, intent: Intent) {
        System.out.println("Match Notification Activated.");

        this.context = context

        val notificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        val id = intent.getIntExtra(NOTIFICATION_ID, 0)
        notificationManager.notify(id, getNotification("Trigger Notification!"))

        // Retrieve the URI of the alarm the user has set
        var ringtoneUri:Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
        player = MediaPlayer.create(context, ringtoneUri)

        player.start()
    }

}

这似乎很奇怪,考虑到我已经在我的文件中指定了我的MatchNotification类。receiverAndroidManifest.xml

测试设备

  1. 摩托罗拉 Moto E6 (Android 9)
  2. Pixel 2 模拟器 (API 26)

注意:解决方案应该有 Java 中的 MainActivity 代码

标签: javaandroidkotlinalarmmanager

解决方案


您的这部分代码似乎是错误的:

notificationIntent.setAction("com.example.basicalarmsetter.MatchNotification");

你在这里使用类名。您需要使用广播接收器的操作,即您放入意图过滤器的操作,即:

notificationIntent.setAction("com.example.notificationtest.MatchNotification");

另一个问题:您在这里创建了两个不必要的警报:

AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, futureInMillis, pendingIntent);
assert alarmManager != null;
alarmManager.setExact(AlarmManager. ELAPSED_REALTIME_WAKEUP, futureInMillis, pendingIntent);

在本节中,不需要以下行:

alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, futureInMillis, pendingIntent);
assert alarmManager != null;

RTC_WAKEUP 值应该与 一起使用System.currentTimeMillis(),而不是SystemClock.elapsedRealtime()

MainActivity.java的最终结果如下所示:

package com.example.basicalarmsetter;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;

public class MainActivity extends AppCompatActivity {
    private int uniqueId = 0;

    // Schedules a notification in the future given the delay
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void scheduleNotification(int matchId, long delay) {
        // Construct the PendingIntent which will trigger our alarm to go off
        Intent notificationIntent = new Intent();
        notificationIntent.setAction("com.example.notificationtest.MatchNotification");

        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), matchId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT) ;
        long futureInMillis = SystemClock.elapsedRealtime() + delay;

        // Set off our PendingIntent
        AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        alarmManager.setExact(AlarmManager. ELAPSED_REALTIME_WAKEUP, futureInMillis, pendingIntent);
    }

    // Sets an Alarm at a future specified date
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void setAlarm(long notificationDelay) {
        try {
            System.out.println("Setting alarm at " + notificationDelay + " seconds");

            // Sets off a notification after 5 seconds
            scheduleNotification(uniqueId, notificationDelay);

            uniqueId++;

        } catch (Exception ex) {
            System.out.println("Cannot print alarm!");
            System.out.println("Exception: " + ex.toString());
        }
    }

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

        setAlarm(15000);
    }
}

推荐阅读