Azure MobileServiceClient LoginAsync()之后为什么Navigation.PushAsync崩溃?

时间:2016-07-17 03:46:58

标签: xamarin.android xamarin.forms azure-mobile-services

编辑: 可以在此处找到演示崩溃的示例项目:https://github.com/rringham/brokenazurexamforms - 您需要在以下位置设置自己的Azure应用服务URL:

  • 的src / BrokenAzureForms /德罗伊德/服务/用户/ DroidUserService.cs
  • 的src / BrokenAzureForms / iOS的/服务/用户/ IosUserService.cs

我在使用Azure Navigation.PushAsync()进行身份验证后尝试使用时,看到Xamarin Forms在Android上发生MobileServiceClient崩溃。此崩溃与Android隔离 - 它不会发生在iOS上。

以下是设置 - 我的基本NavigationPage作为我的主要应用页面:

MainPage = new NavigationPage(new LoginPage());

在我的LoginPage上,我使用DependencyService注入的类进行身份验证,该类在我的Android项目中执行身份验证:

private async void OnMicrosoftAccountTapped(object sender, EventArgs args)
{
    IUserService userService = DependencyService.Get<IUserService>();
    bool authenticated = await userService.LoginWithAzureAD();
    if (authenticated)
    {
        await Navigation.PushAsync(new HomePage(), false);
    }
 }

IUserService的Android实现中,我这样做(几乎就是Azure / Xamarin Forms教程显示的内容):

public async Task<bool> LoginWithAzureAD()
{
    try
    {
        _user = await _client.LoginAsync(Xamarin.Forms.Forms.Context, MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory);
    }
    catch (Exception)
    {
        return false;
    }

    return true;
}

这就是事情崩溃的地方。完成LoginWithAzureAD()后,控件将在OnMicrosoftAccountTapped()中恢复;然后我们去打电话Navigation.PushAsync(),然后热潮 - 应用程序崩溃了,只有很少的细节可以继续:

MobileServiceClient / Navigation crash

所有我能想到的是,Azure MobileServiceClient在内部使用Xamarin.Forms.Forms.Context做了一些非常时髦的事情,因为如果我删除对await userService.LoginWithAzureAD()的调用,则对Navigation.PushAsync()的调用有效没有问题。 MobileServiceClient中的某些内容要么已损坏,要么在Xamarin Forms中破坏了某些内容。

有人看到这样的东西吗?

2 个答案:

答案 0 :(得分:4)

当我这样做时,我使用以下内容:

在MainActivity.cs中:

tags = Tag.where(todo_id: { '$in': todo_ids })
tags = Tag.where(:todo_id.in => todo_ids)
tags = Tag.in(todo_id: todo_ids)
#...

然后,在我的DroidLoginProvider类中,我执行以下操作:

// Initialize for Azure Mobile Apps
Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();

// Initialize for Xamarin Forms
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

// Initialize for Login Provider
var lp = (DroidLoginProvider)DependencyService.Get<ILoginProvider>();
lp.Initialize(this);

我在共享项目中从Singleton包装器调用LoginAsync。它是Singleton非常重要,因为项目中只应该有一个MobileServiceClient - 身份验证存储在MobileServiceClient.CurrentUser属性中,并且只在当前客户端上设置。

您可以在此处查看具有此逻辑的工作项目:https://github.com/adrianhall/30-days-of-zumo-v2/tree/master/file-upload

答案 1 :(得分:4)

我认为登录问题是正交的,您从后台线程调用PushAsync。您应该等待从主线程调用您的依赖服务方法,然后在那里PushAsync

以下是一个示例: