Related
I'm building a music player app and I have a problem with the notification part I think all of my code about the notification is right but when I tap at notification controller buttons broadcast receiver don't work.
AndroidManifest:
<receiver android:name=".notification.NotificationController">
<intent-filter>
<action android:name="com.ydp.eight_d_musicplayer.ACTION_NOTIFY_PLAY_PAUSE"/>
<action android:name="com.ydp.eight_d_musicplayer.ACTION_NOTIFY_SKIP_NEXT"/>
<action android:name="com.ydp.eight_d_musicplayer.ACTION_NOTIFY_SKIP_PREVIOUS"/>
</intent-filter>
</receiver>
My Broadcast:
public class NotificationController extends BroadcastReceiver {
public static String ACTION_NOTIFY_PLAY_PAUSE = "com.ydp.eight_d_musicplayer.ACTION_NOTIFY_PLAY_PAUSE";
public static String ACTION_NOTIFY_SKIP_NEXT = "com.ydp.eight_d_musicplayer.ACTION_NOTIFY_SKIP_NEXT";
public static String ACTION_NOTIFY_SKIP_PREVIOUS = "com.ydp.eight_d_musicplayer.ACTION_NOTIFY_SKIP_PREVIOUS";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_NOTIFY_PLAY_PAUSE)){
if (Player.player.isPlaying()){
Player.player.pause();
}else {
Player.player.start();
}
} else if (intent.getAction().equals(ACTION_NOTIFY_SKIP_PREVIOUS)){
Toast.makeText(context, "previous", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context, "next", Toast.LENGTH_SHORT).show();
}
}
}
And My Service:
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,new Intent(this, MainActivity.class),0);
Intent previous = new Intent();
previous.setAction(ACTION_NOTIFY_SKIP_PREVIOUS);
Intent play = new Intent();
play.setAction(ACTION_NOTIFY_PLAY_PAUSE);
Intent next = new Intent();
play.setAction(ACTION_NOTIFY_SKIP_NEXT);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Notification.Builder notification = new Notification.Builder(this, "playback")
.setSmallIcon(R.drawable.music_icon)
.setContentTitle(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE))
.setContentText(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) + " . " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST))
.setLargeIcon(songCover)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.addAction(R.drawable.ic_skip_previous_black_24dp,"previous",PendingIntent.getBroadcast(this,11,previous,PendingIntent.FLAG_UPDATE_CURRENT))
.addAction(R.drawable.ic_pause_black_24dp,"play",PendingIntent.getBroadcast(this,12,play,PendingIntent.FLAG_UPDATE_CURRENT))
.addAction(R.drawable.ic_skip_next_black_24dp,"next",PendingIntent.getBroadcast(this,13,next,PendingIntent.FLAG_UPDATE_CURRENT))
.setContentIntent(pendingIntent);
Notification.MediaStyle mediaStyle = new Notification.MediaStyle();
mediaStyle.setBuilder(notification);
startForeground(1, mediaStyle.build());
}
Help, please!
Initialize the Intents like this:
new Intent(this, NameOfTheClass.class);
In cases where you are in coroutine for example use
applicationContext
I have implemented android notifications in android studio. I was creating notification for a media player. following is the function for showing notifications
public void showNotification(int playPauseBtn)
{
Intent intent = new Intent(this, PlayerActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
Intent prevIntent = new Intent(this, NotificationReceiver.class).setAction(ACTION_PREVIOUS);
PendingIntent prevPending = PendingIntent.getBroadcast(this, 0, prevIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent pauseIntent = new Intent(this, NotificationReceiver.class).setAction(ACTION_PLAY);
PendingIntent pausePending = PendingIntent.getBroadcast(this, 0, pauseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent nextIntent = new Intent(this, NotificationReceiver.class).setAction(ACTION_NEXT);
PendingIntent nextPending = PendingIntent.getBroadcast(this, 0, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
byte[] picture = null;
try
{
picture = getAlbumArt(listSongs.get(position).getPath());
} catch (Exception ignored)
{
}
Bitmap thumb;
if (picture != null)
{
thumb = BitmapFactory.decodeByteArray(picture, 0, picture.length);
} else
{
thumb = BitmapFactory.decodeResource(getResources(), R.drawable.icon_music);
}
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID_1).setSmallIcon(playPauseBtn)
.setLargeIcon(thumb)
.setContentTitle(listSongs.get(position).getTitle())
.setContentText(listSongs.get(position).getArtist())
.addAction(R.drawable.ic_baseline_skip_previous_24, "Previous", prevPending)
.addAction(R.drawable.ic_baseline_skip_next_24, "Next", nextPending)
.addAction(playPauseBtn, "pause", pausePending)
.setStyle(new androidx.media.app.NotificationCompat.MediaStyle().setMediaSession(mediaSessionCompat.getSessionToken()))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOnlyAlertOnce(true)
.setContentIntent(contentIntent)
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
Toast.makeText(PlayerActivity.this, "Nitification created", Toast.LENGTH_SHORT).show();
}
In the function parameter (playPauseBtn) I am sending the play icon or the pause icon depending upon weather the song is playing or is paused.
Function call is made like following:
showNotification(R.drawable.ic_baseline_pause_24);
OR
showNotification(R.drawable.ic_baseline_play_arrow_24);
But when ever I call this function the notification doesn't show up. I am also using the notification channel but still it is not working. I have also tried to debug the code but the code runs fine, still the notification doesn't show up. please advise
try this.
put this code in your Activity/fragment;
public void getNotification(){
int notifId =new Random().nextInt(500); //get random id
NotificationManager notificationManager;
Notification notification;
notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channelID = "1";
channelName = "news";
channelDesc = "news description";
NotificationChannel notificationChannel = new NotificationChannel(channelID, channelName, NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription(channelDesc);
notificationChannel.enableLights(true);
notificationChannel.setSound(null, null);
notificationChannel.setLightColor(Color.GREEN);
notificationManager.createNotificationChannel(notificationChannel);
}
RingtoneManager.getRingtone(mContext,
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)).play();
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, channelID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title Of MUSIC")
.setContentText("Content")
.setVibrate(new long[]{100, 500, 500, 500, 500})
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
Intent actionReadMessage = new Intent(mContext, NotifAction.class);
actionReadMessage.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
actionReadMessage.setAction("Play");
actionReadMessage.putExtra("NotifId",notifId);
PendingIntent playPendingIntent = PendingIntent.getBroadcast(mContext, notifId, actionReadMessage,PendingIntent.FLAG_CANCEL_CURRENT);
Intent mainAction = new Intent(mContext, NotifAction.class);
mainAction.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
mainAction.setAction("Pause");
mainAction.putExtra("NotifId",notifId);
PendingIntent PausePendingIntent = PendingIntent.getBroadcast(mContext, notifId, mainAction,PendingIntent.FLAG_CANCEL_CURRENT);
builder.setContentIntent(PausePendingIntent);
builder.addAction(R.mipmap.ic_launcher, "Play", playPendingIntent);
builder.addAction(R.mipmap.ic_launcher, "Pause", PausePendingIntent);
notification = builder.build();
notificationManager.notify(notifId, notification);
}
and create class NotifAction.class for handle all action:
public class NotifAction extends BroadcastReceiver {
private static final String TAG = "maybe";
private MediaPlayer mp;
#Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
Bundle extra = intent.getExtras();
if (extra != null) {
int notifId = extra.getInt("NotifId");
if (action.equals("Play")) {
mp = MediaPlayer.create(context, R.raw.music);
handleMusicState(mp);
} else if (action.equals("Pause")) {
handleMusicState(mp);
setMessageRead(notifId, context);
} else {
Toast.makeText(context, "extra action !", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(context, "Empty extra !", Toast.LENGTH_SHORT).show();
}
}
private void setMessageRead(int id, Context context) {
// other method
clearNotification(id, context);
}
private void clearNotification(int id, Context context) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(id);
}
private void handleMusicState(MediaPlayer mediaPlayer) {
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
else mediaPlayer.start();
}
}
define this receiver to manifest:
note:in tag
<receiver android:name=".NotifAction">
<intent-filter>
<action android:name="Play" />
<action android:name="Pause" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
FIX
Donot use .setMediaSession(mediaSessionCompat.getSessionToken()) in .setStyle() in the code given in the question
simply just use
.setStyle(new androidx.media.app.NotificationCompat.MediaStyle())
I am writing a simple Android program that triggers an alarm 15 seconds after the application initialization (plays the default ringtone and pushes a notification) through AlarmManager. Below is my code:
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()
}
}
This seems strange, consdering that I have specified my MatchNotification class as a receiver in my AndroidManifest.xml file.
Devices Tested On:
Motorola Moto E6 (Android 9)
Emulator for Pixel 2 (API 26)
Note: The solution should have the MainActivity code in Java
This part of your code seems wrong:
notificationIntent.setAction("com.example.basicalarmsetter.MatchNotification");
You're using the class name here. You need to use the action of the broadcast receiver, the one you put in your intent filter, a.k.a:
notificationIntent.setAction("com.example.notificationtest.MatchNotification");
Another issue: You're creating two alarms, which is unnecessary, at here:
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);
At this section, following lines are unnecessary:
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, futureInMillis, pendingIntent);
assert alarmManager != null;
The value RTC_WAKEUP is supposed to be used with System.currentTimeMillis(), not SystemClock.elapsedRealtime().
The final of your MainActivity.java would look like this:
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);
}
}
i have a solution that worked for me. Set alert as follow:
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);
}
}
add reveiver in your manifest
<receiver android:name=".utils.AlertReceiver" />//path to your receiver
your alert receiver class can be something like this
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...
}
}
hope this helps. Happy codding!!
Hi it seems to be like you haven't checked that is alarm running in the background or not and there must be some old code
Try the below code just paste it and nothing to do extra with AndroidManifest file and run.
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..!")
}
}
Below is java code
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 to keep running in background also, but for this you have to enable background services from app setting and disable the power saving mode
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>
I still cannot get my AlarmReceiver class' onReceive method to fire. Does anything stick out as wrong with this implementation?
All this is supposed to do is wait a certain period of time (preferably 6 days) and then pop up a notification. (Can you believe there isn't a built in system for this? crontab anyone!?)
MyActivity and BootReceiver both set up an alarm under the necessary conditions. AlarmService kicks out a notification. And AlarmReceiver is supposed to catch the alarm and kick off AlarmService, but it has never caught that broadcast, and won't no matter what I do.
Oh, and I've been testing on my Droid X, 2.3.4. Project being built against API 8.
P.S. Most of this has been adapted from http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/
------------ MyActivity.java ------------
public class MyActivity extends Activity implements SensorEventListener {
private void setupAlarm() {
Log.i(TAG, "Setting up alarm...");
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, AlarmReceiver.class), 0);
// Get alarm trigger time from prefs
Log.i(TAG, "Getting alarm trigger time from prefs...");
SharedPreferences mPrefs2 = PreferenceManager.getDefaultSharedPreferences(context);
long trigger = SocUtil.getLongFromPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER);
Log.i(TAG, "Trigger from prefs: " + trigger + " (" + new Date(trigger).toString() + ").");
// If alarm trigger is not set
if(trigger == new Long(-1).longValue()) {
// Set it
trigger = new Date().getTime() + NOTIFY_DELAY_MILLIS;
SocUtil.saveLongToPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER, trigger);
Log.i(TAG, "Trigger changed to: " + trigger + " (" + new Date(trigger).toString() + ").");
// And schedule the alarm
alarmMgr.set(AlarmManager.RTC, trigger, pendingIntent);
Log.i(TAG, "Alarm scheduled.");
}
// If it is already set
else {
// Nothing to schedule. BootReceiver takes care of rescheduling it after a reboot
}
}
}
------------ AlarmService.java ------------
public class AlarmService extends IntentService {
public AlarmService() {
super("AlarmService");
}
#Override
public void onHandleIntent(Intent intent) {
Log.i(AlarmConst.TAG, "AlarmService invoked.");
this.sendNotification(this);
}
private void sendNotification(Context context) {
Log.i(AlarmConst.TAG, "Sending notification...");
Intent notificationIntent = new Intent(context, Splash.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
NotificationManager notificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon, "Test1", System.currentTimeMillis());
notification.setLatestEventInfo(context, "Test2", "Test3", contentIntent);
notificationMgr.notify(0, notification);
}
}
------------ AlarmReceiver.java ------------
public class AlarmReceiver extends BroadcastReceiver {
// onReceive must be very quick and not block, so it just fires up a Service
#Override
public void onReceive(Context context, Intent intent) {
Log.i(AlarmConst.TAG, "AlarmReceiver invoked, starting AlarmService in background.");
context.startService(new Intent(context, AlarmService.class));
}
}
------------ BootReceiver.java ------------
(to restore wiped alarms, because stuff I schedule with the OS isn't important enough to stick around through a reboot -_-)
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(AlarmConst.TAG, "BootReceiver invoked, configuring AlarmManager...");
Log.i(AlarmConst.TAG, "Setting up alarm...");
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, AlarmReceiver.class), 0);
// Get alarm trigger time from prefs
Log.i(AlarmConst.TAG, "Getting alarm trigger time from prefs...");
SharedPreferences mPrefs2 = PreferenceManager.getDefaultSharedPreferences(context);
long trigger = SocUtil.getLongFromPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER);
Log.i(AlarmConst.TAG, "Trigger from prefs: " + trigger + " (" + new Date(trigger).toString() + ").");
// If trigger exists in prefs
if(trigger != new Long(-1).longValue()) {
alarmMgr.set(AlarmManager.RTC, trigger, pendingIntent);
Log.i(AlarmConst.TAG, "Alarm scheduled.");
}
}
}
------------ Manifest ------------
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<activity
android:name=".MyActivity"
android:label="#string/app_name" >
</activity>
<receiver android:name="com.domain.app.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name="com.domain.app.AlarmReceiver"></receiver>
<service android:name="com.domain.app.AlarmService"></service>
Here is some code I recently used to make a notification every hour (This is in my MainActivity):
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent Notifyintent = new Intent(context, Notify.class);
PendingIntent Notifysender = PendingIntent.getBroadcast(this, 0, Notifyintent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 3600000, Notifysender);
Then in Notify.java
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class Notify extends BroadcastReceiver{
#SuppressWarnings("deprecation")
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager myNotificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "Update Device", 0);
Intent notificationIntent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, "Device CheckIn", "Please run Device CheckIn", contentIntent);
notification.flags |= Notification.FLAG_HIGH_PRIORITY;
myNotificationManager.notify(0, notification);
}
}
Then lastly in the AndroidManifest.xml I have this in between the tags:
<receiver android:name=".Notify" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.NOTIFY" />
</intent-filter>
</receiver>
I have the main code that I know works at the office, feel free to email me for more help as I faced the same issues.
email: sbrichards at mit.edu
You must register your AlarmReceiver with an intent Action. like below. and the action string must be same to what action you are broadcasting by sendBroadcast() method..
like sendBroadcast(new Intent(""com.intent.action.SOMEACTION.XYZ""));
<receiver android:name="com.domain.app.AlarmReceiver">
<intent-filter>
<action android:name="com.intent.action.SOMEACTION.XYZ" />
</intent-filter>
</receiver>
I solved this by not even using a BroadcastReceiver. Every single one of the tutorials and posts I read about how to do notification alarms (and that was A LOT) said to use a BroadcastReceiver, but apparently I don't understand something, or that's a load of crap.
Now I just have the AlarmManager set an alarm with an Intent that goes directly to a new Activity I created. I still use the BootReceiver to reset that alarm after a reboot.
This lets the notification work in-app, out-of-app, with the app process killed, and after a reboot.
Thanks to the other commenters for your time.
I am attempting to convert some code I found in a tutorial for my own use. Originally, the code launched the system contacts list when the user would click a notification generated by my app. I am trying to start an Activity of my own instead of launching the contact list, but it's not working. More specifically, nothing happens. There is no error, and my Activity doesn't load either. The notification window disappears after clicking, and the original Activity is still visible.
Here is my code:
public class MyBroadcastReceiver extends BroadcastReceiver {
private NotificationManager mNotificationManager;
private int SIMPLE_NOTFICATION_ID;
public void onReceive(Context context, Intent intent){
Bundle extras = intent.getExtras();
String deal = (String) extras.get("Deal");
String title = "Deal found at " + (String) extras.get("LocationName");
mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notifyDetails = new Notification(R.drawable.icon, title,System.currentTimeMillis());
Class ourClass;
try {
ourClass = Class.forName("com.kjdv.gpsVegas.ViewTarget");
Intent startMyActivity = new Intent(context, ourClass);
PendingIntent myIntent = PendingIntent.getActivity(context, 0,startMyActivity, 0);
notifyDetails.setLatestEventInfo(context, title, deal, myIntent);
notifyDetails.flags |= Notification.FLAG_AUTO_CANCEL;
notifyDetails.flags |= Notification.DEFAULT_SOUND;
mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
This is my entry in the AndroidManifext.xml file...
<activity android:name=".ViewTarget" android:label="#string/app_name" >
<intent-filter>
<action android:name="com.kjdv.gpsVegas.ViewTarget" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And this is my Activity that I want to launch...
public class ViewTarget extends ListActivity {
public ListAdapter getListAdapter() {
return super.getListAdapter();
}
public ListView getListView() {
return super.getListView();
}
public void setListAdapter(ListAdapter adapter) {
super.setListAdapter(adapter);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.locations);
Log.v("db", "Inside ViewTarget");
}
}
Which Android version are you running on? You might wanna try using NotificationCompat instead. This class is include in the latest support package.
Intent notificationIntent = new Intent(context, ViewTarget.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,
0, notificationIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = context.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.app_icon)
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.app_icon))
.setTicker(payload)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle("Message")
.setContentText(payload);
Notification n = builder.getNotification();
n.defaults |= Notification.DEFAULT_ALL;
nm.notify(0, n);
EDIT:
I know this is an old thread/question but this answer helped me for showing the activity when tapping the notification.
For those people that this isn't working is probably because you haven't "registered" the activity in your manifest. For example:
<activity
android:name="com.package.name.NameOfActivityToLaunch"
android:label="Title of Activity" >
<intent-filter>
<action android:name="com.package.name.NAMEOFACTIVITYTOLAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And, hopefully, this should work.
Hope it helped...
you should set action and category for Intent.
Intent startMyActivity = new Intent(context, ourClass);
startMyActivity .setAction(Intent.ACTION_MAIN);
startMyActivity .addCategory(Intent.CATEGORY_LAUNCHER);
it works
I figured out the problem. I forgot to include the package name in the activity declaration in the Manifest file.
Wrong:
activity android:name=".ViewTarget" android:label="#string/app_name"
Correct:
activity android:name="com.kjdv.gpsVegas.ViewTarget" android:label="#string/app_name"
Can you try removing the Intent filter, so it looks like this:
<activity android:name=".ViewTarget" android:label="#string/app_name" />
Also, not sure if this code will work:
ourClass = Class.forName("com.kjdv.gpsVegas.ViewTarget");
Intent startMyActivity = new Intent(context, ourClass);
Can you try it like this instead:
Intent startMyActivity = new Intent(context, ViewTarget.class);
In order to launch an Activity from an Intent, you need to add a flag:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
This is true even if you declare the class in the Intent's constructor.
check this code
public class TestActivity extends Activity {
private static final int UNIQUE_ID = 882;
public static NotificationManager nm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent navigationIntent = new Intent();
navigationIntent.setClass(classname.this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, navigationIntent,
0);
String body = "New notificattion added!!!";
String title = "Notification";
Notification n = new Notification(R.drawable.icon, body,
System.currentTimeMillis());
//this is for giving number on the notification icon
n.number = Integer.parseInt(responseText);
n.setLatestEventInfo(this, title, body, pi);
n.defaults = Notification.DEFAULT_ALL;
nm.notify(UNIQUE_ID, n);