Xamarin.foms在Android的后台进程中形成意外警报触发器



我只是想获得多个倒计时计数器,当它单独达到0时,我想发出警报(用户在一个和下一个之间没有任何交互(。

例如,倒计时被编程为5、4和7分钟。如果是几秒钟,应用程序在屏幕打开的情况下工作,或者只是几秒钟,没有问题,但几分钟后,屏幕关闭,手机进入Doze模式(我认为(,结果是:5、6、26和9、58(而不是5、4和7(。

我读过很多这里讨论过的用户解决方案,但对我来说并不奏效。这款手机运行安卓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

但这只适用于屏幕始终打开并带有标志的情况。部分情况下,屏幕关闭,应用程序停止,计数器不工作。在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);

最新更新