Son*_*ali 7 c# portable-class-library xamarin xamarin.forms
嗨,我正在尝试使用PCL以xamarin形式构建应用程序.如果应用程序闲置超过10分钟或更长时间,我正尝试从我的应用程序注销用户.我通过在app即将进入睡眠状态时调用的事件来尝试它.但是如果设备screentimeout被设置为永不超时那么也许它永远不会进入睡眠状态.那么我怎样才能做到这一点.我是xamarin表格的新手.当我为所有平台构建应用程序时,我很困惑如何管理此超时?
Wol*_*urs 10
现在我使用以下方法.可能需要做一些额外的测试,以确保一切按预期工作.例如,我不确定如果应用程序(iOS或Android)在后台工作了很长时间会发生什么.定时器是否仍会每秒调用一次?也许当使用具有足够短的到期时间(约5分钟)的计时器时,这不是问题吗?等等...
我的方法基于我在网上找到的几段代码(一些Xamarin代码,一些Swift/Java代码) - 似乎没有一个很好的综合解决方案.
无论如何,一些初步测试表明这种方法工作正常.
首先,我创建了一个名为的单例类SessionManager.这个类包含一个计时器(实际上只是一个每秒睡眠的while循环)以及启动,停止和扩展计时器的方法.如果会话到期计时器到期,它还将触发事件.
public sealed class SessionManager
{
static readonly Lazy<SessionManager> lazy =
new Lazy<SessionManager>(() => new SessionManager());
public static SessionManager Instance { get { return lazy.Value; } }
SessionManager() {
this.SessionDuration = TimeSpan.FromMinutes(5);
this.sessionExpirationTime = DateTime.FromFileTimeUtc(0);
}
/// <summary>
/// The duration of the session, by default this is set to 5 minutes.
/// </summary>
public TimeSpan SessionDuration;
/// <summary>
/// The OnSessionExpired event is fired when the session timer expires.
/// This event is not fired if the timer is stopped manually using
/// EndTrackSession.
/// </summary>
public EventHandler OnSessionExpired;
/// <summary>
/// The session expiration time.
/// </summary>
DateTime sessionExpirationTime;
/// <summary>
/// A boolean value indicating wheter a session is currently active.
/// Is set to true when StartTrackSessionIsCalled. Becomes false if
/// the session is expired manually or by expiration of the session
/// timer.
/// </summary>
public bool IsSessionActive { private set; get; }
/// <summary>
/// Starts the session timer.
/// </summary>
/// <returns>The track session async.</returns>
public async Task StartTrackSessionAsync() {
this.IsSessionActive = true;
ExtendSession();
await StartSessionTimerAsync();
}
/// <summary>
/// Stop tracking a session manually. The OnSessionExpired will not be
/// called.
/// </summary>
public void EndTrackSession() {
this.IsSessionActive = false;
this.sessionExpirationTime = DateTime.FromFileTimeUtc(0);
}
/// <summary>
/// If the session is active, then the session time is extended based
/// on the current time and the SessionDuration.
/// duration.
/// </summary>
public void ExtendSession()
{
if (this.IsSessionActive == false) {
return;
}
this.sessionExpirationTime = DateTime.Now.Add(this.SessionDuration);
}
/// <summary>
/// Starts the session timer. When the session is expired and still
/// active the OnSessionExpired event is fired.
/// </summary>
/// <returns>The session timer async.</returns>
async Task StartSessionTimerAsync() {
if (this.IsSessionActive == false) {
return;
}
while (DateTime.Now < this.sessionExpirationTime) {
await Task.Delay(1000);
}
if (this.IsSessionActive && this.OnSessionExpired != null) {
this.IsSessionActive = false;
this.OnSessionExpired.Invoke(this, null);
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于Android应用程序,我然后:
配置SessionManagerMainActivity中的会话到期时注销.
覆盖该OnUserInteraction方法以MainActivity在用户交互上扩展会话计时器.
public class MainActivity /* ... */ {
protected override void OnCreate(Bundle bundle)
{
// ...
SessionManager.Instance.SessionDuration = TimeSpan.FromSeconds(10);
SessionManager.Instance.OnSessionExpired = HandleSessionExpired;
}
public override void OnUserInteraction()
{
base.OnUserInteraction();
SessionManager.Instance.ExtendSession();
}
async void HandleSessionExpired(object sender, EventArgs e)
{
await App.Instance.DoLogoutAsync();
}
}
Run Code Online (Sandbox Code Playgroud)对于iOS,我执行以下操作:
SessionManager在会话到期时配置AppDelegate中的注销.
向关键窗口添加自定义手势处理程序,以扩展用户交互的会话计时器.
public partial class AppDelegate /* ... */
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
// ...
var success = base.FinishedLaunching(app, options);
if (success) {
SessionManager.Instance.SessionDuration = TimeSpan.FromSeconds(10);
SessionManager.Instance.OnSessionExpired += HandleSessionExpired;
var allGesturesRecognizer = new AllGesturesRecognizer(delegate
{
SessionManager.Instance.ExtendSession();
});
this.Window.AddGestureRecognizer(allGesturesRecognizer);
}
return success;
}
async void HandleSessionExpired(object sender, EventArgs e)
{
await App.instance.DoLogoutAsync();
}
class AllGesturesRecognizer: UIGestureRecognizer {
public delegate void OnTouchesEnded();
private OnTouchesEnded touchesEndedDelegate;
public AllGesturesRecognizer(OnTouchesEnded touchesEnded) {
this.touchesEndedDelegate = touchesEnded;
}
public override void TouchesEnded(NSSet touches, UIEvent evt)
{
this.State = UIGestureRecognizerState.Failed;
this.touchesEndedDelegate();
base.TouchesEnded(touches, evt);
}
}
}
Run Code Online (Sandbox Code Playgroud)编辑:博洛在下面问了一个很好的问题,所以我会在这里添加.用户登录后立即调用StartTrackSessionAsync.当用户退出应用程序时,应调用EndTrackSession.
小智 6
调整了@Wolfgang 版本
public sealed class SessionManager
{
static readonly Lazy<SessionManager> lazy =
new Lazy<SessionManager>(() => new SessionManager());
public static SessionManager Instance { get { return lazy.Value; } }
private Stopwatch StopWatch = new Stopwatch();
SessionManager()
{
SessionDuration = TimeSpan.FromMinutes(5);
}
public TimeSpan SessionDuration;
public void EndTrackSession()
{
if (StopWatch.IsRunning)
{
StopWatch.Stop();
}
}
public void ExtendSession()
{
if (StopWatch.IsRunning)
{
StopWatch.Restart();
}
}
public void StartTrackSessionAsync()
{
if (!StopWatch.IsRunning)
{
StopWatch.Restart();
}
Xamarin.Forms.Device.StartTimer(new TimeSpan(0, 0, 2), () =>
{
if (StopWatch.IsRunning && StopWatch.Elapsed.Minutes >= SessionDuration.Minutes)
{
Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
{
await Prism.PrismApplicationBase.Current.Container.Resolve<INavigationService>().NavigateAsync("/Index/Navigation/LoginPage");
});
StopWatch.Stop();
}
return true;
});
}
}
Run Code Online (Sandbox Code Playgroud)
在主要活动下添加了以下内容
public override void OnUserInteraction()
{
base.OnUserInteraction();
SessionManager.Instance.ExtendSession();
}
Run Code Online (Sandbox Code Playgroud)
小智 1
不幸的是,这并不是您可以在客户端轻松完成的事情。也没有办法仅通过 PCL 来完成此操作。可能有一个插件可以添加到您的项目中,但我还没有找到。
造成这种情况的原因是 iOS 和 Android 处理应用程序生命周期的方式不同。两者非常不同。例如,一旦 iOS 挂起您的应用程序,实际上只有 2 种方法可以唤醒它。GPS 位置更新和推送通知。在 Android 中,这更容易,因为他们有 AlarmManager,您可以注册并意图为您执行注销。
我的建议是,如果您控制正在使用的 api,请让会话在服务器端过期,这样 10 分钟后传入的任何请求都会失败,并在客户端适当处理这些失败。
如果您纯粹关心应用程序何时位于前台且处于活动状态但未使用,则您将必须实现一个计时器,并在每次有用户交互时重置它。
| 归档时间: |
|
| 查看次数: |
4655 次 |
| 最近记录: |