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

Rob*_*Rob 11 xamarin.android azure-mobile-services xamarin.forms

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

  • SRC/BrokenAzureForms/Droid的/服务/用户/ DroidUserService.cs
  • SRC/BrokenAzureForms/iOS设备/服务/用户/ IosUserService.cs

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

这是设置 - 我有一个基本的NavigationPage主要应用页面:

MainPage = new NavigationPage(new LoginPage());
Run Code Online (Sandbox Code Playgroud)

在我LoginPageDependencyService身上,我使用一个在我的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);
    }
 }
Run Code Online (Sandbox Code Playgroud)

在我的Android实现中IUserService,我这样做(几乎就是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;
}
Run Code Online (Sandbox Code Playgroud)

事情就是分崩离析的地方.当LoginWithAzureAD()完成后,控制在恢复OnMicrosoftAccountTapped(); 然后我们去打电话Navigation.PushAsync(),热潮 - 应用程序崩溃,只有很少的细节继续:

MobileServiceClient /导航崩溃

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

有谁看到这样的东西?

Adr*_*all 4

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

在MainActivity.cs中:

// 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);
Run Code Online (Sandbox Code Playgroud)

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

Context _context;

public void Initialize(Context context)
{
    this._context = context;
}

public async Task LoginAsync(MobileServiceClient client)
{
    await client.LoginAsync(this._context, MobileServiceAuthenticationProvider.whatever);
}
Run Code Online (Sandbox Code Playgroud)

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

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