Android: 警报未通过 AlarmManager 触发
Android: Alarm not being triggered through AlarmManager
我正在编写一个简单的 Android 程序,通过 AlarmManager
在应用程序初始化(播放默认铃声并推送通知)后 15 秒触发警报。下面是我的代码:
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
class 指定为 receiver
。
测试设备:
- 摩托罗拉 Moto E6 (Android 9)
- Pixel 2 模拟器(API 26)
注意:方案中MainActivity代码要在Java
您好,您似乎还没有检查过是否在后台发出警报 运行ning 并且一定有一些旧代码
试试下面的代码,只需粘贴它,无需对 AndroidManifest 文件和 运行.
做任何额外的事情
class MyActivity : AppCompatActivity() {
private var alarmManager: AlarmManager? = null
private var broadcastReceiver: BroadcastReceiver? = null
private var pendingIntent: PendingIntent? = null
private val REQUEST_CODE = 45645
private var id: String? = "myname"
private var timeInMilliSeconds: Long = 15000
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
initAlarm()
}
private fun initAlarm() {
//creating intent
val intent = Intent(id)
val alarmRunning = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_NO_CREATE
) != null
//setting broadcast
broadcastReceiver = getBroadcastReceiver()
registerReceiver(
broadcastReceiver,
IntentFilter(id)
)
//setting alarm
val ensurePositiveTime = Math.max(timeInMilliSeconds, 0L)
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
//Check if alarm is already running
if (!alarmRunning) {
alarmManager?.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ensurePositiveTime, pendingIntent)
} else {
updateAlarm()
Log.e("Alarm", "Alarm already running.!")
}
}
private fun updateAlarm() {
//calculating alarm time and creating pending intent
val intent = Intent(id)
val ensurePositiveTime = Math.max(timeInMilliSeconds, 0L)
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
//removing previously running alarm
alarmManager?.cancel(pendingIntent)
unregisterReceiver(broadcastReceiver)
//setting broadcast
broadcastReceiver = getBroadcastReceiver()
registerReceiver(
broadcastReceiver,
IntentFilter(id)
)
//Check if alarm is already running
alarmManager?.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + ensurePositiveTime,
pendingIntent
)
Log.e("Alarm", "Alarm updated..!")
}
/**
* This will receive broadcast after completed seconds
*/
private fun getBroadcastReceiver(): BroadcastReceiver {
return object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
createNotification()
}
}
}
/***
* It creates notification
*/
private fun createNotification() {
val channelId = "fcm_default_channel"
val channelName = "notification"
val defaultSoundUri =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this@MyActivity, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("I am alarm from my activity")
.setContentTitle(getString(R.string.app_name))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
val mNotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_HIGH
)
notificationBuilder.setChannelId(channelId)
mNotificationManager.createNotificationChannel(channel)
}
val notification = notificationBuilder.build()
mNotificationManager.notify(0, notification)
}
/**
* Use this to cancel alarm
*/
private fun cancelAlarm() {
if (pendingIntent != null) {
alarmManager?.cancel(pendingIntent)
}
if (broadcastReceiver != null) {
unregisterReceiver(broadcastReceiver)
broadcastReceiver = null
}
Log.e("Alarm", "Alarm has been canceled..!")
}
}
下面是 java 代码
public class AlarmActivity extends AppCompatActivity {
private AlarmManager alarmManager;
private PendingIntent pendingIntent;
private int REQUEST_CODE = 45645;
private String id = "myname";
private long timeInMilliSeconds = 5000;
static String APP_TAG = "classname";
private BroadcastReceiver broadcastReceiver;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
initAlarm();
}
private void initAlarm() {
//creating intent
Intent intent = new Intent(id);
boolean alarmRunning = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_NO_CREATE
) != null;
//setting broadcast
broadcastReceiver = new MyReceiver();
registerReceiver(
broadcastReceiver,
new IntentFilter(id)
);
//setting alarm
long ensurePositiveTime = Math.max(timeInMilliSeconds, 0L);
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
//Check if alarm is already running
if (!alarmRunning) {
alarmManager.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + ensurePositiveTime,
pendingIntent
);
} else {
updateAlarm();
Log.e("Alarm", "Alarm already running.!");
}
}
private void updateAlarm() {
//calculating alarm time and creating pending intent
Intent intent = new Intent(id);
long ensurePositiveTime = Math.max(timeInMilliSeconds, 0L);
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
//removing previously running alarm
alarmManager.cancel(pendingIntent);
unregisterReceiver(broadcastReceiver);
//setting broadcast
broadcastReceiver = new MyReceiver();
registerReceiver(
broadcastReceiver,
new IntentFilter(id)
);
//Check if alarm is already running
alarmManager.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + ensurePositiveTime,
pendingIntent
);
Log.e("Alarm", "Alarm updated..!");
}
/**
* Use this to cancel alarm
*/
private void cancelAlarm() {
if (pendingIntent != null) {
alarmManager.cancel(pendingIntent);
}
if (broadcastReceiver != null) {
unregisterReceiver(broadcastReceiver);
broadcastReceiver = null;
}
Log.e("Alarm", "Alarm has been canceled..!");
}
}
BroadCastReceiver class
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
createNotification(context);
WakeLocker.release();
}
/***
* It creates notification
* @param context
*/
private void createNotification(Context context) {
String channelId = "fcm_default_channel";
String channelName = "notification";
Uri defaultSoundUri =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("I am alarm from my activity")
.setContentTitle(context.getString(R.string.app_name))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel =
new NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_HIGH
);
notificationBuilder.setChannelId(channelId);
mNotificationManager.createNotificationChannel(channel);
}
Notification notification = notificationBuilder.build();
mNotificationManager.notify(0, notification);
}
}
Wake Locker class 也可以在后台保持 运行ning,但是为此你必须从应用程序设置中启用后台服务并禁用省电模式
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context c) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) c.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, AlarmActivity.APP_TAG);
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null){
wakeLock.release();
}
wakeLock = null;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<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/Theme.Alarmdemo">
<activity android:name=".AlarmActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.example.alarmdemo.MyReceiver" />
</application>
您的这部分代码似乎有误:
notificationIntent.setAction("com.example.basicalarmsetter.MatchNotification");
您在这里使用的是 class 名称。你需要使用广播接收器的动作,你放在你的意图过滤器中的那个,a.k.a:
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);
}
}
我有一个适合我的解决方案。设置警报如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
long delayInMillis = 5000;//your delay in millisecond
Intent myIntent = new Intent(this, AlertReceiver.class);
//any data you want to pass to your receiver class
myIntent.putExtra(AlertReceiver.TITLE, "Scheduled Alert");
myIntent.putExtra(AlertReceiver.CONTENT, "You have scheduled alert. Tap here to view continue...");
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, delayInMillis, pendingIntent);
}
}
在您的清单中添加接收者
<receiver android:name=".utils.AlertReceiver" />//path to your receiver
您的警报接收器 class 可以是这样的
public class AlertReceiver extends BroadcastReceiver {
private static final String TAG = "AlertReceiver";
public static final String TITLE = "title";
public static final String CONTENT = "content";
@Override
public void onReceive(Context context, Intent receivedIntent) {
String title = receivedIntent.getStringExtra(TITLE);
String message = receivedIntent.getStringExtra(CONTENT);
Log.e(TAG, "onReceive: " + title + ":" + message);
//you can show your notification or anything you want to do once you receive your alert here...
}
}
希望这对您有所帮助。编码愉快!!
我正在编写一个简单的 Android 程序,通过 AlarmManager
在应用程序初始化(播放默认铃声并推送通知)后 15 秒触发警报。下面是我的代码:
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
class 指定为 receiver
。
测试设备:
- 摩托罗拉 Moto E6 (Android 9)
- Pixel 2 模拟器(API 26)
注意:方案中MainActivity代码要在Java
您好,您似乎还没有检查过是否在后台发出警报 运行ning 并且一定有一些旧代码
试试下面的代码,只需粘贴它,无需对 AndroidManifest 文件和 运行.
做任何额外的事情class MyActivity : AppCompatActivity() {
private var alarmManager: AlarmManager? = null
private var broadcastReceiver: BroadcastReceiver? = null
private var pendingIntent: PendingIntent? = null
private val REQUEST_CODE = 45645
private var id: String? = "myname"
private var timeInMilliSeconds: Long = 15000
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
initAlarm()
}
private fun initAlarm() {
//creating intent
val intent = Intent(id)
val alarmRunning = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_NO_CREATE
) != null
//setting broadcast
broadcastReceiver = getBroadcastReceiver()
registerReceiver(
broadcastReceiver,
IntentFilter(id)
)
//setting alarm
val ensurePositiveTime = Math.max(timeInMilliSeconds, 0L)
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
//Check if alarm is already running
if (!alarmRunning) {
alarmManager?.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ensurePositiveTime, pendingIntent)
} else {
updateAlarm()
Log.e("Alarm", "Alarm already running.!")
}
}
private fun updateAlarm() {
//calculating alarm time and creating pending intent
val intent = Intent(id)
val ensurePositiveTime = Math.max(timeInMilliSeconds, 0L)
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
//removing previously running alarm
alarmManager?.cancel(pendingIntent)
unregisterReceiver(broadcastReceiver)
//setting broadcast
broadcastReceiver = getBroadcastReceiver()
registerReceiver(
broadcastReceiver,
IntentFilter(id)
)
//Check if alarm is already running
alarmManager?.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + ensurePositiveTime,
pendingIntent
)
Log.e("Alarm", "Alarm updated..!")
}
/**
* This will receive broadcast after completed seconds
*/
private fun getBroadcastReceiver(): BroadcastReceiver {
return object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
createNotification()
}
}
}
/***
* It creates notification
*/
private fun createNotification() {
val channelId = "fcm_default_channel"
val channelName = "notification"
val defaultSoundUri =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this@MyActivity, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("I am alarm from my activity")
.setContentTitle(getString(R.string.app_name))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
val mNotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_HIGH
)
notificationBuilder.setChannelId(channelId)
mNotificationManager.createNotificationChannel(channel)
}
val notification = notificationBuilder.build()
mNotificationManager.notify(0, notification)
}
/**
* Use this to cancel alarm
*/
private fun cancelAlarm() {
if (pendingIntent != null) {
alarmManager?.cancel(pendingIntent)
}
if (broadcastReceiver != null) {
unregisterReceiver(broadcastReceiver)
broadcastReceiver = null
}
Log.e("Alarm", "Alarm has been canceled..!")
}
}
下面是 java 代码
public class AlarmActivity extends AppCompatActivity {
private AlarmManager alarmManager;
private PendingIntent pendingIntent;
private int REQUEST_CODE = 45645;
private String id = "myname";
private long timeInMilliSeconds = 5000;
static String APP_TAG = "classname";
private BroadcastReceiver broadcastReceiver;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
initAlarm();
}
private void initAlarm() {
//creating intent
Intent intent = new Intent(id);
boolean alarmRunning = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_NO_CREATE
) != null;
//setting broadcast
broadcastReceiver = new MyReceiver();
registerReceiver(
broadcastReceiver,
new IntentFilter(id)
);
//setting alarm
long ensurePositiveTime = Math.max(timeInMilliSeconds, 0L);
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
//Check if alarm is already running
if (!alarmRunning) {
alarmManager.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + ensurePositiveTime,
pendingIntent
);
} else {
updateAlarm();
Log.e("Alarm", "Alarm already running.!");
}
}
private void updateAlarm() {
//calculating alarm time and creating pending intent
Intent intent = new Intent(id);
long ensurePositiveTime = Math.max(timeInMilliSeconds, 0L);
pendingIntent = PendingIntent.getBroadcast(
this,
REQUEST_CODE,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
//removing previously running alarm
alarmManager.cancel(pendingIntent);
unregisterReceiver(broadcastReceiver);
//setting broadcast
broadcastReceiver = new MyReceiver();
registerReceiver(
broadcastReceiver,
new IntentFilter(id)
);
//Check if alarm is already running
alarmManager.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + ensurePositiveTime,
pendingIntent
);
Log.e("Alarm", "Alarm updated..!");
}
/**
* Use this to cancel alarm
*/
private void cancelAlarm() {
if (pendingIntent != null) {
alarmManager.cancel(pendingIntent);
}
if (broadcastReceiver != null) {
unregisterReceiver(broadcastReceiver);
broadcastReceiver = null;
}
Log.e("Alarm", "Alarm has been canceled..!");
}
}
BroadCastReceiver class
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
createNotification(context);
WakeLocker.release();
}
/***
* It creates notification
* @param context
*/
private void createNotification(Context context) {
String channelId = "fcm_default_channel";
String channelName = "notification";
Uri defaultSoundUri =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("I am alarm from my activity")
.setContentTitle(context.getString(R.string.app_name))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel =
new NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_HIGH
);
notificationBuilder.setChannelId(channelId);
mNotificationManager.createNotificationChannel(channel);
}
Notification notification = notificationBuilder.build();
mNotificationManager.notify(0, notification);
}
}
Wake Locker class 也可以在后台保持 运行ning,但是为此你必须从应用程序设置中启用后台服务并禁用省电模式
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context c) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) c.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, AlarmActivity.APP_TAG);
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null){
wakeLock.release();
}
wakeLock = null;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<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/Theme.Alarmdemo">
<activity android:name=".AlarmActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.example.alarmdemo.MyReceiver" />
</application>
您的这部分代码似乎有误:
notificationIntent.setAction("com.example.basicalarmsetter.MatchNotification");
您在这里使用的是 class 名称。你需要使用广播接收器的动作,你放在你的意图过滤器中的那个,a.k.a:
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);
}
}
我有一个适合我的解决方案。设置警报如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
long delayInMillis = 5000;//your delay in millisecond
Intent myIntent = new Intent(this, AlertReceiver.class);
//any data you want to pass to your receiver class
myIntent.putExtra(AlertReceiver.TITLE, "Scheduled Alert");
myIntent.putExtra(AlertReceiver.CONTENT, "You have scheduled alert. Tap here to view continue...");
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, delayInMillis, pendingIntent);
}
}
在您的清单中添加接收者
<receiver android:name=".utils.AlertReceiver" />//path to your receiver
您的警报接收器 class 可以是这样的
public class AlertReceiver extends BroadcastReceiver {
private static final String TAG = "AlertReceiver";
public static final String TITLE = "title";
public static final String CONTENT = "content";
@Override
public void onReceive(Context context, Intent receivedIntent) {
String title = receivedIntent.getStringExtra(TITLE);
String message = receivedIntent.getStringExtra(CONTENT);
Log.e(TAG, "onReceive: " + title + ":" + message);
//you can show your notification or anything you want to do once you receive your alert here...
}
}
希望这对您有所帮助。编码愉快!!