Pushing notifications when app is closed - android

I am looking to create a Text-Based Android game using C# in Xamarin Forms.
In the story, I want to set the character tasks, which will take them some time e.g. "I'll go dig this hole, I'll give you a buzz when I'm done."
How do I set up notifications to appear after set times? For example the above statement may take 10 minutes, then the user receives a notification to continue the game?
I've only started C# a week ago, so I apologize if this is noobish, or already been asked. I have looked everywhere but there are several types of notification, and it seems like I'm reading french when I try to make sense of it.

I would start by creating 2 Interfaces in the PCL Project:
public interface IAlarm {
void SetAlarm();
}
public interface INotification {
void Notify(LocalNotification notification);
}
Then, in the Android Project, create the implementations:
Alarm Helper
[assembly: Dependency(typeof(AlarmHelper))]
namespace Test.Droid
{
class AlarmHelper: IAlarm
{
public void SetAlarm(int minutes)
{
var alarmTime = Calendar.Instance;
alarmTime.Add(CalendarField.Minute, minutes);
var intent = new Intent(Android.App.Application.Context, typeof(ScheduledAlarmHandler));
var pendingIntent = PendingIntent.GetBroadcast(Android.App.Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
var alarmManager = Android.App.Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
alarmManager.Set(AlarmType.RtcWakeup, alarmTime.TimeInMillis, pendingIntent);
}
}
}
Notification Helper
[assembly: Dependency(typeof(NotificationHelper))]
namespace Test.Droid
{
class NotificationHelper : INotification
{
public void Notify (string title, string text)
{
NotificationManager notificationManager = (NotificationManager) Android.App.Application.Context.GetSystemService(Context.NotificationService);
Intent intent = new Intent(Android.App.Application.Context, typeof(MainActivity));
PendingIntent pIntent = PendingIntent.GetActivity(Android.App.Application.Context, 0, intent, PendingIntentFlags.OneShot);
Notification nativeNotification = new Notification();
var builder = new NotificationCompat.Builder(Android.App.Application.Context)
.SetContentTitle(title)
.SetContentText(text)
.SetSmallIcon(Resource.Drawable.ic_notif) // 24x24 dp
.SetLargeIcon(BitmapFactory.DecodeResource(Android.App.Application.Context.Resources, Android.App.Application.Context.ApplicationInfo.Icon))
.SetPriority((int)NotificationPriority.Default)
.SetAutoCancel(true)
.SetContentIntent(pIntent);
notificationManager.Notify(0, builder.Build()); // Id 0 can be random
}
}
}
When the waiting time is over, the BroadCastReceiver will be called:
[BroadcastReceiver]
class ScheduledAlarmHandler : WakefulBroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Implement quick checking logic here if notification is still required, plus its tittle and text
// you have 10 seconds max in this method and cannot use 'await'
var notificationHelper = new NotificationHelper();
notificationHelper.Notify("Title","Text");
}
}
In the PCL project game logic, you can set a new alarm as follows:
alarmHelper = DependencyService.Get<IAlarm>();
alarmSetter.SetAlarm(10); // 10 minutes from now
I have intentionally separated the Alarm & Notification logic, to enable you to check after 10 minutes if the notification should still be displayed and set its title and text. An alternative is to pass the title and text at time of setting the alarm using intent.putextra.

Add this line to your AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
Implement BroadcastReceiver in your android project
[BroadcastReceiver]
public class NotificationBroadcastReceiver : BroadcastReceiver
{
private ApprovalDataStore _approvalDataStore => DependencyService.Get<ApprovalDataStore>();
public override async void OnReceive(Context context, Intent intent)
{
var pm = PowerManager.FromContext(context);
var wakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "GCM Broadcast Reciever Tag");
wakeLock.Acquire();
//Write your code here
// When you are finished
wakeLock.Release();
}
}

Related

How to properly handle intents in xamarin

