I am currently trying to set up the date picker and time picker to fire out a notification when the time is reached. I have created a method in MainActivity and this is being called from AlarmReceiver. Every time the timer reaches the set amount, the application is crashing and no errors are being shown in logcat.
I know it is something to do with this method being called from AlarmReceiver, i just don't know what the problems is. This method is also currently linked to a button which is working when pressed (buttonStopAlarm) fires a notification when pressed as wanted) so overall the method does work, it's just not working when being called from another class.
Any help would be greatly appreciated! Thank you!
AlarmReceiver
package servicealarmdemo.test2;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
MainActivity main = new MainActivity();
#Override
public void onReceive(Context arg0, Intent arg1) {
Toast.makeText(arg0, "Alarm received!", Toast.LENGTH_LONG).show();
main.addNotification();
}
}
By doing this MainActivity main = new MainActivity(); you are just creating an instance of MainActivity but it will not have it's context mean this which is basically provided when Activity is started by the OS
so move you Notification code in your Receiver and use arg0 as context
public class AlarmReceiver extends BroadcastReceiver {
//MainActivity main = new MainActivity();
Context cxt;
#Override
public void onReceive(Context arg0, Intent arg1) {
Toast.makeText(arg0, "Alarm received!", Toast.LENGTH_LONG).show();
cxt = arg0;
//main.addNotification();
addNotification();
}
public void addNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(cxt)
.setSmallIcon(R.drawable.icon_transperent)
.setContentTitle("Achieve Alert!")
.setContentText("This is a reminder for your deadline!");
Intent notificationIntent = new Intent(cxt, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(cxt, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Add as notification
NotificationManager manager = (NotificationManager)cxt.getSystemService(Context.NOTIFICATION_SERVICE);
builder.setVibrate(new long[] { 0, 1000, 1000, 1000, 1000 });
manager.notify(0, builder.build());
}
}
Related
I wanted my Application to send notification everyday to the user, following this link and doing everything as described. The app doesn't send notifications. The buildLocalNotification function is being triggered every 60 seconds, but no Notification is displayed. I kept an Interval of 2000 ms but android changed it to 60 Seconds.
Logcat Message: Suspiciously short interval 2000 millis; expanding to 60 seconds Every 60 seconds the notification function is triggered.
This is my
NotfBroadcastReceiver.class
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import androidx.core.app.NotificationCompat;
#SuppressWarnings("deprecation")
public class NotfBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Get notification manager to manage/send notifications
//Intent to invoke app when click on notification.
//In this sample, we want to start/launch this sample app when user clicks on notification
Intent intentToRepeat = new Intent(context, SplashScreen.class);
//set flag to restart/relaunch the app
intentToRepeat.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//Pending intent to handle launch of Activity in intent above
PendingIntent pendingIntent =
PendingIntent.getActivity(context, NotificationHelper.ALARM_TYPE_ELAPSED, intentToRepeat, PendingIntent.FLAG_UPDATE_CURRENT);
//Build notification
Notification repeatedNotification = buildLocalNotification(context, pendingIntent).build();
//Send local notification
NotificationHelper.getNotificationManager(context).notify(NotificationHelper.ALARM_TYPE_ELAPSED, repeatedNotification);
}
public NotificationCompat.Builder buildLocalNotification(Context context, PendingIntent pendingIntent) {
NotificationCompat.Builder builder =
(NotificationCompat.Builder) new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(android.R.drawable.arrow_up_float)
.setContentTitle("Workout Reminder")
.setAutoCancel(true);
Log.d("DEBUG", "buildLocalNotification: "+"Notification");
return builder;
}
This is my
AlarmBootReceiver.class
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AlarmBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
//only enabling one type of notifications for demo purposes
NotificationHelper.scheduleRepeatingElapsedNotification(context);
}
}
}
This is the code that turn notification on and off:
swnotf.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
{
if(b)
{
Log.d("DEBUG", "onCheckedChanged: "+ "ON");
CommonFunctions.setSwitchState(getContext(),"ON");
NotificationHelper.scheduleRepeatingElapsedNotification(getContext());
NotificationHelper.enableBootReceiver(getContext());
}
else
{
Log.d("DEBUG", "onCheckedChanged: "+"OFF");
CommonFunctions.setSwitchState(getContext(),"OFF");
NotificationHelper.cancelAlarmElapsed();
NotificationHelper.disableBootReceiver(getContext());
}
}
});
Please I have already spent THREE days trying other solutions and fixing this. I don't want to spend more time on this. Any help would be Appreciated.
Thank you.
Ok, so I have a main activity called 'Main.java'. This main activity starts an AlarmManager which fires an intent leading to 'AlarmReceiver.java'.
This 'AlarmReceiver.java' then creates a notification which has two buttons on it. One of the buttons is a deletion button, and so when the user clicks on that button, another intent is fired, leading it to 'DelPair.java'.
In DelPair.java, I modify a table in a Database, but then I need the UI of Main.java to reflect this change. I have created two functions in Main.java called updateArrayFromDB() and updateUIFromArray() to do this for me:
updateArrayFromDB() will sync an ArrayList created in Main.java to a
certain table in the DB.
updateUIFromArray() will change the UI of
Main.java to represent the ArrayList that has just been changed.
The problem is that I cannot call these two functions from DelPair.java (they don't exist in that space). I have come across Serializables in trying to find an answer but I don't know enough to know if they apply here or exactly how to implement them across the AlarmManager and the NotificationManager.
How can I access these methods from DelPair.java?
In Main.java:
public void updateArrayFromDB(){
//... The code for this is long and irrelevant
}
public void updateUIFromArray(){
//... The code for this is long and irrelevant
}
private void SendNotification() {
Intent intent = new Intent(this, AlarmReceiver.class);
//...
PendingIntent sender = PendingIntent.getBroadcast(this, 2 , intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, 5000, notif_freq, sender);
}
In AlarmReceiver.java:
Intent delPairI = new Intent(context, DelPair.class);
PendingIntent delPairPI = PendingIntent.getService(context, 0, delPairI, PendingIntent.FLAG_UPDATE_CURRENT);
Notification noti;
noti = new Notification.Builder(context)
//...
.addAction(R.drawable.ic_delete_icon, "Delete the thing", delPairPI)
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, noti);
and then in DelPair.java:
public class DelPair extends IntentService {
//...
#Override
protected void onHandleIntent(final Intent intent) {
//...
Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
getApplicationContext().sendBroadcast(it);
handler.post(new Runnable() {
#Override
public void run() {
//... here is where I update the database, which works perfectly
//now need to update the UI and array in Main.java
updateArrayFromDB(); //these lines
updateUIFromArray(); //obviously don't work
}
});
}
}
Why not use broadcasts ? in onHandleIntent just send a broadcast
Intent i = new Intent();
i.setAction(CUSTOM_INTENT);
//put relevant data in intent
getApplicationContext().sendBroadcast(i);
The broadcast receiver:
public class IncomingReceiver extends BroadcastReceiver {
private MainActivity act;
public IncomingReceiver(MainActivity main){
this.act = act;
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(CUSTOM_INTENT)) {
System.out.println("GOT THE INTENT");
// call the method on act
}
}
}
In your activity onResume - register new IncomingReceiver, onPause unregister
private IncomingReceiver receiver;
public void onCreate(Bundle bOs){
//other codes
receiver = new IncomingReceiver(this);
}
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction(CUSTOM_INTENT);
registerReceiver(receiver, filter);
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(receiver);
super.onPause();
}
Since you need to have an updated UI based on database changes, you can call updateArrayFromDB() and updateUIFromArray() in the onResume() method of your activity so the UI gets updated each time the user enters the activity.
I broadcast an Intent : com.ss.CUSTOM_INTENT
/*-----Class BroadcastReceiverApp-------*/<br/>
public class BroadcastReceiverApp extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.broadcast_activity);
}
/* #Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}*/
// broadcast a custom intent.
public void broadcastIntent(View view){
Intent intent = new Intent();
intent.setAction("com.ss.CUSTOM_INTENT");
sendBroadcast(intent);
}
}
/*------------------------*/
But when I receive that broadcast intent, I want it to be shown in notification drawer.
The Receiver class can extend only BroadcastReceiver class, hence it is now allowing to extend Activity class there by I cannot use:
Context context = getApplicationContext();
which is to be further used in Notification.Builder(context)....
This is my the Broadcast Receiver class:
public class MyReceiver extends BroadcastReceiver , Activity{
private static final int MY_NOTIFICATION_ID=1;
NotificationManager notificationManager;
Notification myNotification;
private final String myBlog = "http://android-er.blogspot.com/";
Context cont = getApplicationContext();
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(myBlog));
PendingIntent pendingIntent = PendingIntent.getActivity(
MyReceiver.this,
0,
myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification = new Notification.Builder(context)
.setContentTitle("Exercise of Notification!")
.setContentText("http://android-er.blogspot.com/")
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
Log.i(getClass().getSimpleName(),"Sucessfully Changed Time");
}
}
Can anyone help in this ? I want to later change the broadcast intent to "android.intent.action.DATE_CHANGED/TIME_CHANGED" which is even not working.
But when I receive that broadcast intent, I want it to be
shown in notification drawer.
If your question is "how to update the gui from a BroadcastReceiver" you have to put the BroadcastReceiver class inside the Activity that you want to update.
The nested BroadcastReceiver class can access the elements of the outer Activity.
For an example see
Android BroadcastReceiver within Activity
I am developing an Android prayer app for Muslims. I have already developed the code to obtain the prayer times with the help of praytimes.org. Now I want to make it so that the user is notified at that time to pray. But for now, I just want to be able to send a notification at a certain time. Looking at the code and online resources, it seems to me as if it should work but for some reason, the notification is not displaying. I know the code for the notification part is correct because I created a button to create a notification using that code and it works. So I believe the problem is with the service, receiver, or alarmManager.
My guess is the problem has to do with the onStartCommand() method in MyNotificationService.java. I am not too familiar with services and their life-cycles so please go easy on me.
Thanks in advance.
In my MainActivity.java, here is the code in my onCreate() method.
/*========================Begin Notification Code==============================*/
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, 1);
calendar.set(Calendar.YEAR, 2015);
calendar.set(Calendar.DAY_OF_MONTH, 18);
calendar.set(Calendar.HOUR_OF_DAY, 4);
calendar.set(Calendar.MINUTE, 45);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.AM_PM,Calendar.PM);
Intent intent = new Intent(MainActivity.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent,0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
/*========================End Notification Code==============================*/
Here is MyReceiver.class
package com.ahmed.omar.tawheed;
/**
* Created by Omar on 1/18/15.
*/
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Intent service = new Intent(context, MyNotificationService.class);
context.startService(service);
}
}
Here is MyNotificationService.java
package com.ahmed.omar.tawheed;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
public class MyNotificationService extends Service {
private NotificationManager notificationManager;
private int prayerNotificationID = 420; //blazeIt
#Override
public IBinder onBind(Intent arg0)
{
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();
}
#Override
public int onStartCommand(Intent intent1, int flag, int startId) {
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification n = new NotificationCompat.Builder(this)
.setContentTitle("Time to Pray")
.setContentText("It is now time to pray salah")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.setAutoCancel(true)
.build();
notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
n.flags = Notification.FLAG_AUTO_CANCEL;
// Sending the notification itself
notificationManager.notify(prayerNotificationID, n);
return START_STICKY;
}
#Override
public void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
}
}
Here are the lines from my AndroidManifest.xml
<service android:name=".MyNotificationService"
android:enabled="true" />
<receiver android:name=".MyReceiver"/>
See the documentation for Calendar.MONTH. The valid values start at 0 (for January), not 1. So, your code is trying to set an alarm on February 18, not January 18. Try changing the Calendar.MONTH value to 0 instead of 1.
This is what i do for send notification.
fun showNotification(context: Context,title: String, message: String) {
Log.e("notification", "visible")
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
val channel = NotificationChannel("1",
"NAMAJ_CHANNEL",
NotificationManager.IMPORTANCE_DEFAULT)
channel.description = "namaj alarm channel"
mNotificationManager.createNotificationChannel(channel)
}
val mBuilder = NotificationCompat.Builder(context, "1")
.setSmallIcon(com.waltonbd.muslimcalender.R.mipmap.ic_launcher) // notification icon
.setContentTitle(title) // title for notification
.setContentText(message)// message for notification
.setAutoCancel(true) // clear notification after click
val intent = Intent(context, MainActivity::class.java)
val pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
mBuilder.setContentIntent(pi)
mNotificationManager.notify(0, mBuilder.build())
}
I am learning how to build home screen widget in Android. This code is for an app widget to toggle RingerMode from NORMAL to SILENT and vice-versa.
This works fine but I need a full in-sight of logical flow (i.e which gets initiated when, goes where, does what, dies when) of all the intents in this.
Please help me understand this topic clearer.
package com.dummies.android.silentmodetoggle;
import android.app.Activity;
import android.app.IntentService;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.util.Log;
import android.widget.RemoteViews;
public class AppWidget extends AppWidgetProvider {
public static String tag ="SilentModeToggleWidget";
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d(tag, "onReceive() first line");
if(intent.getAction()==null)
{
//Do Something
Log.d(tag, "before startService()");
context.startService(new Intent(context, ToggleService.class));
}
else{
super.onReceive(context, intent);
}
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Do something in specified intervals
context.startService(new Intent(context, ToggleService.class));
}
public static class ToggleService extends IntentService{
public ToggleService(){
super("AppWidget$ToggleService");
Log.d(tag, "In ToggleService construcor");
}
#Override
protected void onHandleIntent(Intent arg0) {
Log.d(tag, "In ToggleService > onHandleIntent");
// TODO Auto-generated method stub
ComponentName cn = new ComponentName(this, AppWidget.class);
AppWidgetManager mgr = AppWidgetManager.getInstance(this);
mgr.updateAppWidget(cn, buildUpdate(this));
}
private RemoteViews buildUpdate(Context context){
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget);
AudioManager audioManager = (AudioManager)context.getSystemService(Activity.AUDIO_SERVICE);
if(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT){
updateViews.setImageViewResource(R.id.phoneState, R.drawable.phone_on);
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
else{
updateViews.setImageViewResource(R.id.phoneState, R.drawable.phone_silent);
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}
Intent i = new Intent(this, AppWidget.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
updateViews.setOnClickPendingIntent(R.id.phoneState, pi);
return updateViews;
}
}
}
still not sure on what are u asking, but I'll try to answer, if not what u want, please explain in a different way.
Intent are usually started immediatly. You create an Intent can start it by calling startService or startActivity, so for example:
context.startService(new Intent(context, ToggleService.class));
on both times you wrote the above code, the service ToggleService is immediatly started.
PendingIntent on the other hand are saved to be started at later time, so for example
updateViews.setOnClickPendingIntent(R.id.phoneState, pi);
on the above line, the AppWidget Broadcast is started when the user clicks on R.id.phoneState in your HomeScreen AppWidget.
Each PendingIntent is stored in the system with a certain ID, this ID is the requestCode parameter (you used zero on your code)... that means, that if you create a different PendingIntent with the same ID it will override it, meaning a different action will be started when the user clicks on R.id.phoneState