Notification launched by date from sqlite db - sqlite

In my app i keep date (dd-mm-yyyy) in SQLite DB, and i want to launch 1 day before that date te notification.
Am i doing something wrong that notification is not starting?
public class AlarmReceiver extends BroadcastReceiver {
BHItem currentItem;
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager mNM;
mNM = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "Return time",System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);
notification.setLatestEventInfo(context, context.getText(R.string.alarm_service_label), currentItem.getItem() + " return to: " + currentItem.getReturndate(), contentIntent);
mNM.notify(R.string.alarm_service_label, notification);
notification.flags|= Notification.FLAG_AUTO_CANCEL;
}
}
AlarmManager class
here im tring to compare current date with date from database, and if its 1 day bef
public class AlarmService {
private BHItem alarmDate;
private Context context;
private PendingIntent mAlarmSender;
public AlarmService(Context context) {
this.context = context;
mAlarmSender = PendingIntent.getBroadcast(context, 0, new Intent(context, AlarmReceiver.class), 0);
}
public void startAlarm(){
Calendar currentDate = Calendar.getInstance();
Calendar myDate= Calendar.getInstance();
try {
Date convDate = new SimpleDateFormat("dd-MM-yyyy").parse(alarmDate.getReturndate());
myDate.setTime(convDate);
if (currentDate.compareTo(myDate)== 1) {
long dd = myDate.getTimeInMillis();
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, dd, mAlarmSender);
}
} catch (Exception e) {
// Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
Also i tried to start alarm with this, but still nothing
public void startAlarm(){
Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, 10);
long firstTime = c.getTimeInMillis();
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, firstTime, mAlarmSender);
}
in Manifest i added
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<application...
<receiver android:process=":remote" android:name="AlarmReceiver"></receiver>
thanks for any clues and help

I've tested this code and onReceive is not getting fired. I order to make it work, you should set a intent filter in your receiver config in Manifest. And then use the same filter when setting the intent for your alarm. Set receiver in manifest like this:
<receiver
android:name="AlarmReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.NOTIFY" />
</intent-filter>
</receiver>
And then change this code snippet:
mAlarmSender = PendingIntent.getBroadcast(context, 0, new Intent(context, AlarmReceiver.class), 0);
To this:
mAlarmSender = PendingIntent.getBroadcast(context, 0, new Intent("android.intent.action.NOTIFY"), 0);
Those changed made this working on API 15. Make sure to test this solution first with short time alarm set to fire after few seconds, it's much easier to debug it this way.

Related

BroadcastReceiver does not work on Android 12

In my Xamarin Forms project I have:
[BroadcastReceiver(Permission = "RECEIVE_BOOT_COMPLETED",
Exported = true,
Enabled = true)]
[IntentFilter(new[] {Intent.ActionBootCompleted})]
public class GeofenceReceiver: BroadcastReceiver
I use it for GeofenceTransitionEnter and GeofenceTransitionExit events.
I also have ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION permissions.
But OnReceive method is not called on API 31. I have not this problem with lower APIs.
Android 12 targetSDKVersion 31 challenges (Broadcast Receiver, Pending Intent) Crash Issues - doesn't work for me
I have done a sample to test. And it worked well, the OnReceive method will call a few minutes after the device restarted.
The receiver:
[BroadcastReceiver(Permission = "RECEIVE_BOOT_COMPLETED",
Exported = true,
Enabled = true)]
[IntentFilter(new[] { Intent.ActionBootCompleted })]
public class GeofenceReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
//launch our activity
if (intent.Action == "android.intent.action.BOOT_COMPLETED")
{
Toast.MakeText(context,"Device Restart",ToastLength.Long).Show();
Intent intent1 = new Intent(context,typeof(ForegroundServiceDemo));
intent1.SetFlags(ActivityFlags.NewTask);
context.StartForegroundService(intent1);
}
}
}
The foreground service:
[Service]
public class ForegroundServiceDemo : Service
{
private string NOTIFICATION_CHANNEL_ID = "1000";
private int NOTIFICATION_ID = 1;
private string NOTIFICATION_CHANNEL_NAME = "notification";
private void startForegroundService()
{
var notifcationManager = GetSystemService(Context.NotificationService) as NotificationManager;
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
createNotificationChannel(notifcationManager);
}
var notification = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
notification.SetAutoCancel(false);
notification.SetOngoing(true);
notification.SetSmallIcon(Resource.Mipmap.icon);
notification.SetContentTitle("ForegroundService");
notification.SetContentText("Foreground Service is running");
StartForeground(NOTIFICATION_ID, notification.Build());
}
private void createNotificationChannel(NotificationManager notificationMnaManager)
{
var channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME,
NotificationImportance.Low);
notificationMnaManager.CreateNotificationChannel(channel);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
startForegroundService();
return StartCommandResult.NotSticky;
}
}
The AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
      <uses-permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