At the moment I am using firebase messaging for my push notification. I am attaching data to my intent so I can capture it and my application can use that data when the push is clicked.
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string TAG = "MyFirebaseMsgService";
public override void HandleIntent(Intent intent)
{
CreateNotification(intent);
}
private void CreateNotification(Object e)
{
var i = e as Intent;
var bundle = i.Extras;
var intent = new Intent(this, typeof(MainActivity));
var notificationName = bundle.GetString("notificationName");
if (!string.IsNullOrEmpty(notificationName))
{
intent.PutExtra("notificationName", notificationName);
}
intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.CancelCurrent | PendingIntentFlags.UpdateCurrent);
Notification.Builder builder = new Notification.Builder(this);
builder.SetSmallIcon(Resource.Drawable.icon_notification);
builder.SetContentIntent(pendingIntent);
builder.SetLargeIcon(BitmapFactory.DecodeResource(Resources, Resource.Drawable.icon));
builder.SetContentText(body);
builder.SetDefaults(NotificationDefaults.Sound);
builder.SetAutoCancel(true);
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
builder.SetChannelId("YourChannelID");
}
NotificationManager notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(1, builder.Build());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Then on my MainActivity Side of the program, OnCreate is triggered when the application is launched back into the foreground.
protected override void OnCreate(Bundle bundle)
{
....
App.NotificationName = Intent.GetStringExtra("notificationName");
....
}
The issue I am having now is that one one of my device (Android 7 OS) it works as intended, OnCreate is triggered when the application is brought to the foreground. The issue I am having now is that OnCreate isn't triggered on my other device (Android 8 OS). Whats the best way to handle this intents and where should I put this code App.NotificationName = Intent.GetStringExtra("notificationName"); so that it'll trigger on any device
From what I understood I guess you should use OnMessageReceived then you'll be able to get your notification using by GetNotification():
public override async void OnMessageReceived(RemoteMessage message)
{
var fromNotification = message.GetNotification();
//...use message.Data and prepare the notification to notify
}
Of cource the approach depends on your remote notification payload (Notification or Data messages)
Also you can use ActivityFlags.NewTask while creating the notification:
intent = new Intent(Application.Context, typeof(MainPage));
flags = PendingIntentFlags.CancelCurrent;
intent.SetFlags(ActivityFlags.NewTask);
But you will have to create your MainActivity as LaunchMode.SingleTop and will able to handle notification toast taps at OnNewIntent(Intent intent) and OnCreate(Bundle bundle) using by Intent instance from those overriden methods. (For OnCreate you should use Intent property of your Activity)

Scheduling a local Notification with System Date and notifies without launching the App (Xamarin.Forms)

