I have the following code:
public partial class MetricsPage : ContentPage
{
public MetricsPage()
{
InitializeComponent();
using var client = new HttpClient();
client.BaseAddress = new Uri("http://example.com");
client.Timeout = new TimeSpan(0, 0, 3);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Api-Key", "<my_key>");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
totalCreatedThings.Text = GetNumberOfThingsAsync(client).GetAwaiter().GetResult();
}
static async Task<string> GetNumberOfThingsAsync(HttpClient client)
{
try
{
HttpResponseMessage response = await client.GetAsync("/api/get_number_things").ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
string numberOfThings = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return numberOfThings;
}
else
{
return string.Empty;
}
}
catch (HttpRequestException hex)
{
System.Diagnostics.Debug.WriteLine(hex.Message);
return string.Empty;
}
catch (OperationCanceledException oex)
{
System.Diagnostics.Debug.WriteLine(oex.Message);
return string.Empty;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
return string.Empty;
}
}
}
For this code and when debugging with the Windows Machine in Visual Studio 2022, errors in GetNumberOfThingsAsync are catched correctly. These errors consist on a failed request to the api. However, when executing this exact same code in Android, errors are not catched and the following error is shown instead:
System.Threading.Tasks.TaskCanceledException: 'The request was canceled due to the configured HttpClient.Timeout of 3 seconds elapsing.'
And the output is:
[monodroid-net] Exception caught while cancelling connection: Java.Net.SocketException: Socket closed
[monodroid-net] at Java.Interop.JniEnvironment.InstanceMethods.CallVoidMethod(JniObjectReference instance, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.g.cs:line 11884
[monodroid-net] at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractVoidMethod(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:line 17
[monodroid-net] at Java.Net.HttpURLConnectionInvoker.Connect() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net6.0/android-31/mcw/Java.Net.HttpURLConnection.cs:line 725
[monodroid-net] at Xamarin.Android.Net.AndroidMessageHandler.<>c__DisplayClass125_0.<ConnectAsync>b__0() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs:line 444
[monodroid-net] --- End of managed Java.Net.SocketException stack trace ---
[monodroid-net] java.net.SocketException: Socket closed
[monodroid-net] at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:394)
[monodroid-net] at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
[monodroid-net] at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
[monodroid-net] at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
[monodroid-net] at java.net.Socket.connect(Socket.java:646)
[monodroid-net] at com.android.okhttp.internal.Platform.connectSocket(Platform.java:182)
[monodroid-net] at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:145)
[monodroid-net] at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
[monodroid-net] at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
[monodroid-net] at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
[monodroid-net] at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
[monodroid-net] at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
[monodroid-net] at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
[monodroid-net] at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
[monodroid-net] at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
[monodroid-net]
[monodroid-net] --- End of managed Java.Net.SocketException stack trace ---
[monodroid-net] java.net.SocketException: Socket closed
[monodroid-net] at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:394)
[monodroid-net] at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
[monodroid-net] at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
[monodroid-net] at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
[monodroid-net] at java.net.Socket.connect(Socket.java:646)
[monodroid-net] at com.android.okhttp.internal.Platform.connectSocket(Platform.java:182)
[monodroid-net] at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:145)
[monodroid-net] at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
[monodroid-net] at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
[monodroid-net] at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
[monodroid-net] at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
[monodroid-net] at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
[monodroid-net] at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
[monodroid-net] at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
[monodroid-net] at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
[monodroid-net]
**System.Threading.Tasks.TaskCanceledException:** 'The request was canceled due to the configured HttpClient.Timeout of 3 seconds elapsing.'
Errors in the request must be catched both for the Windows Machine and for Android.
CodePudding user response:
If your issue is the debugger is not working this might help.
Add this in on create method in android main activity.
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
AppDomain.CurrentDomain.UnhandledException = CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ System.Diagnostics.Debug.WriteLine(e.ToString()); }
Try adding that and make sure JIT debugger is enabled and you can get it working maybe? I used the above and it works for me. Not sure if it will help you do what you want. At least it might help with debugging it.
CodePudding user response:
Due to the Socket closed
error message I suspect that chances are that your HttpClient
instance is disposed before your HTTP request could have been completed.
I would suggest moving your HTTP request from the .ctor.
E.g., you can override the OnNavigatedTo()
method that can be an async method.
protected override async void OnNavigatedTo(NavigatedToEventArgs args)
{
using var client = new HttpClient();
client.BaseAddress = new Uri("http://example.com");
client.Timeout = new TimeSpan(0, 0, 3);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Api-Key", "<my_key>");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue(
System.Net.Mime.MediaTypeNames.Application.Json
)
);
totalCreatedThings.Text = await GetNumberOfThingsAsync(client);
}