I added the RECEIVE_BOOT_COMPLETED into the AndroidManifes.xml, because if I just added it in the [BroadcastReceiver], the receiver will not work. So you can also try to add it in the AndroidManifes.xml.
In addition, you can create a new project to test my code. It worked on Android 12.0 emulator when I tested it. Finally, if it still not work, could you please show the code in the OnReceive method? Maybe the OnReceive method was called, but the code in it can't run background such as start an activity.
I just added something like this into GepfencePendingIntent:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
} else {
PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
I found it here: https://www.flybuy.com/android-12-pendingintent-mutability-and-geofences

Task running once a day on Xamarin Forms

I started using xamarin a few months ago, and, until now, I didn't have the need of doing something like this.
I'm developing an app that, once a day, should run a WCF web service and verify if an information is true. If it is true, it should show a notification on the device.
My problem is that I don't know how to perform it, i've read about backgrounding and schedule tasks, but I didn't understand well how can I perform this. How can I do it using Xamarin.Forms?
Thank you!
For Android, a solution needs 4 components:
AlarmManager to set daily check schedule
BroadCastReceiver to receive the daily trigger and call the IntentService
IntentService to execute awaitable calls
OnBootReceiver to ensure alarms are set again after a device reboot
For iOS, you will most likely need remote push notifications.
Some sample code below for the Android components:
AlarmManager - Setting the Alarm
[assembly: Dependency(typeof(AlarmHelper))] // above the namespace
...
class AlarmHelper: IAlarm
{
var now = Calendar.Instance;
var alarmTime = Calendar.Instance;
alarmTime.Set(CalendarField.HourOfDay, settings.AlarmHour); // Set Alarm start Hour
alarmTime.Set(CalendarField.Minute, settings.AlarmMinutes); // Set Alarm Start Minutes
if (alarmTime.Before(now))
{
alarmTime.Add(CalendarField.Hour, 24);
}
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.SetRepeating(AlarmType.RtcWakeup, alarmTime.TimeInMillis, AlarmManager.IntervalDay, pendingIntent);
}
BroadCastReceiver - Receiving the Alarm
[BroadcastReceiver]
class ScheduledAlarmHandler : WakefulBroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Console.WriteLine("ScheduledAlarmHandler", "Starting service #" + SystemClock.ElapsedRealtime());
Intent service = new Intent(context, typeof(WakefulAPIService));
StartWakefulService(context, service);
}
}
IntentService - Executing awaitable calls
[Service]
[IntentFilter(new String[] { "com.test.testApp.WakefulAPIService" })]
class WakefulAPIService : IntentService
{
protected override void OnHandleIntent(Intent intent)
{
// Your API Call code here
Console.WriteLine("WakefulAPIService", "Completed service # " + SystemClock.ElapsedRealtime());
Android.Support.V4.Content.WakefulBroadcastReceiver.CompleteWakefulIntent(intent);
}
}
OnBootReceiver - Ensuring alarms are set again after a device reboot
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "android.intent.action.BOOT_COMPLETED", "android.intent.action.QUICKBOOT_POWERON" })]
class OnBootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Console.WriteLine("On Boot Reveiver", "Alarm Set Again after Reboot");
var alarmHelper = new AlarmHelper();
alarmHelper.SetAlarm();
}
}
The required permissions for this to work are 'RECEIVE_BOOT_COMPLETED' and 'WAKE_LOCK'
In this case for Android you can use you can use JobScheduler, see this class
[Service(Name = "com.xamarin.samples.downloadscheduler.DownloadJob",
Permission = "android.permission.BIND_JOB_SERVICE")]
public class DownloadJob : JobService
{
public override bool OnStartJob(JobParameters jobParams)
{
Task.Run(() =>
{
//Your periodic task here
});
return true;
}
public override bool OnStopJob(JobParameters jobParams)
{
//true so we re-schedule the task
return true;
}
}
Then you can create a Factory to call this service.
public static class ReadLocationSchedulerFactory
{
public static JobInfo.Builder CreateJobBuilderUsingJobId<T>(this Context context, int jobId) where T : JobService
{
var javaClass = Java.Lang.Class.FromType(typeof(T));
var componentName = new ComponentName(context, javaClass);
return new JobInfo.Builder(jobId, componentName);
}
}
Then in your Main Activity you have to call the Factory.
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App172S.App());
#region Scheduler
var jobBuilder = this.CreateJobBuilderUsingJobId<ReadLocationScheduler>(152);
//This means each 20 mins
jobBuilder.SetPeriodic(20 * 60 * 1000);
//Persists over phone restarts
jobBuilder.SetPersisted(true);
//If Fails re-try each 2 mins
jobBuilder.SetBackoffCriteria(120 * 1000, BackoffPolicy.Linear);
var jobInfo = jobBuilder.Build();
var jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
jobScheduler.Cancel(152);
var scheduleResult = jobScheduler.Schedule(jobInfo);
if (JobScheduler.ResultSuccess == scheduleResult)
{
//If OK maybe show a msg
}
else
{
//If Failed do something
}
#endregion
}

android with out using google cloud