Am trying to schedule a local notification depending on the time set in SQLite , I am using a certain library in this link :
local Notification library
I have implemented it well, but am still facing the problems below:
a) The notification comes only when I launch the App.
b)All notification time notifies once which are stored locally in SQLite.
Now how can I make this Application to capture the system time (Phone time)
and it notifies like an Alarm without even launching the Application
Am I supposed to use one of these methods:
i) OnSleep
ii)OnResume etc or...
So below is how I was placing my code in App.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using Diabetes.localDB;
using Diabetes.Main;
using Newtonsoft.Json;
using Plugin.Notifications;
using Xamarin.Forms;
namespace Diabetes
{
public partial class App : Application
{
public App()
{
InitializeComponent();
// Setting the Alarm time
MedicationDatabase db = new MedicationDatabase();
//Getting list of time set in SQlite.
var alarm_list = db.GetAlarmList();
// Looping each time to make an alarm
foreach (var alarm in alarm_list)
{
try
{
Debug.WriteLine("Date Time Format : " + alarm);
//This is the library to set Notifications, Date is where the time is attached.
CrossNotifications.Current.Send(new Notification
{
Title = "Hola! ",
Message = "Hey Eddy I remind you take insulin, this is the time you told me to remind you.",
Vibrate = true,
Sound = "pop",
Date = DateTime.Parse(alarm)
});
}
catch (FormatException v)
{
Debug.WriteLine("Format Exception : " + v);
}
catch (OverflowException c)
{
Debug.WriteLine("Overflow Exception : " + c);
}
}
MainPage = new NavigationPage(new Login())
{
BarBackgroundColor = Color.FromHex("#66C8F3"),
BarTextColor = Color.White,
Title = "Diabetics App"
};
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
Now how can I make this Application to capture the system time (Phone time) and it notifies like an Alarm without even launching the Application
You can use Android.App.AlarmManager, this class provides access to the system alarm services. 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.
Since you're using XF for development, then, firstly you should be able to create a receiver for broadcast in Android Client Project for example:
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var message = intent.GetStringExtra("message");
var title = intent.GetStringExtra("title");
var resultIntent = new Intent(context, typeof(MainActivity));
resultIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
var pending = PendingIntent.GetActivity(context, 0,
resultIntent,
PendingIntentFlags.CancelCurrent);
var builder =
new Notification.Builder(context)
.SetContentTitle(title)
.SetContentText(message)
.SetSmallIcon(Resource.Drawable.Icon)
.SetDefaults(NotificationDefaults.All);
builder.SetContentIntent(pending);
var notification = builder.Build();
var manager = NotificationManager.FromContext(context);
manager.Notify(10010, notification);
}
}
Then in XF, when we need to use native method of each platform from PCL, we can use DependencyService to implement it.
In PCL, create an interface like this:
public interface ISetAlarm
{
void SetAlarm(int hour, int minute);
}
Then, in Android client project, implement this interface for example like this:
[assembly: Xamarin.Forms.Dependency(typeof(SetAlarmImplementation))]
namespace YOURNAMESPACE.Droid
{
public class SetAlarmImplementation : ISetAlarm
{
public void SetAlarm(int hour, int minute)
{
Intent myintent = new Intent(Xamarin.Forms.Forms.Context, typeof(AlarmReceiver));
var pendingintent = PendingIntent.GetBroadcast(Xamarin.Forms.Forms.Context, 0, myintent, PendingIntentFlags.UpdateCurrent);
Java.Util.Date date = new Java.Util.Date();
Java.Util.Calendar cal = Java.Util.Calendar.Instance;
cal.TimeInMillis = Java.Lang.JavaSystem.CurrentTimeMillis();
cal.Set(Java.Util.CalendarField.HourOfDay, hour);
cal.Set(Java.Util.CalendarField.Minute, minute);
cal.Set(Java.Util.CalendarField.Second, 0);
AlarmManager alarmManager = Xamarin.Forms.Forms.Context.GetSystemService(Android.Content.Context.AlarmService) as AlarmManager;
alarmManager.Set(AlarmType.RtcWakeup, cal.TimeInMillis, pendingintent);
}
}
}
Then finally when you want to call this from PCL, you can call it like this:
DependencyService.Get<ISetAlarm>().SetAlarm(13, 30);

Android - Trouble with service sending multiple local notifications

I've inherited a code base for an Android app and I'm facing a particularly though problem with local notifications.
The idea is to send a notification for each event which is scheduled in the future, considering also the reminder preference on how many minutes before the event the user wants to be notified.
Everything works just fine, except that after the notification is thrown for the first time, if the user opens the app before the event starts, the notification gets thrown another time. This happens every time the app is opened between (event start date - reminder) and event start date.
I've already gave a look at this and also this with no luck.
I've read that using a service may cause exactly this problem and some suggest to remove it but I think this is needed since the notification must be thrown also when the app is closed.
Currently the structure of the code is the following:
Edit - updated description of TabBarActivity
Inside TabBarActivity I have the method scheduleTravelNotification that schedules the AlarmManager.
This method is executed everytime there is a new event to be added on local database, or if an existing event have been updated.
The TabBarActivity runs this method inside the onCreate and onResume methods.
TabBarActivity is also the target of the notification - onclick event.
private static void scheduleTravelNotification(Context context, RouteItem routeItem) {
long currentTime = System.currentTimeMillis();
int alarmTimeBefore = routeItem.getAlarmTimeBefore();
long alarmTime = routeItem.getStartTime() - (alarmTimeBefore * 1000 * 60);
if(alarmTimeBefore < 0){
return;
}
if(alarmTime < currentTime){
return;
}
Intent actionOnClickIntent = new Intent(context, TravelNotificationReceiver.class);
PendingIntent travelServiceIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis(), actionOnClickIntent, PendingIntent.FLAG_ONE_SHOT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(alarmTime);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), travelServiceIntent);
Log.e("NEXT ALARM", "Time: " + String.valueOf(calendar.getTimeInMillis()));
}
This is TravelNotificationReceiver.java (should I use LocalBroadcastReceiver instead of BroadcastReceiver?)
public class TravelNotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("RECEIVER", "received TravelNotification request");
Intent notificationIntent = new Intent(context, TravelNotificationService.class);
context.startService(notificationIntent);
}
}
TravelNotificationService.java extends NotificationService.java setting as type = "Travel", flags = 0, title = "something" and text = "something else".
public abstract class NotificationService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
sendNotification();
return super.onStartCommand(intent, flags, startId);
}
public abstract String setNotificationType();
public abstract int setNotificationFlags();
public abstract String setNotificationTitle();
public abstract String setNotificationText();
/**
* Executes all the logic to init the service, prepare and send the notification
*/
private void sendNotification() {
int flags = setNotificationFlags();
String type = setNotificationType();
NotificationHelper.logger(type, "Received request");
// Setup notification manager, intent and pending intent
NotificationManager manager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intentAction = new Intent(this.getApplicationContext(), TabBarActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intentAction, flags);
// Prepares notification
String title = setNotificationTitle();
String text = setNotificationText();
Notification notification = NotificationHelper.buildNotification(getApplicationContext(), title, text, pendingIntent);
// Effectively send the notification
manager.notify(101, notification);
NotificationHelper.logger(type, "Notified");
}
}
Edit - Here's the code for NotificationHelper.buildNotification
public static Notification buildNotification(Context context, String title, String text, PendingIntent pendingIntent) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setAutoCancel(true);
builder.setContentText(text);
builder.setContentTitle(title);
builder.setContentIntent(pendingIntent);
builder.setSmallIcon(R.mipmap.launcher);
builder.setCategory(Notification.CATEGORY_MESSAGE);
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
return builder.build();
}
Thank you for the answers!
Edit I've seen also this but has no accepted answers, while this post suggest something that I think it's already managed with if(alarmTime < currentTime){ return; } in scheduleTravelNotification.
This may not be your exact problem, but at a glance, you're sending the notification in onStartCommand() which can itself be run many times during the lifetime of the service -- for example, if you issue the service start command "blindly" in an onCreate of an activity, it will happen every time the activity is (re)created.
You have a few options for handling this.
One is to create a boolean flag as a property of the service, default to false, and check it before sending the notification. If it's false, send the notification and set it to true, and if it's already true you do not send a notification.
Another is to check and see if the service is already running, and if it is, don't send the service start command in the first place. This can be tedious to do everywhere, and violates DRY, so if you take this route you may want to create a static method in your service class which checks to see if the service is running and then starts it if not, and call that instead of explicitly starting the service.
Similar to user3137702 answer you could simple have a static boolean of APPISINFORGROUND which is checked everytime the send notification method is hit, and managed from your application/activities code.
As User said it is likely that your onStartCommand method is being called at odd times due to the app / service lifecycle.
Alternatively check your receiver is not being called somewhere else from your code.
It may be your NotificationHelper class which is causing an issue. Please share the code for this class.
One thought may be that your notification is not set to be auto cancelled, check if you include the setAutoCancel() method in your Notification Builder.
Notification notification = new Notification.Builder(this).setAutoCancel(true).build();
I've found a way to make it work, I'm posting this since it seems to be a problem of many people using the approach suggested in this and this articles. After months of testing I can say I'm pretty satisfied with the solution I've found.
The key is to avoid usage of Services and rely on AlarmScheduler and Receivers.
1) Register the receiver in your manifest by adding this line:
<receiver android:name="<your path to>.AlarmReceiver" />
2) In your activity or logic at some point you want to schedule a notification related to an object
private void scheduleNotification(MyObject myObject) {
// Cal object to fix notification time
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(myObject.getTime());
// Build intent and extras: pass id in case you need extra details in notification text
// AlarmReceiver.class will receive the pending intent at specified time and handle in proper way
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("OBJECT_ID", myObject.getId());
// Schedule alarm
// Get alarmManager system service
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(getBaseContext().ALARM_SERVICE);
// Build pending intent (will trigger the alarm) passing the object id (must be int), and use PendingIntent.FLAG_UPDATE_CURRENT to replace existing intents with same id
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), myObject.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Finally schedule the alarm
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
}
3) Define AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Find object details by using objectId form intent extras (I use Realm but it can be your SQL db)
MyObject myObject = RealmManager.MyObjectDealer.getObjectById(intent.getStringExtra("OBJECT_ID"), context);
// Prepare notification title and text
String title = myObject.getSubject();
String text = myObject.getFullContent();
// Prepare notification intent
// HomeActivity is the class that will be opened when user clicks on notification
Intent intentAction = new Intent(context, HomeActivity.class);
// Same procedure for pendingNotification as in method of step2
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(context, myObject.getId(), intentAction, PendingIntent.FLAG_UPDATE_CURRENT);
// Send notification (I have a static method in NotificationHelper)
NotificationHelper.createAndSendNotification(context, title, text, pendingNotificationIntent);
}
}
4) Define NotificationHelper
public class NotificationHelper {
public static void createAndSendNotification(Context context, String title, String text, PendingIntent pendingNotificationIntent) {
// Get notification system service
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
// Build notification defining each property like sound, icon and so on
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context);
notificationBuilder.setContentTitle(title);
notificationBuilder.setContentText(text);
notificationBuilder.setSmallIcon(R.drawable.ic_done);
notificationBuilder.setCategory(Notification.CATEGORY_MESSAGE);
notificationBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setContentIntent(pendingNotificationIntent);
notificationBuilder.setDefaults(Notification.DEFAULT_SOUND);
notificationManager.notify(1001, notificationBuilder.build());
}
}
At this point it should work and schedule / trigger notification at the right time, and when notification is opened it will appear only once starting the activity declared in notification pending intent.
There is still a problem, AlarmManager have a "volatile" storage on user device, so if user reboots or switch off the phone you will lose all intents that you previously scheduled.
But fortunately there is also a solution for that:
5) Add at top of your manifest this uses permission
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
6) Right below the line added at step 1 register the boot receiver
<receiver android:name="<your path to>.BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
7) Define the BootReceiver
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do something very similar to AlarmReceiver but this time (at least in my case) since you have no source of intents loop through collection of items to understand if you need to schedule an alarm or not
// The code is pretty similar to step 3 but repeated in a loop
}
}
At this point your app should be able to schedule / trigger notification and restores those reminders even if the phone is switched off or rebooted.
Hope this solution will help someone!

