Я использую Xamarin для создания приложения и Android и застрял с уведомлениями.
Чего я хочу добиться:
- Появляется уведомление каждый день с указанием c час
- Он имеет две кнопки «да» и «нет»
- Пользователь может щелкнуть их, и мое приложение что-то сделает с этими данными.
Проблема:
Появляется уведомление, я закрываю приложение (просто отмахиваюсь от экрана последних приложений) и затем нажимаю на кнопку уведомления - ничего не происходит. Если я нажму на тело уведомления - приложение откроется, но мне нужно, чтобы оно выполнило некоторые действия с помощью этих кнопок.
Вот некоторые из моих исходных файлов:
MainActivity.cs
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
AnswerReciever receiver;
public static long reminderInterval = 30 * 1000; //every 30 seconds for test
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
CreateNotificationFromIntent(Intent);
receiver = new AnswerReciever();
//trying to schedule notification for specific time of the day
var alarmIntent = new Intent(this, typeof(AlarmReceiver));
var pending = PendingIntent.GetBroadcast(this, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
var alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>();
alarmManager.SetInexactRepeating(AlarmType.RtcWakeup, FirstReminder(), reminderInterval, pending);
}
public static long FirstReminder()
{
var dt = DateTime.Now;
//dt = dt.Date.AddHours(22).AddMinutes(00).AddSeconds(0);
//TODO set from user settings
var timestamp = (long)(dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
return timestamp;
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void OnNewIntent(Intent intent)
{
CreateNotificationFromIntent(intent);
}
protected override void OnResume()
{
try
{
UnregisterReceiver(receiver);
}
catch (IllegalArgumentException) { }
RegisterReceiver(receiver, new IntentFilter(Constants.ANDROID_NOTIFICATION_ACTION));
base.OnResume();
}
protected override void OnDestroy()
{
UnregisterReceiver(receiver);
base.OnDestroy();
}
protected override void OnPause()
{
base.OnPause();
}
void CreateNotificationFromIntent(Intent intent)
{
if (intent?.Extras != null)
{
string title = intent.Extras.GetString(AndroidNotificationManager.TitleKey);
string message = intent.Extras.GetString(AndroidNotificationManager.MessageKey);
DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
}
}
}
AlarmReceiver.cs
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
DependencyService.Get<INotificationManager>().ScheduleNotification(Constants.NOTIFICATION_TITLE, Constants.NOTIFICATION_TEXT);
}
}
AnswerReciever.cs
[BroadcastReceiver(Enabled = true, Exported = true)]
[IntentFilter(new[] { Constants.ANDROID_NOTIFICATION_ACTION })]
public class AnswerReciever : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);
var result = intent.GetBooleanExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ACTION, false);
var date = intent.GetStringExtra(Constants.ANDROID_NOTIFICATION_EXTRA_DATE);
var id = intent.GetIntExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ID, -1);
manager.Cancel(id);
//do something with data
}
}
AndroidNotificationManager.cs
public class AndroidNotificationManager : INotificationManager
{
const int mainActivityPendingIntentId = 0;
const int firstActionPendingIntentId = 1;
const int secondActionPendingIntentId = 2;
bool channelInitialized = false;
int messageId = -1;
NotificationManager manager;
public static string TitleKey => "Title";
public static string MessageKey => "Message";
public event EventHandler NotificationReceived;
public void Initialize()
{
CreateNotificationChannel();
}
public int ScheduleNotification(string title, string message)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}
messageId++;
var mainActivityIintent = new Intent(AndroidApp.Context, typeof(MainActivity));
var mainActivityPendingIntent = PendingIntent.GetActivity(AndroidApp.Context, mainActivityPendingIntentId, mainActivityIintent, PendingIntentFlags.OneShot);
var firstActionIntent = new Intent(Constants.ANDROID_NOTIFICATION_ACTION);
firstActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ACTION, false);
firstActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_DATE, DateTime.Now.Date.ToString("s"));
firstActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ID, messageId);
var pFirstActionIntent = PendingIntent.GetBroadcast(AndroidApp.Context, firstActionPendingIntentId, firstActionIntent, PendingIntentFlags.OneShot);
var secondActionIntent = new Intent(Constants.ANDROID_NOTIFICATION_ACTION);
secondActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ACTION, true);
secondActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_DATE, DateTime.Now.Date.ToString("s"));
secondActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ID, messageId);
var pSeconActionIntent = PendingIntent.GetBroadcast(AndroidApp.Context, secondActionPendingIntentId, secondActionIntent, PendingIntentFlags.OneShot);
var builder = new NotificationCompat.Builder(AndroidApp.Context, Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_ID)
.SetContentIntent(mainActivityPendingIntent)
.SetContentTitle(title)
.SetContentText(message)
.AddAction(Resource.Drawable.navigation_empty_icon, Constants.ANDROID_NOTIFICATION_ANSWER_NO, pFirstActionIntent)
.AddAction(Resource.Drawable.navigation_empty_icon, Constants.ANDROID_NOTIFICATION_ANSWER_YES, pSeconActionIntent)
.SetAutoCancel(true)
.SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.navigation_empty_icon))
.SetSmallIcon(Resource.Drawable.navigation_empty_icon)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);
var notification = builder.Build();
manager.Notify(messageId, notification);
return messageId;
}
public void ReceiveNotification(string title, string message)
{
var args = new NotificationEventArgs()
{
Title = title,
Message = message,
};
NotificationReceived?.Invoke(null, args);
}
void CreateNotificationChannel()
{
manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channelNameJava = new Java.Lang.String(Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_NAME);
var channel = new NotificationChannel(Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_ID, channelNameJava, NotificationImportance.Default)
{
Description = Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_DESC
};
manager.CreateNotificationChannel(channel);
}
channelInitialized = true;
}
}
Я создал образец проекта для воспроизведения моя проблема, если это поможет: https://github.com/Immelstorn/NotificationsTest