how to get Notification with out using google cloud . i thought of running a thread in back ground service and update the Notification but how i can i do it.pls help me out thanks in advance
public class BackgroundThread implements Runnable {
#Override
public void run() {
List<InvoiceDetail> invoiceDetails = JsonReader.getInvoice();
if (invoiceDetails.size() > 0) {
NotificationManager nfman = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int notifyID = 1;
NotificationCompat.Builder builder = new NotificationCompat.Builder(
LoginActivity.this).setContentTitle("WORK ASSIGNED")
.setContentText("You've received new messages.");
builder.setContentText("hai");
nfman.notify(1, builder.build());
}
}
}
public class Notifier extends BroadcastReceiver {
#SuppressWarnings("deprecation")
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sPrefs = context.getSharedPreferences("loginData", 0);
String id = sPrefs.getString("id", "default value");
String userss = sPrefs.getString("user", "default value");
String pass = sPrefs.getString("pass", "default value");
if (id.trim().length() > 0) {
List<NotifierDetail> subjects = DataBase.notificationMethod(id);
if (subjects.size() > 0) {
User user = new User();
user.setUserName(userss);
user.setPassWord(pass);
User users = DataBase.login(user);
BaseConstants.user = users;
for (NotifierDetail sub : subjects) {
NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(
R.drawable.logo, " Notification Today",
System.currentTimeMillis());
notification.defaults=Notification.DEFAULT_SOUND;
notification.defaults=Notification.DEFAULT_VIBRATE;
DataBase.updateNotificationMethod(sub.getId());
notification.flags = Notification.FLAG_AUTO_CANCEL;
Intent in = new Intent(context, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 0,
in, 0);
CharSequence name = "Notification";
CharSequence mess = name + " about " + sub.getSubject();
notification.setLatestEventInfo(context, name, mess, pi);
nm.notify(0, notification);
}
}
}
}
}

No effect on notification click in Android

I am using a local notification in my application like this.
showNotification(this, "Title1", "Message One", 1);
showNotification(this, "Title2", "Message Two", 2);
showNotification(this, "Title3", "Message Three", 3);
showNotification(this, "Title4", "Message Four", 4);
public static void showNotification(Context con, String title,
String message, int id) {
NotificationManager manager = (NotificationManager) con
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification note = new Notification(R.drawable.ic_noti_logo,title, System.currentTimeMillis());
Intent notificationIntent = new Intent(con,Result.class);
notificationIntent.putExtra("Message", message);
notificationIntent.putExtra("NotiId", id);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(con, 0,
notificationIntent, PendingIntent.FLAG_ONE_SHOT);
note.setLatestEventInfo(con, title, message, pi);
note.defaults |= Notification.DEFAULT_ALL;
note.flags |= Notification.FLAG_AUTO_CANCEL;
manager.notify(id, note);
}
in Resut.java
message = getIntent().getStringExtra("Message");
notiId = getIntent().getIntExtra("NotiId", 0);
showAlert(message,notiId);
private void showAlert(String msg, int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(msg).setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// finish();
cancelNotification(Result.this,id);
}
});
AlertDialog alert = builder.create();
alert.show();
}
public static void cancelNotification(Context con, int id) {
NotificationManager manager = (NotificationManager) con
.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(id);
}
my problem is that, I am getting 4 notification message in notification bar and when I am clicking any of them I am redirecting to Result Activity but it hapens only ones when second time I clicked there was no effect. please help me.
The problem is that the four notifications share the same PendingIntent because they reference equivalent Intents (the docs for Intent.filterEquals() explain that to be considered distinct, Intents must differ in either action, data, class, type, or categories—note that extras are specifically not considered when determining whether Intents are equal). Furthermore, you're using PendingIntent.FLAG_ONE_SHOT which guarantees the PendingIntent can only be used once.

Not getting the notification from NotificationCompat.Builder

i want to generate a notification bar showing the progress via builder method but i dont know where i am going wrong.if anyone who can tell me where i am wrong and help me i will be thankful.....
public class DownloadReceiver extends ResultReceiver{
private final static String TAG = "DownloadReceiver";
public Context context;
public DownloadReceiver(Handler handler,Context context) {
super(handler);
this.context = context;
Log.d(TAG,handler.getLooper().getThread().getName());
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
Log.d(TAG,"in download receiver");
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
Intent notifyIntent = new Intent(android.content.Intent.ACTION_VIEW,Uri.parse("http://www.android.com"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, 0);
if(resultCode == DownloadService.COMPLETED){
Log.d(TAG,resultCode + "");
Builder notificationBuilder = new NotificationCompat.Builder(context)
.setProgress(100, 20, false)
.addAction(R.drawable.ic_action_search, "title", pendingIntent)
.setWhen(System.currentTimeMillis());
// notification.flags = Notification.FLAG_ONGOING_EVENT;
// notification.setLatestEventInfo(context, "contentTitle", "contentText", pendingIntent);
notificationManager.notify(50, notificationBuilder.build());
}else if(resultCode == DownloadService.ALLCOMPLETED){
}
}
}
I just had to deal with this just now, the solution for me was that you have to add a notification image
.setSmallIcon(R.drawable.launcher)
otherwise it won't show anything. The old notification method didn't require you to set this yourself, as it would default to the app's icon.

Resources