Not sure of what to choose between Service, BroadcastReceiver and AlarmManager

Hello guys i am building an app in which i would like to add subscription. That means that every user has to pay monthly.
So i want to check if the user has paid he will be able to proceed with the orders if he didn't then i want a dialog to redirect him to pay. What would you suggest me to use Service, BroadcastReceiver or AlarmaManager?
I was thinking of creating a Service and within it create an AsyncTask that will check to the database if the user has paid and then if not inform the user with a dialog. Also i was thinking of creating Notiofications to the user that the subscription ending.
What is your opinion???
I developed a similar function to check many bills. I combined the three methods to ensure stability. But I think you should use Google Play In-app Billing to achieve subscriptions instead of using a local database. If you must use a database to subscribe:
1.After users subscribe, saved info to the database and start a service. the service start a thread,the thread get Data and Analyzing user payments. then use AlarmManager to set Notification and stopSelf.
public class NotificationService extends Service {
...
private AlarmManager am;
private PendingIntent pi;
private NotificationManager mNM;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread thread = new Thread(null, mTask, "AlarmService_Service");
thr.start();
return START_REDELIVER_INTENT;
}
Runnable mTask = new Runnable() {
public void run() {
List<Subscription> mDataList = getData;
if (mDataList.size() > 0) {
for (Subscription mSubscription : mDataList) {
if (mSubscription.isSub == true) {
Intent intent = new Intent(NotificationService.this,
AlamrReceiver.class);
intent.putExtra("data", (Serializable)mSubscription);
intent.setData(Uri.parse("custom://" + uniqueCode));
intent.setAction(String.valueOf(uniqueCode));
am = (AlarmManager) getSystemService(ALARM_SERVICE);
pi = PendingIntent.getBroadcast(
NotificationService.this, uniqueCode, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
am.set(AlarmManager.RTC_WAKEUP, reminderTime, pi);
uniqueCode = uniqueCode + 1;
}
}
}
NotificationService.this.stopSelf();
}
};
}
2.Receive broadcast information and show Notification.
public class AlamrReceiver extends BroadcastReceiver {
private NotificationManager mNM;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
mNM = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Subscription mSubscription = intent.getSerializableExtra("data");
if (mSubscription != null) {
showNotification(context, mSubscription);
}
}
private void showNotification(Context context, Subscription mSubscription) {
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context);
builder.setContentTitle(text);
builder.setContentText(subTitleString + currencyString);
builder.setSmallIcon(Common.CATEGORY_ICON[cIcon]);
builder.setDefaults(Notification.DEFAULT_VIBRATE);
builder.setAutoCancel(true);
Intent intent = new Intent(context, BillDetailsActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(BillDetailsActivity.class);
intent.putExtra("dataMap", (Serializable) tMap);
stackBuilder.addNextIntent(intent);
PendingIntent contentIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
int uniqueRequestCode = (int) System.currentTimeMillis();
mNM.notify(uniqueRequestCode, builder.build());
}
}
Do not forget BOOT_COMPLETED , when the phone restarted , start the service and check the database
I am not sure of concept of your app, but if you want to check whether user has subscribed for current month or not, you don't need to run a Service for that.
You should check this in Splash Screen or Main Activity of your app. But anyways,
if you still need to do this, i suggest to go with Service or AlarmManager.
BroadcastReceiver won't work alone, you need to trigger them on particular events according to your need.
Also if you use service, please keep in mind that Android MIGHT kill your service in low memory kind of situation.
So i'll suggest that you should go with AlarmManager, which will check for subscription status after specific time or something.
PS : i know this should be addded as comment, but i don't have enough reputations to comment so posted as answer

