java - Android:未通过 AlarmManager 触发警报

标签 java android kotlin 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()
    }

}

这看起来很奇怪,考虑到我在我的 AndroidManifest.xml 文件中将我的 MatchNotification 类指定为 receiver

测试设备:

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

注意:方案中要有Java中的MainActivity代码

最佳答案

您的这部分代码似乎有误:

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

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

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);
    }
}

关于java - Android:未通过 AlarmManager 触发警报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67054978/

相关文章:

android - 日历不返回 GMT

java - 字符串格式无法正确显示在 Android Studio 的 ListView 中

kotlin - 使用KDoc记录变量组

javascript - 如何配置 create-react-kotlin-app 以使 kotlinx.serialization 正常工作

android - 导航 Controller 在实时数据观察器中被调用两次

java - 从 C 客户端向 Java 服务器发送一个整数

Java抽象类获取扩展类的类型

java - 在java中找到可执行jar文件的位置

java - 我们可以使用扫描仪输入将值插入 jdbc 程序中的数据库吗

java - 每次除法我得到 0.0