BroadcastReceiver does not work on Android 12 - xamarin.forms

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

Related

Xamarin.Forms AudioManager not toggling SpeakerPhone with Android 10, 11, 12, 13

I have this background service that toggles speakerphone during inbound/outbound calls without any success! Why and how can I fix it?
Thanks in Advance!!!!!!!
[Service]//(IsolatedProcess = true)]
public class PhoneCallService : Service
{
public override void OnCreate()
{
base.OnCreate();
}
public override IBinder OnBind(Intent intent)
{
return null;
//throw new NotImplementedException();
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
base.OnStartCommand(intent, flags, startId);
MainActivity.audioManager = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
int WaitTime = 30;
Task.Run(async () =>
{
while (true)
{
if (MainActivity.audioManager.SpeakerphoneOn)
{ MainActivity.audioManager.SpeakerphoneOn = false; }
else { MainActivity.audioManager.SpeakerphoneOn = true; }
await Task.Delay(TimeSpan.FromSeconds(WaitTime));
}
});
}
}
This background service should toggle SpeakerPhone ON/OFF every thirty seconds during InBound/OutBound Calls. But it doesn't. It used to work on Android 10, 11, 12 but not now!
Perhaps on Android 13 there may be a different way to address this in Xamarin.Forms. Some of the methods I tried failed.
There is a known issue about this, you can follow it up here:
SpeakerPhone not activating on Android 13 under Android Studio and Visual Studio.
And you can check the similar thread here:
How to turn-on SpeakerPhone for incoming call in Xamarin.Forms Android 13.

Is there a way to use the camera functions in Xamarin Forms without downloading any extra NuGet Packages?

I am currently building a project which allows the user to take a photo of something and use that photo. I was wondering if there were any other methods out there that does not require me to download any Plugins or NuGet Packages?
You need to create a ICameraPickerService in Xamarin Forms :
public interface IPhotoPickerService
{
Task<byte[]> GetImageStreamAsync();
}
In iOS , create the CameraPickerService :
[assembly: Dependency(typeof(CameraPickerService))]
namespace DependencyServiceDemos.iOS
{
public class CameraPickerService: ICameraPickerService
{
TaskCompletionSource<byte[]> taskCompletionSource;
UIImagePickerController imagePicker;
public Task<byte[]> GetImageStreamAsync()
{
// Create and define UIImagePickerController
imagePicker = new UIImagePickerController
{
SourceType = UIImagePickerControllerSourceType.Camera,
MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.Camera)
};
// Set event handlers
imagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia;
imagePicker.Canceled += OnImagePickerCancelled;
// Present UIImagePickerController;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
var viewController = window.RootViewController;
viewController.PresentModalViewController(imagePicker, true);
// Return Task object
taskCompletionSource = new TaskCompletionSource<byte[]>();
return taskCompletionSource.Task;
}
void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)
{
UIImage image = args.EditedImage ?? args.OriginalImage;
if (image != null)
{
// Convert UIImage to .NET Stream object
NSData data;
if (args.ReferenceUrl.PathExtension.Equals("PNG") || args.ReferenceUrl.PathExtension.Equals("png"))
{
data = image.AsPNG();
}
else
{
data = image.AsJPEG(1);
}
Stream stream = data.AsStream();
UnregisterEventHandlers();
// Set the Stream as the completion of the Task
taskCompletionSource.SetResult(data.ToArray());
}
else
{
UnregisterEventHandlers();
taskCompletionSource.SetResult(null);
}
imagePicker.DismissModalViewController(true);
}
void OnImagePickerCancelled(object sender, EventArgs args)
{
UnregisterEventHandlers();
taskCompletionSource.SetResult(null);
imagePicker.DismissModalViewController(true);
}
void UnregisterEventHandlers()
{
imagePicker.FinishedPickingMedia -= OnImagePickerFinishedPickingMedia;
imagePicker.Canceled -= OnImagePickerCancelled;
}
}
}
Not forgetting to add permission in Info.plist :
<key>NSCameraUsageDescription</key>
<string>Use Camera</string>
In addition , iOS need to run in a physical device.
In Android , create the CameraPickerService :
[assembly: Dependency(typeof(CameraPickerService))]
namespace DependencyServiceDemos.Droid
{
public class CameraPickerService : ICameraPickerService
{
public Task<byte[]> GetImageStreamAsync()
{
// Define the Intent for getting images
Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");
// Start the camera (resumes in MainActivity.cs)
MainActivity.Instance.StartActivityForResult(
getImageByCamera,
MainActivity.PickImageId);
// Save the TaskCompletionSource object as a MainActivity property
MainActivity.Instance.PickImageTaskCompletionSource = new TaskCompletionSource<byte[]>();
// Return Task object
return MainActivity.Instance.PickImageTaskCompletionSource.Task;
}
}
}
Adding permission in AndroidMainfest.xml :
<uses-permission android:name= "android.permission.CAMERA" />
<uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE" />
Get Image data in MainActivity :
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
internal static MainActivity Instance { get; private set; }
public int CAMERA_JAVA_REQUEST_CODE = 1;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Instance = this;
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
DependencyService.Register<ITextToSpeechService, TextToSpeechService>();
}
// Field, property, and method for Picture Picker
public static readonly int PickImageId = 1000;
public TaskCompletionSource<byte[]> PickImageTaskCompletionSource { set; get; }
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
base.OnActivityResult(requestCode, resultCode, intent);
if (requestCode == PickImageId)
{
if ((resultCode == Result.Ok) && (intent != null))
{
Bundle bundle = intent.Extras;
Bitmap bitmap = (Bitmap)bundle.Get("data");
//// Set the Stream as the completion of the Task
MemoryStream memoryStream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 50, memoryStream);
PickImageTaskCompletionSource.SetResult(memoryStream.ToArray());
}
else
{
PickImageTaskCompletionSource.SetResult(null);
}
}
}
}
Finally , show image in ContentPage of Forms :
async void OnPickPhotoButtonClicked(object sender, EventArgs e)
{
(sender as Button).IsEnabled = false;
byte[] data = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
MemoryStream stream = new MemoryStream(data);
if (stream != null)
{
image.Source = ImageSource.FromStream(() => stream) ;
}
(sender as Button).IsEnabled = true;
}
The effect :
Note : If want to pick a Photo from the Picture Library, you can have a look at this official document .

