I'm doing a simple service that, every 10 minutes, download a WebPage (The HTML code), and notify the user if something is changed. Now, the problem is that the first 3-4 notifications are shown correctly, but after these, there's an important delay between notifications, and sometimes they don't arrive.
Here's my code:
Monitor.java
public void onCreate() {
super.onCreate();
customHandler = new android.os.Handler();
customHandler.postDelayed(runnable, 0);
}
Runnable runnable = new Runnable() {
#Override
public void run() {
RUN = true;
LINK = readMessage("ADDR");
Ion.with(getApplicationContext()).load(LINK).asString().setCallback(new FutureCallback<String>() {
#Override
public void onCompleted(Exception e, String result) {
Risultad = result;
if (fileExists(getApplicationContext(), "AVV") == false)
{
Savefile(Risultad, "AVV");
Intent i = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, i, 0);
NotificationManager notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder n = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("First")
.setContentText(Risultad.toString())
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setVibrate(new long[]{2000})
.setContentIntent(pi)
.setAutoCancel(true)
.setSmallIcon(android.R.drawable.ic_dialog_email);
notificationManager.notify(0, n.build());
}
if (fileExists(getApplicationContext(), "AVV") == true)
{
final String OldAvv = readMessage("AVV");
if (Risultad.equals(OldAvv + "\r\n") == false) {
Savefile(result, "AVV");
Intent i = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, i, 0);
NotificationManager notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder n = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Something happened")
.setContentText(result.toString())
.setContentIntent(pi)
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setSmallIcon(android.R.drawable.ic_dialog_email);
notificationManager.notify(0, n.build());
}
}
}
});
customHandler.postDelayed(this, 300000);
}
I'm using the Ion library to download the page.
readMessage, SaveFile and fileExist are used to read,save or check my HTML code stored on the device.
Sometimes, the notifications are shown when I open the app.
What can I do to receive the notifications on time?
Have a look at AlarmManager
These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running. Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
See this guide for more info and code examples
Related
I have an application that sends notifications, but when the user leaves the application the notification is still there, in case he does not click on it.
So, when the user logs out, or the session user is "null", the notifications will be automatically deleted.
My code:
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void enviarNotificacao(){
Intent intent = new Intent(this, BottomNavigation.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.putExtra("totens", listaTotem);
int id = (int) (Math.random()*1000);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setTicker("Olá Marujo!!!");
builder.setContentTitle("Capitão Cupom");
builder.setContentText("Um novo tesouro próximo de você");
builder.setSmallIcon(R.drawable.logo);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.logo));
builder.setContentIntent(pi);
builder.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(id, builder.build());
Notification n = builder.build();
n.vibrate = new long[]{150, 300, 150, 600};
notificationManager.notify(R.drawable.logo, n);
try {
Uri som = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone toque = RingtoneManager.getRingtone(this, som);
toque.play();
}catch (Exception e){
}
Sessao.instance.setSailor(sailor);
}
NotificantionManager.cancel(id) cancels a notification with that id. NoticiationManager.cancelAll() cancels all notifications from this app. Detecting when a session ends will obviously be business logic you need to build. When it happens, call one of the 2 above functions.
Override onPause() in Activity and put this inside:
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
When leaves the application call it
notificationManager.cancel(NOTIFICATION_ID);
I'm trying to figure out how to run some code when an alarmmanager alarm fires. I currently can schedule the alarms, and right now I am sending a broadcast when the alarm fires and I have a broadcast receiver to pick it up. The problem is when the user closes the app by swiping it out of recent apps, my broadcast receivers get stopped, so even when the broadcast is sent, there is no receiver to pick it up. How can I run code straight from the alarm?
Here is my code I am using right now to create a notification at a certian time:
Creating the alarm:
alarmManager.SetExactAndAllowWhileIdle(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime() + ((long)(App.checkInTimes[i].TimeOfDay.TotalSeconds - DateTime.Now.TimeOfDay.TotalSeconds) * 1000), PendingIntent.GetBroadcast(Android.App.Application.Context, 0, new Intent("android.intent.action.CREATE_CHECKIN_NOTIFICATION"), PendingIntentFlags.UpdateCurrent));
And the broadcast receiver to create the notification:
[IntentFilter(new[] { "android.intent.action.CREATE_CHECKIN_NOTIFICATION" })]
public class NotificationReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
//Send Check In Notification
//Setup notification
Notification.Builder builder = new Notification.Builder(Android.App.Application.Context);
builder.SetContentTitle("Please Check In Now");
builder.SetContentText("Tap here to check in");
builder.SetSmallIcon(Resource.Drawable.exclamationPoint);
builder.SetPriority(2);
long[] pattern = { 1000, 1000, 1000, 1000 };
builder.SetVibrate(pattern);
builder.SetLights(Android.Graphics.Color.Red, 1500, 1500);
Intent launchIntent = new Intent(Android.App.Application.Context, typeof(CheckInScreen));
PendingIntent pendingIntent = PendingIntent.GetActivity(Android.App.Application.Context, 1, launchIntent, PendingIntentFlags.UpdateCurrent);
builder.SetContentIntent(pendingIntent);
//Build notification
Notification notification = builder.Build();
notification.Flags = NotificationFlags.AutoCancel;
//Get Notification Manager
NotificationManager notificationManager = Android.App.Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;
//Publish Notification
notificationManager.Notify(0, notification);}
From this:
The problem is your BroadcastReceiver does not have the [BroadcastReceiver] attribute.
Looking at your code, this is exactly the problem. You are missing said attribute.
Try adding
[BroadcastReceiver]
before your class definition.
I am using the onDestroy method, which I have learned is not always called when app is closed. And this has created a problem for me, where I would like to have the notification pop up every time the app closed. Is there a better way to do this? By the way, onStop and onPause are not options for me, because my app runs as a background service. Interestingly, my onDestroy method works everytime my background service is running, but whenever it is turned off, and just the app interface is open, my onDestroy never is called. This seems weird because I thought that onDestroy isn't called if the device is lacking resources, and running my service would be taking up more resources than not. Idk. Any help on this would be greatly appreciated!
`#Override
public void onDestroy(){
super.onDestroy();
Log.d("asdasd","asdasdasdasdasd");
if(notif.isChecked()) {
Intent intent1 = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification noti = new Notification.Builder(this)
.setContentTitle("S-Dimmer")
.setContentText(getResources().getString(R.string.sDimmerStopped))
.setSmallIcon(R.drawable.ic_action_name1)
.setContentIntent(pIntent).getNotification();
noti.flags = Notification.FLAG_NO_CLEAR;
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(0, noti);
doas.isRunning = false;
}
}`
This method is not always called, so you should try from background service, as there's also some destruction process alert.
So please try to do what ever you want there in the services.
Please check out this ..
onDestroy() may or may not be called on any given activity or service. The general rule is that either onDestroy() is called, or your process is terminated, or your code crashed.
You don't. Your process may be terminated for any reason, at any time, by the user or by the OS. You may or may not be called with onDestroy() when that occurs. While you may be able to improve your success rate a little via onTaskRemoved() on a Service, this itself has proven unreliable, and it will not cover all scenarios.
you are doing it wrong way. In onDestroy method all other stuffs should implemented before super.onDestory()
try this
#Override
public void onDestroy(){
Log.d("asdasd","asdasdasdasdasd");
if(notif.isChecked()) {
Intent intent1 = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification noti = new Notification.Builder(this)
.setContentTitle("S-Dimmer")
.setContentText(getResources().getString(R.string.sDimmerStopped))
.setSmallIcon(R.drawable.ic_action_name1)
.setContentIntent(pIntent).getNotification();
noti.flags = Notification.FLAG_NO_CLEAR;
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(0, noti);
doas.isRunning = false;
}
super.onDestroy();
}`
onTaskRemoved()
{
if(notif.isChecked()) {
Intent intent1 = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification noti = new Notification.Builder(this)
.setContentTitle("S-Dimmer")
.setContentText(getResources().getString(R.string.sDimmerStopped))
.setSmallIcon(R.drawable.ic_action_name1)
.setContentIntent(pIntent).getNotification();
noti.flags = Notification.FLAG_NO_CLEAR;
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(0, noti);
doas.isRunning = false;
}
}
I've a date and time stored in database, I need to continuously monitor the time and date in the background and run a function in the app when that time comes, there can be set of of date and time's, i only know that i need services to do this, but not more than that. can some please tell whether this can be achieved or not? if yes, please suggest me how I can proceed further.Thank u...
Android has a very developer friendly class for that: AlarmManager
So, take the Date an Time from database, define an alarm event with it, subscribe your app for notifications for that and wait until the event comes to do the job you need to do.
this is how:
public class MyAlarm extends IntentService {
private NotificationManager myAlarmNotificationManager;
public MyAlarm() {
super("MyAlarm");
}
//this send the notification
private void sendNotification(String message) {
Log.d("MyAlarm", "Preparing to send notification...: " + message);
myAlarmNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, AlarmActivity.class), 0);
NotificationCompat.Builder alamNotificationBuilder = new NotificationCompat.Builder(
this).setContentTitle("Alarm").setSmallIcon(R.drawable.ic_launcher)
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setContentText(message);
alamNotificationBuilder.setContentIntent(contentIntent);
myAlarmNotificationManager.notify(1, alamNotificationBuilder.build());
Log.d("MyAlarm", "Notification sent.");
}
#Override
public void onHandleIntent(Intent intent) {
sendNotification("Do something");
}
}
I've got a service that scrapes a website for data then if necessary gives the user a notification.
The problem I'm having is that the notifications disappear as soon as the service closes (which could be instantly). The below code is all of the notification code the app has. I haven't put in any code to cancel the notifications.
public static void CreateNotificationCompat(int notificationID, String link, String title, String text, Context ctx)
{
Intent notificationIntent = new Intent("android.intent.action.VIEW", Uri.parse(link));
PendingIntent contentIntent = PendingIntent.getActivity(ctx.getApplicationContext(), 0, notificationIntent, 0);
NotificationManager nm = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
Resources res = ctx.getResources();
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.notify_icon)
.setWhen(System.currentTimeMillis())
.setContentTitle(title)
.setContentText(text)
.setAutoCancel(false);
Notification n = builder.getNotification();
nm.notify(notificationID, n);
}
If it makes any difference (pretty sure it doesn't) i'm using the application context here.
My services is started periodically, processes a website, notifies if needed and then closes.
At the end of my service instead of just calling stopSelf() i sleep for 30 or so seconds and then call stopSelf(). Then the notification stays for 30 seconds and then disappears. Nothing relevant appears in logcat at the time the notifications disappear.
I've only been able to test using ICS so far.
The code you have posted works. I tested it from both an activity and a service on jb, and the notification stays when the components are stopped. I even verified that I could kill the process and the notification stays. Try to strip down the app and see if the problem persists. Specifically check to see that you don't call cancel on the notification by mistake.
You seem to forgot check developer manual first. See here http://developer.android.com/guide/topics/ui/notifiers/notifications.html and look for FLAG_ONGOING_EVENT and FLAG_NO_CLEAR flags.
I've only been able to test using ICS so far.
That's why simulators are quite useful. Try it. It's part of SDK.
Please try the old way on the same device and tell us if it behaves the same way:
private static void CreateNotificationCompat(int notificationID, String link, String title, String text, Context ctx) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) ctx.getSystemService(ns);
Notification notification = new Notification(R.drawable.notify_icon, title, System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL;
PendingIntent contentIntent;
Bundle bundle = new Bundle();
Intent notificationIntent = new Intent("android.intent.action.VIEW", Uri.parse(link));
contentIntent = PendingIntent.getActivity(ctx, notificationID,
notificationIntent, 0);
notification.setLatestEventInfo(ctx, title, text,
contentIntent);
mNotificationManager.notify(notificationID, notification);
}
Just aa note this behaviour occurs when startForeground() is used and then stopSelf() is called.