【发布时间】:2021-12-27 04:53:03
【问题描述】:
我正在尝试实现一个后台服务,它会不断地通知我。为此,我使用了警报管理器和广播接收器。这是我的广播接收器代码
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new string[] {PeriodicService.AlarmService, "android.intent.action.BOOT_COMPLETED" }, Priority = (int)IntentFilterPriority.LowPriority)]
public class BackgroundReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager)context.GetSystemService(Context.PowerService);
PowerManager.WakeLock wakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "BackgroundReceiver");
wakeLock.Acquire();
Device.StartTimer(new TimeSpan(0, 0, 10), () =>
{
// do something every 60 seconds
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(Android.App.Application.Context, "Hi when app opened", ToastLength.Short).Show();
NotificationCenter.NotifyNotificationTapped(intent);
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Alarm)
.Build();
// var alarmUri = Android.Net.Uri.Parse("Resources/Audio/AlarmSound.wav");
NotificationCenter.Current.Show((notification) => notification
.WithScheduleOptions((schedule) => schedule
.Build())
.WithAndroidOptions((android) => android
.WithAutoCancel(true)
.WithChannelId("General")
.WithPriority(Plugin.LocalNotification.NotificationPriority.High)
.Build())
.WithiOSOptions((ios) => ios
.ShouldPlayForegroundSound(true)
.Build())
.WithReturningData("Dummy Data")
.WithTitle("Test Title")
.WithDescription("Test Description")
.WithNotificationId(100)
.Create());
Toast.MakeText(Android.App.Application.Context, "HI", ToastLength.Short).Show();
MessagingCenter.Send<object, string>(this, "UpdateLabel", "Hello from Android");
});
return true; // runs again, or false to stop
});
wakeLock.Release();
}
}
这是我的后台服务代码
[Service]
public class PeriodicService : Service
{
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
// From shared code or in your PCL
MessagingCenter.Send<object, string>(this, "UpdateLabel", "Hello from Android");
Device.StartTimer(new TimeSpan(0, 0, 10), () =>
{
// do something every 60 seconds
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(Android.App.Application.Context, "Hi when app closed", ToastLength.Short).Show();
});
return true; // runs again, or false to stop
});
return StartCommandResult.Sticky;
}
}
这是我的主要活动代码
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
global::Xamarin.Essentials.Platform.Init(this, savedInstanceState);
ZXing.Net.Mobile.Forms.Android.Platform.Init();
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
global::ZXing.Net.Mobile.Forms.Android.Platform.Init();
LoadApplication(new App());
Intent alarmIntent = new Intent(Application.Context, typeof(BackgroundReceiver));
BackgroundReceiver myreceiver = new BackgroundReceiver();
RegisterReceiver(myreceiver, new IntentFilter("android.intent.action.BOOT_COMPLETED"));
//StartService(new Intent(this, typeof(PeriodicService)));
// CreateNotificationChannel();
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
//DispatchNotificationThatServiceIsRunning();
//StartForegroundService(Intent);
StartService(new Intent(this, typeof(PeriodicService)));
}
else
{
StartService(new Intent(this, typeof(PeriodicService)));
}
//alarmIntent.PutExtra("message", "This is my test message!");
//alarmIntent.PutExtra("title", "This is my test title!");
//PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
//AlarmManager alarmManager = (AlarmManager)Application.Context.GetSystemService(Context.AlarmService);
//alarmManager.SetAndAllowWhileIdle(AlarmType.RtcWakeup, DateTime.Now.Millisecond + 5000, pendingIntent);
}
这是我在 manifest
中的代码<application android:theme="@style/MainTheme" android:usesCleartextTraffic="true" android:allowBackup="false" android:label="myproject">
<receiver android:name=".BackgroundReceiver" android:enabled="true" android:exported="true" android:process=":remote" android:label="myproject" />
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
这是我的我请求许可的代码。
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
global::Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
global::ZXing.Net.Mobile.Android.PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
我经历了很多解决方案,但没有任何帮助。这些是我浏览过的链接
Android - AlarmManager is not working after app is closed
Alarm Manager not working when app closed
我也尝试使用前台服务,这是我的服务代码
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
// From shared code or in your PCL
MessagingCenter.Send<object, string>(this, "UpdateLabel", "Hello from Android");
CreateNotificationChannel();
DispatchNotificationThatServiceIsRunning();
return StartCommandResult.Sticky;
}
public void DispatchNotificationThatServiceIsRunning()
{
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.SetDefaults((int)NotificationDefaults.All)
.SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
.SetSound(null)
.SetPriority(NotificationCompat.PriorityHigh)
.SetAutoCancel(false)
.SetSmallIcon(Resource.Drawable.notification_icon_background)
.SetContentTitle("test")
.SetContentText("service started")
.SetOngoing(true);
Notification bui = mBuilder.Build();
NotificationManager notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(0, bui);
StartForeground(121, bui);
}
public void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var channelName = "Notification_Channel";
var channelDescription = "Foreground Notification";
var channel = new NotificationChannel("10121", channelName, NotificationImportance.High)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
到目前为止,我在应用设置中获得了通知渠道,但通知没有显示给我。我正在使用 Redmi note 8 设备,并且我的目标 android 版本是 Android 11.0(API 级别 30)。我已经浏览了满足我要求的应用程序 StepSetGo 你可以发现在 Playstore 中你可以看到 应用程序持续显示通知 即使 应用程序被杀死,它记录了没有互联网的步数。我已经为此应用程序授予了相同的权限,例如 自动启动和无电池限制,但它仍然无法正常工作。我不知道如何解决这个问题有什么建议吗?
【问题讨论】:
-
也许我错过了...您的代码在哪里检查在运行时您的应用程序是否实际上已获得用户的权限,如果没有,是否对 Android 进行适当的调用,这将打开一个标准的 Android 对话框,用户可以接受或拒绝? docs.microsoft.com/en-us/xamarin/android/app-fundamentals/…
-
@ToolmakerSteve 我已经在我请求许可的地方添加了代码。
-
到目前为止一切顺利。现在查看Checking Permissions,并检查返回的
status。 -
@ToolmakerSteve 是的,权限很好,但应用程序在关闭时仍然没有运行。
-
可以,可以使用
FCM来实现这个功能。
标签: c# android xamarin xamarin.forms background-service