Я разрабатываю приложение с использованием .NET MAUI, которое должно постоянно прослушивать пропущенные вызовы и отправлять номер телефона вызывающего абонента в конечную точку API. Я реализовал службу переднего плана, чтобы приложение работало в фоновом режиме. Служба работает несколько минут, но затем перестает работать, когда устройство переходит в режим ожидания или когда приложение не открывается, что приводит к пропущенным вызовам API.
Я пробовал использовать передний план service с постоянным уведомлением, но, похоже, он не обеспечивает стабильную работу службы.
Вот моя реализация: MainActivity. сс
using Android;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Util;
using AndroidX.Core.App;
using AndroidX.Core.Content;
using System.Threading;
using System.Threading.Tasks;
namespace MissedCallSMSService.Platforms.Android
{
[Service]
public class MissedCallService : Service
{
private MissedCallReceiver mReceiver;
private const int NotificationId = 1;
private string NOTIFICATION_CHANNEL_ID = "1000";
private int NOTIFICATION_ID = 1;
private string NOTIFICATION_CHANNEL_NAME = "notification";
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
// Run the service in the foreground to ensure it continues running
Notification notification = new NotificationCompat.Builder(this, "missed_call_channel")
.SetContentTitle("Missed Call Service")
.SetContentText("Listening for missed calls")
.SetSmallIcon(Resource.Drawable.maui_splash_image)
.Build();
// StartForeground(NotificationId, notification);
StartForegroundService();
// Start listening for missed calls
ListenForMissedCalls();
return StartCommandResult.Sticky;
}
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.appicon);
notification.SetContentTitle("ForegroundService");
notification.SetContentText("Foreground Service is running");
StartForeground(NOTIFICATION_ID, notification.Build());
}
private void CreateNotificationChannel(NotificationManager notificationManager)
{
var channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME,
NotificationImportance.High);
notificationManager.CreateNotificationChannel(channel);
}
private void ListenForMissedCalls()
{
mReceiver = new MissedCallReceiver();
var filter = new IntentFilter();
filter.AddAction("android.intent.action.PHONE_STATE");
RegisterReceiver(mReceiver, filter);
// Check periodically if permissions are granted and notify if not
Task.Run(() =>
{
while (true)
{
Thread.Sleep(5000); // Sleep for 5 seconds before checking again
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadPhoneState) != Permission.Granted ||
ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadCallLog) != Permission.Granted)
{
NotifyUserToGrantPermissions();
}
}
});
}
private void NotifyUserToGrantPermissions()
{
NotificationManager notificationManager = (NotificationManager)GetSystemService(NotificationService);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channel = new NotificationChannel("missed_call_channel", "Missed Call Channel", NotificationImportance.High)
{
Description = "Notifications for missed call permissions"
};
notificationManager.CreateNotificationChannel(channel);
}
var notificationIntent = new Intent(this, typeof(MainActivity));
notificationIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
var pendingIntent = PendingIntent.GetActivity(this, 0, notificationIntent, PendingIntentFlags.UpdateCurrent);
var builder = new NotificationCompat.Builder(this, "missed_call_channel")
.SetContentTitle("Missed Call Service")
.SetContentText("Please grant phone state and call log permissions.")
.SetSmallIcon(Resource.Drawable.maui_splash_image)
.SetContentIntent(pendingIntent)
.SetAutoCancel(true);
notificationManager.Notify(NotificationId, builder.Build());
}
public override void OnDestroy()
{
base.OnDestroy();
if (mReceiver != null)
{
UnregisterReceiver(mReceiver);
}
}
}
}
Мне нужно, чтобы служба постоянно работала в фоновом режиме и прослушивала пропущенные вызовы, даже когда телефон находится в режиме ожидания или приложение не открыто. Я также хочу убедиться, что необходимые разрешения запрошены и предоставлены, включая разрешения на доступ к уведомлениям. Каким изменениям или передовому опыту мне следует следовать, чтобы добиться этого?
Я разрабатываю приложение с использованием .NET MAUI, которое должно постоянно прослушивать пропущенные вызовы и отправлять номер телефона вызывающего абонента в конечную точку API. Я реализовал службу переднего плана, чтобы приложение работало в фоновом режиме. Служба работает несколько минут, но затем перестает работать, когда устройство переходит в режим ожидания или когда приложение не открывается, что приводит к пропущенным вызовам API. Я пробовал использовать передний план service с постоянным уведомлением, но, похоже, он не обеспечивает стабильную работу службы. Вот моя реализация: [b]MainActivity. сс[/b] [code]using Android; using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using Android.Provider; // For Settings.Secure using AndroidX.Core.App; using AndroidX.Core.Content; using Android.Widget;
namespace MissedCallSMSService.Platforms.Android { [Activity(Label = "MissedCallSMSService", MainLauncher = true)] public class MainActivity : Activity { const int RequestCallLogPermissionId = 0; const int RequestNotificationAccessId = 1;
void CheckAndRequestNotificationPermission() { if (!IsNotificationServiceEnabled()) { // Guide the user to the notification access settings Intent intent = new Intent(Settings.ActionNotificationListenerSettings); StartActivityForResult(intent, RequestNotificationAccessId); } }
if (requestCode == RequestCallLogPermissionId) { if (grantResults.Length > 0 && grantResults[0] == Permission.Granted) { // Permissions granted CheckAndRequestNotificationPermission(); } else { // Permissions denied Toast.MakeText(this, "Permissions denied. The app requires call log access to function properly.", ToastLength.Long).Show(); } } }
private bool IsNotificationServiceEnabled() { string pkgName = PackageName; string flat = Settings.Secure.GetString(ContentResolver, "enabled_notification_listeners"); if (flat != null && flat.Contains(pkgName)) { return true; } return false; } } } [/code] [b]MissedCallService.cs[/b] [code]using Android; using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using Android.Util; using AndroidX.Core.App; using AndroidX.Core.Content; using System.Threading; using System.Threading.Tasks;
namespace MissedCallSMSService.Platforms.Android { [Service] public class MissedCallService : Service { private MissedCallReceiver mReceiver; private const int NotificationId = 1; private string NOTIFICATION_CHANNEL_ID = "1000"; private int NOTIFICATION_ID = 1; private string NOTIFICATION_CHANNEL_NAME = "notification";
public override IBinder OnBind(Intent intent) { return null; }
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { // Run the service in the foreground to ensure it continues running Notification notification = new NotificationCompat.Builder(this, "missed_call_channel") .SetContentTitle("Missed Call Service") .SetContentText("Listening for missed calls") .SetSmallIcon(Resource.Drawable.maui_splash_image) .Build();
// Start listening for missed calls ListenForMissedCalls();
return StartCommandResult.Sticky; }
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.appicon); notification.SetContentTitle("ForegroundService"); notification.SetContentText("Foreground Service is running"); StartForeground(NOTIFICATION_ID, notification.Build()); }
private void CreateNotificationChannel(NotificationManager notificationManager) { var channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.High); notificationManager.CreateNotificationChannel(channel); }
private void ListenForMissedCalls() { mReceiver = new MissedCallReceiver();
var filter = new IntentFilter(); filter.AddAction("android.intent.action.PHONE_STATE");
RegisterReceiver(mReceiver, filter);
// Check periodically if permissions are granted and notify if not Task.Run(() => { while (true) { Thread.Sleep(5000); // Sleep for 5 seconds before checking again
if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { var channel = new NotificationChannel("missed_call_channel", "Missed Call Channel", NotificationImportance.High) { Description = "Notifications for missed call permissions" }; notificationManager.CreateNotificationChannel(channel); }
var notificationIntent = new Intent(this, typeof(MainActivity)); notificationIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask); var pendingIntent = PendingIntent.GetActivity(this, 0, notificationIntent, PendingIntentFlags.UpdateCurrent);
var builder = new NotificationCompat.Builder(this, "missed_call_channel") .SetContentTitle("Missed Call Service") .SetContentText("Please grant phone state and call log permissions.") .SetSmallIcon(Resource.Drawable.maui_splash_image) .SetContentIntent(pendingIntent) .SetAutoCancel(true);
public override void OnDestroy() { base.OnDestroy(); if (mReceiver != null) { UnregisterReceiver(mReceiver); } } } } [/code] Мне нужно, чтобы служба постоянно работала в фоновом режиме и прослушивала пропущенные вызовы, даже когда телефон находится в режиме ожидания или приложение не открыто. Я также хочу убедиться, что необходимые разрешения запрошены и предоставлены, включая разрешения на доступ к уведомлениям. Каким изменениям или передовому опыту мне следует следовать, чтобы добиться этого?