6

I am working on an Android application, backed up by an ASP.NET Core application hosted on Azure. I am using a shared Library project to test basic stuff on a Console Application project before making the functionalities for the Xamarin.Forms (Android-only) project.
The following piece of code is run after logging into the web service, where Client is a HttpClient:

public static async Task<MyClass> GetInformationAsync(string accountId)
{
    HttpResponseMessage response = await Client.GetAsync(UriData + "/" + accountId);
    response.EnsureSuccessStatusCode();
    string responseContent = await response.Content.ReadAsStringAsync();
    return JsonConvert.DeserializeObject<MyClass>(responseContent);
}

Under the same computer/network, the code finishes in less than a second on the Console application, however, it never finishes (even waited a minute) in the Xamarin.Forms.Android project.
I find this weird since the Android client can successfully login to the web service using PostAsync.

There is a difference, however, on how the Android client and the Console client call GetInformationAsync.

While the Console client calls it asynchronously:

 private static async void TestDataDownload()
 {
      ...
      var data = await WebApiClient.GetInformationAsync(myId);
 }

The Android client calls it synchronously

 public void MainPage()
 {
      ...
      var data = WebApiClient.GetInformationAsync(myId).Result;
 }
Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120

2 Answers2

19

It seems like you are experiencing a deadlock of some sort. You might want to include the code where you actually call GetInformationAsync, as it is probably where the problem source is.

You can probably fix your issue by:

  1. Not calling GetInformationAsync in a sync way
  2. Postfixing your async calls in GetInformationAsync with ConfigureAwait(false) to not switch context on every method call.

So your GetInformationAsync method would look like:

public static async Task<MyClass> GetInformationAsync(string accountId)
{
    var response = await Client.GetAsync(UriData + "/" + accountId).ConfigureAwait(false);
    response.EnsureSuccessStatusCode();
    var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    return JsonConvert.DeserializeObject<MyClass>(responseContent);
}

Then if you call it somewhere you need it to return back on the same context, I.e. if you need to update UI:

var myClass = await GetInformationAsync(accountId);
// update UI here...

Otherwise if you don't need to return on the same context:

var myClass = await GetInformationAsync(accountId).ConfigureAwait(false);
Cheesebaron
  • 24,131
  • 15
  • 66
  • 118
-1

If you are using http instead of https. Make sure you add the following lines in Android Mainfest for android. For More information see the following documentaion https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/http-stack?tabs=windows

android:usesCleartextTraffic="true"

Complete Mainfest File is

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.maximop2p" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
    <application android:label="MaximoP2P.Android" android:theme="@style/MainTheme"
                 android:usesCleartextTraffic="true"></application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>
Adnan Malik
  • 67
  • 1
  • 3
  • First of all, this is a very old question. Secondly, what makes you think that whether using HTTPS or HTTP makes a difference to the question posted? – Camilo Terevinto Oct 21 '21 at 09:35