2016-07-17 21 views
11

Edit: Przykładowy projekt, który demonstruje awarii można znaleźć tutaj: https://github.com/rringham/brokenazurexamforms - trzeba ustawić własny Azure App Obsługi URL w:Dlaczego niepowodzenie Navigation.PushAsync po uruchomieniu usługi Azure MobileServiceClient LoginAsync()?

  • src/BrokenAzureForms/Droid/Usługi/Użytkownik/DroidUserService .cs
  • src/BrokenAzureForms/iOS/Usługi/Użytkownik/IosUserService.cs

Widzę awarię Xamarin Forms pod postacią Navigation.PushAsync() na Androida, gdy próbuję go użyć po uwierzytelniania z Azure MobileServiceClient. Ta awaria jest odizolowana od Androida - nie dzieje się to na iOS.

Oto konfiguracja - Mam podstawową NavigationPage jak mój głównej stronie aplikacji:

MainPage = new NavigationPage(new LoginPage()); 

na moim LoginPage, ja uwierzytelniania przy użyciu DependencyService -injected klasę, która przeprowadza uwierzytelnianie w moim Android projektu:

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); 
    } 
} 

W moim Android realizacji IUserService, mogę to zrobić (prawie dokładnie to, co tworzy Azure/Xamarin samouczki pokazać):

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

    return true; 
} 

Oto, gdzie wszystko się rozpada. Po wykonaniu LoginWithAzureAD() sterowanie wznawia się w OnMicrosoftAccountTapped(); Następnie przejdź zadzwonić Navigation.PushAsync() oraz wysięgnik - Aplikacja ulega awarii, bardzo mało szczegółów, aby przejść na:

MobileServiceClient/Navigation crash

Wszystko, co mogę myśleć, że Azure MobileServiceClient robi coś bardzo ostry z Xamarin.Forms.Forms.Context wewnętrznie, bo jeśli Usuwam połączenie pod numer await userService.LoginWithAzureAD(), połączenie z Navigation.PushAsync() działa bez żadnych problemów. Coś w MobileServiceClient jest uszkodzone lub łamie coś w Xamarin Forms.

Ktoś widzi coś takiego?

+0

Hi @Rob Ringham, czy uda Ci się uzyskać to posortowane koniec? To jest właśnie problem, z którym obecnie borykam się i przygwoździłem go do tego samego połączenia, co ty. Dzięki. –

Odpowiedz

4

Kiedy to zrobić, używam następujące:

W 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); 

Następnie w mojej klasie DroidLoginProvider, I wykonaj następujące czynności:

Context _context; 

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

public async Task LoginAsync(MobileServiceClient client) 
{ 
    await client.LoginAsync(this._context, MobileServiceAuthenticationProvider.whatever); 
} 

I wywołaj funkcję LoginAsync z opakowania Singleton w moim udostępnionym projekcie. Ważne jest, aby był to Singleton, ponieważ w projekcie powinien znajdować się tylko jeden obiekt MobileServiceClient - uwierzytelnienie jest przechowywane we właściwości MobileServiceClient.CurrentUser i jest ustawiane tylko na bieżącym kliencie.

można zobaczyć projekt pracy z tą logiką tutaj: https://github.com/adrianhall/30-days-of-zumo-v2/tree/master/file-upload

+0

Dzięki Adrian - Spróbowałem, specjalnie dodając wywołanie inicjacyjne dla aplikacji mobilnych Azure w MainActivity, a także buforując kontekst Androida mojego dostawcy loginu z MainActivity; Zaktualizowałem kod w repozytorium Git tak, że jest to efektywna funkcjonalność równoważna z tym, co sugerujesz, ale niestety nadal widzę awarię (również postępuję zgodnie z podejściem Singleton RE: MobileServiceClient). Podam twój przykładowy projekt wiru i zobaczę, czy to działa! –

+0

Ostatni komentarz na ten temat - Używam Xamarin Forms v2.3.x w moich projektach. Istnieje wersja późniejsza, ale mam problemy z uzyskaniem właściwej kombinacji, aby uzyskać prawidłową kompilację na Androida. –

+0

Podobnie jak FYI, właśnie czytałem o Singletonach i znalazłem to na MSDN: "Główną wadą wdrożenia [Singleton] jest to, że nie jest bezpieczny dla środowisk wielowątkowych. wykonanie wpisz metodę właściwości Instance w tym samym czasie, więcej niż jedno wystąpienie obiektu Singleton. " (Zaczerpnięte z https://msdn.microsoft.com/en-us/library/ff650316.aspx) –

4

myślę kwestia logowania jest prostopadły, a ty dzwonisz PushAsync z wątku tła. Powinieneś poczekać na wywołanie metody usługi zależnej z głównego wątku, a następnie wykonać tam PushAsync.

Oto przykład: metoda

+0

Hmm, zdecydowanie nie nazywam 'PushAsync' z wątku tła - moja metoda LoginWithAzureAD jest wywoływana na wątku UI w przycisku Kliknięta obsługa zdarzeń, która z kolei (i na tym samym wątku) wywołuje' MobileServiceClient''s ' Metoda LoginAsync'. –

+0

@RobRingham Tak, to brzmi jak wątek interfejsu użytkownika. Aby wyizolować problem, spróbuj przenieść kod PushAsync do interfejsu użytkownika i poczekaj na wynik logowania, a następnie sprawdź, czy nie wystąpił wyjątek. –

+0

Nie jestem pewien, czy podążam - wywołanie 'PushAsync' jest zdecydowanie wywoływane w wątku interfejsu użytkownika po oczekiwaniu na wynik logowania (który powraca pomyślnie). Próbowałem nawet umieścić wywołanie 'PushAsync' dalej w pętli uruchamiania UI przez' Device.BeginInvokeOnMainThread() ', bezskutecznie. Wygląda na to, że coś w działaniu "MobileServiceClient" jest niezgodne ze sposobem działania Xamarin Forms na systemie Android; Podejrzewam, że może to być błąd w samej Xamarin Forms. –

Powiązane problemy