c# - Xamarin.forms Android 后台进程中的意外警报触发
问题描述
我只是想获得多个倒计时计数器,当它分别达到 0 时,我想发出警报(用户在一个和下一个之间没有任何交互)。
例如,倒计时被编程为 5、4 和 7 分钟。如果是几秒钟,并且应用程序在屏幕开启或仅几秒钟的情况下工作没有问题,但只要几分钟,屏幕就会关闭并且手机进入打盹模式(我认为),结果时间是:5、6: 26 和 9:58(而不是 5,4 和 7)。
我已经阅读了很多这里讨论过的用户解决方案,但它对我不起作用。该手机运行Android v10。
使用 SetExactAndAllowWhileIdle 对警报进行编程的代码:
public void ProgAlarm(int nIntervalo) {
var alarmIntent = new Intent(MainActivity.Instance, typeof(AlarmReceiver));
alarmIntent.PutExtra("Contador", nIntervalo);
var pending = PendingIntent.GetBroadcast(MainActivity.Instance, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
MainActivity.alarM.SetExactAndAllowWhileIdle(AlarmType.ElapsedRealtimeWakeup,
SystemClock.ElapsedRealtime()+tiempos[nIntervalo]*1000, pending);
}
并触发事件以重新编程警报:
[BroadcastReceiver]
public class AlarmReceiver: BroadcastReceiver {
public override void OnReceive(Context context, Intent intent) {
DependencyService.Get<IVarios>().Beep();
int actual=intent.GetIntExtra("Contador",-1);
if (actual!=-1) DependencyService.Get<IVarios>().ProgAlarm(++actual);
}
}
在警报之前,我尝试使用 PowerManager:
PowerManager pM = (PowerManager)GetSystemService(PowerService);
wakeLock=pM.NewWakeLock(WakeLockFlags.Partial, "CronoMultiple");
[...]
wakeLock.Acquire();
[...]
wakeLock.Release();
并带有标志:WakeLockFlags.AcquireCausesWakeup
但这仅在屏幕始终处于打开状态且带有 .Partial 标志时才有效,屏幕关闭并且应用程序停止并且计数器不起作用。在 PC 模拟器中它可以工作(即使使用 adb 命令),但不能在手机上工作。
任何不使用服务的解决方案?(我是 Xamarin.forms 的新手)。
解决方案
这是一个简单的示例,它会每 1 分钟报警一次:
界面IVarios
public interface IVarios
{
void ProgAlarm(int minute);
}
在MainActivity中,让它实现Ivarios:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,IVarios
{
public void ProgAlarm(int minute)
{
Intent intent = new Intent(MainActivity.Instance, typeof(LongRunningService));
intent.PutExtra("Contador", minute);
MainActivity.Instance.StartService(intent);
}
}
在 Android 项目中,创建LongRunningService:
[Service]
class LongRunningService : Service
{
int minutes;
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
base.OnCreate();
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
Android.Util.Log.Error("LongRunningService", "executed");
AlarmManager manager = (AlarmManager)GetSystemService(AlarmService);
int min = intent.GetIntExtra("Contador", -1);
minutes = min != -1 ? min : minutes;
int anHour = minutes * 60 * 1000; // Number of milliseconds
long triggerAtTime = SystemClock.ElapsedRealtime() + anHour;
Intent i = new Intent(this, typeof(AlarmReceiver));
PendingIntent pi = PendingIntent.GetBroadcast(this, 0, i, PendingIntentFlags.UpdateCurrent);
manager.SetExactAndAllowWhileIdle(AlarmType.ElapsedRealtimeWakeup, triggerAtTime, pi);
return StartCommandResult.Sticky;
}
}
在 Android 项目中,创建AlarmReceiver:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Intent i = new Intent(context, typeof(LongRunningService));
context.StartService(i);
}
}
然后你可以在你的页面中调用它:
DependencyService.Get<IVarios>().ProgAlarm(1);
推荐阅读
- woocommerce - Woocommerce:以编程方式向订单添加新的增值税行
- python-3.x - 将文件夹中不同文件类型的数据合并到 pandas DataFrame
- armadillo - armadillo svd 用于前几个奇异向量
- python - 用 Pipeline 和 Column Transformer 包裹类似的 Transformer 会产生不同的结果
- c++ - 普通 Makefile C++ 项目和单元测试
- javascript - Selenium:仅获取元素的直接文本
- java - heroku 将 spring 应用程序从 java 7 升级到 java 8 遇到 java.util.Map$Entry 无法解决的问题
- python-3.x - Sqlite3 var 数据库名称
- python - 如何遍历 LXML etree 并创建 XML 的方案
- dataweave - 我如何在 Mule 4 中实现 JSON 修补