Scanning for beacons using universal beacon library

I am trying to implement a mobile app (on iPhone) that just scans for beacons and displays a notification for each one. I am a noob with beacons/bluetooth.
I implemented it using the universal beacon library (https://github.com/andijakl/universal-beacon) and i've attached my ios bluetooth implementation.
my problem is that i receive about 12 beacon added events even though i only have two (I assume it is picking up all my other bluetooth devices). I also only receive the local name in the advertisement_received event.
My questions are:
how do I distinguish that it is a beacon being added?
how do i get the unique id an url from the beacon? (they are kontakt beacons)
Thanks for any help.
My beacon service:
public BeaconService()
{
// get the platform-specific provider
var provider = RootWorkItem.Services.Get<IBluetoothPacketProvider>();
if (null != provider)
{
// create a beacon manager, giving it an invoker to marshal collection changes to the UI thread
_manager = new BeaconManager(provider, Device.BeginInvokeOnMainThread);
_manager.Start();
_manager.BeaconAdded += _manager_BeaconAdded;
provider.AdvertisementPacketReceived += Provider_AdvertisementPacketReceived;
}
}
My ios bluetooth implementation:
public class iOSBluetoothPacketProvider : CocoaBluetoothPacketProvider { }
public class CocoaBluetoothPacketProvider : NSObject, IBluetoothPacketProvider
{
public event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
public event EventHandler<BTError> WatcherStopped;
private readonly CocoaBluetoothCentralDelegate centralDelegate;
private readonly CBCentralManager central;
public CocoaBluetoothPacketProvider()
{
Debug.WriteLine("BluetoothPacketProvider()");
centralDelegate = new CocoaBluetoothCentralDelegate();
central = new CBCentralManager(centralDelegate, null);
}
private void ScanCallback_OnAdvertisementPacketReceived(object sender, BLEAdvertisementPacketArgs e)
{
AdvertisementPacketReceived?.Invoke(this, e);
}
public void Start()
{
Debug.WriteLine("BluetoothPacketProvider:Start()");
centralDelegate.OnAdvertisementPacketReceived += ScanCallback_OnAdvertisementPacketReceived;
// Wait for the PoweredOn state
//if(CBCentralManagerState.PoweredOn == central.State) {
// central.ScanForPeripherals(peripheralUuids: new CBUUID[] { },
// options: new PeripheralScanningOptions { AllowDuplicatesKey = false });
//}
}
public void Stop()
{
Debug.WriteLine("BluetoothPacketProvider:Stop()");
centralDelegate.OnAdvertisementPacketReceived -= ScanCallback_OnAdvertisementPacketReceived;
central.StopScan();
WatcherStopped?.Invoke(sender: this, e: new BTError(BTError.BluetoothError.Success));
}
}
internal class CocoaBluetoothCentralDelegate : CBCentralManagerDelegate
{
public event EventHandler<BLEAdvertisementPacketArgs> OnAdvertisementPacketReceived;
#region CBCentralManagerDelegate
public override void ConnectedPeripheral(CBCentralManager central, CBPeripheral peripheral)
{
Debug.WriteLine($"ConnectedPeripheral(CBCentralManager central, CBPeripheral {peripheral})");
}
public override void DisconnectedPeripheral(CBCentralManager central, CBPeripheral peripheral, NSError error)
{
Debug.WriteLine($"DisconnectedPeripheral(CBCentralManager central, CBPeripheral {peripheral}, NSError {error})");
}
public override void DiscoveredPeripheral(CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI)
{
Debug.WriteLine($"Cocoa peripheral {peripheral}");
Debug.WriteLine($"Cocoa advertisementData {advertisementData}");
Debug.WriteLine($"Cocoa RSSI {RSSI}");
var bLEAdvertisementPacket = new BLEAdvertisementPacket()
{
Advertisement = new BLEAdvertisement()
{
LocalName = peripheral.Name,
ServiceUuids = new List<Guid>(),
DataSections = new List<BLEAdvertisementDataSection>(),
ManufacturerData = new List<BLEManufacturerData>()
},
AdvertisementType = BLEAdvertisementType.ScanResponse,
BluetoothAddress = (ulong)peripheral.Identifier.GetHashCode(),
RawSignalStrengthInDBm = RSSI.Int16Value,
Timestamp = DateTimeOffset.Now
};
//https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataserviceuuidskey
//if (advertisementData.ContainsKey(CBAdvertisement.DataServiceUUIDsKey))
//{
// bLEAdvertisementPacket.Advertisement.ServiceUuids.Add(
// item: new BLEManufacturerData(packetType: BLEPacketType.UUID16List,
// data: (advertisementData[CBAdvertisement.DataServiceUUIDsKey])));
//}
//https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataservicedatakey
//if (advertisementData.ContainsKey(CBAdvertisement.DataServiceDataKey))
//{
// bLEAdvertisementPacket.Advertisement.DataSections.Add(
// item: new BLEManufacturerData(packetType: BLEPacketType.ServiceData,
// data: advertisementData[CBAdvertisement.DataServiceDataKey]));
//}
//https://developer.apple.com/documentation/corebluetooth/cbadvertisementdatamanufacturerdatakey
if (advertisementData.ContainsKey(CBAdvertisement.DataManufacturerDataKey))
{
bLEAdvertisementPacket.Advertisement.ManufacturerData.Add(
item: new BLEManufacturerData(packetType: BLEPacketType.ManufacturerData,
data: (advertisementData[CBAdvertisement.DataManufacturerDataKey]
as NSData).ToArray()));
}
// Missing CBAdvertisement.DataTxPowerLevelKey
var bLEAdvertisementPacketArgs = new BLEAdvertisementPacketArgs(data: bLEAdvertisementPacket);
OnAdvertisementPacketReceived?.Invoke(this, bLEAdvertisementPacketArgs);
}
public override void FailedToConnectPeripheral(CBCentralManager central, CBPeripheral peripheral, NSError error)
{
Debug.WriteLine($"FailedToConnectPeripheral(CBCentralManager central, CBPeripheral {peripheral}, NSError {error})");
}
public override void UpdatedState(CBCentralManager central)
{
switch (central.State)
{
case CBCentralManagerState.Unknown:
Debug.WriteLine("CBCentralManagerState.Unknown");
break;
case CBCentralManagerState.Resetting:
Debug.WriteLine("CBCentralManagerState.Resetting");
break;
case CBCentralManagerState.Unsupported:
Debug.WriteLine("CBCentralManagerState.Unsupported");
break;
case CBCentralManagerState.Unauthorized:
Debug.WriteLine("CBCentralManagerState.Unauthorized");
break;
case CBCentralManagerState.PoweredOff:
Debug.WriteLine("CBCentralManagerState.PoweredOff");
break;
case CBCentralManagerState.PoweredOn:
Debug.WriteLine("CBCentralManagerState.PoweredOn");
central.ScanForPeripherals(peripheralUuids: new CBUUID[] { },
options: new PeripheralScanningOptions { AllowDuplicatesKey = true });
break;
default:
throw new NotImplementedException();
}
}
public override void WillRestoreState(CBCentralManager central, NSDictionary dict)
{
Debug.WriteLine($"WillRestoreState(CBCentralManager central, NSDictionary {dict})");
}
#endregion CBCentralManagerDelegate
}
So in case anyone is looking for this. The universal beacon library does not have an ios implementation that converts the ios packets to the universal packets. This need to be implemented.
how do I distinguish that it is a beacon being added?
I look for the Eddystone packets and if found I add to the observable list.
how do i get the unique id an url from the beacon? (they are kontakt beacons)
You need to loop through the advertisementData sent with the advertisement and create a BLEAdvertisementDataSection. copy the frame data as NSData.

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
}

Notification launched by date from sqlite db

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.

Resources