How to know make notification when user doesn't executing application

I'd like to make an notification which start to count time when user exited android application. If user do not executed application after 1hours, It notified me to execute and If user ignoring it, It executes saved SMS messages. I found some examples on timer, but I do not know how to find application exit time. Please give me some advice with full code. I am desperately need it...
TimerTask task = new TimerTask(){
public void run() {
try {
mainTime++;
int min = mainTime / 60;
int sec = mainTime % 60;
String strTime = String.format("%s : %s", min, sec);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Timer mTimer = new Timer();
mTimer.schedule(task, 0, 60000);
Intent sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.putExtra("Chack your app", smsBody);
sendIntent.putExtra("12345678", phonenumber);
sendIntent.setType("vnd.android-dir/mms-sms");
startActivity(sendIntent);
Okay so what you need to do is to store the system time locally (may be using SharedPreferences) when the application exits. You can register a BroadcastReceiver which will help you trigger some action when 1hr or a certain time has passed from the locally stored time when app exited.
If you want to know how to handle programmatically when and how to exit the app , please refer this answer.
You could also try to use the Android alarm system. Once the user exit your application, you could set up an Alarm. Something like:
YourActivityOrFragment.java
#Override
protected void onStop() {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
c.add(Calendar.HOUR,1);
scheduleAlarm(c.getTimeInMillis());
}
private void scheduleAlarm(long time) {
Intent yourIntent = new Intent("Some_ID");
PendingIntent pi = PendingIntent.getBroadcast(YourClass.this, ALARM_ID, yourIntent, PendingIntent.FLAG_CANCEL_CURRENT);
// Put some extras here, if you need so. Like:
// yourIntent.putExtra("field","value");
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,time,pi);
}
Now, create a BroadcastReceiver to handle those alarms.
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
private static final String LOG_TAG = AlarmReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG, "Alarm fired!");
Intent it = new Intent(context, YourNotificationHandler.class);
// Get your Extras here. And do whatever you want, if you need.
// For what you said, there's no need to start an Activity, so let's handle that alarm as a service.
context.startService(it);
// But if for some reason you want to start an Activity, just do it like:
// context.startActivity(it);
}
}
On your AndroidManifest.xml declare your BroadcastReceiver.
<receiver android:name=".AlarmReceiver" >
<intent-filter>
<action android:name="Some_ID" />
<category android:name="android.intent.category.default" />
</intent-filter>
</receiver>
And last of all, create your service to handle your notifications, you could try something like an IntentService. On that file, you'll have a onHandleIntent(Intent intent) method. Get your Intent there, and it's Extras, and do whatever you want to do. Later, just call your Notifications. I've used a utility class on my projects to handle those, but feel free to choose how you'll do that.
Example:
public static void createService(Context context, CharSequence tickerMessage, CharSequence title,
CharSequence message, int icon, int id, Intent intent, long[] pattern, Boolean autoCancel) {
PendingIntent p = PendingIntent.getService(context, 0, intent, 0);
Notification n;
int apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= 11) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(title)
.setTicker(tickerMessage)
.setContentText(message)
.setSmallIcon(icon)
.setContentIntent(p)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
if (pattern.length > 0) {
builder.setVibrate(pattern);
}
if (autoCancel != null) {
builder.setAutoCancel(autoCancel);
}
if (apiLevel >= 17) {
// Android 4.2+
n = builder.build();
}
else {
// Android 3.x
n = builder.getNotification();
}
}
else {
// Android 2.2+
n = new Notification(icon, tickerMessage, System.currentTimeMillis());
// Data
n.setLatestEventInfo(context, title, message, p);
}
NotificationManager nm = (NotificationManager)
context.getSystemService(Activity.NOTIFICATION_SERVICE);
nm.notify(id, n);
}
You can read more about alarms here.
More on Service here.
BroadcastReceiver here.
Notifications, here and here.
And this might be an interesting read about Notification as well.

Categories

Resources