I have a Xamarin.Forms application that supports UWP, iOS, and Android. Specifically, I am now testing my app on Android emulator. For getting location, I am using Xamarin.Essentials. Here are pieces of my code:
In a PageModel:
bu = await GeolocationSrvc.GetBusinessUnitAsync();
And here is the implementation of the method above:
public static async Task<BusinessUnits> GetBusinessUnitAsync()
{
BusinessUnits bu = BusinessUnits.Aus;
try
{
Location location = await GetLocation().ConfigureAwait(false);
IEnumerable<Placemark> placemarks = await Geocoding.GetPlacemarksAsync(location);
Placemark placemark = placemarks?.FirstOrDefault();
string countryCode = placemark?.CountryCode;
switch (countryCode)
{
case "AQ":
case "AU":
case "NZ":
bu = BusinessUnits.Aus;
break;
default:
bu = BusinessUnits.NA;
break;
}
}
catch (Exception)
{
throw;
}
return bu;
}
private static Task<Location> GetLocation()
{
GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
TaskCompletionSource<Location> locationTaskCompletionSource = new TaskCompletionSource<Location>();
Device.BeginInvokeOnMainThread(async () =>
{
locationTaskCompletionSource.SetResult(await Geolocation.GetLocationAsync(request));
});
return locationTaskCompletionSource.Task;
}
When the execution comes to
locationTaskCompletionSource.SetResult(await Geolocation.GetLocationAsync(request));
I am asked if I want to allow the app to get my location. If I press Yes, it works as expected. But if I press No, the location is never returned (not even null), the following code is never executed. I expected in case of answering No to use default value set in
BusinessUnits bu = BusinessUnits.Aus;
But it does not happen.
Alternate approach would be to check for location permission before hand using a simple dependency service for each platform.
If the permission is granted, then continue with location fetch. Else prompt user to get permission.
For ex. Android implementation to check location permission:
public bool IsLocationPermissionGranted()
{
if (ContextCompat.CheckSelfPermission(Application.Context,
Manifest.Permission.AccessFineLocation) == Permission.Granted)
{
return true;
}
return false;
}
You're not setting the Exception of your TaskCompletionSource object:
private static Task<Location> GetLocation()
{
GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
TaskCompletionSource<Location> locationTaskCompletionSource = new TaskCompletionSource<Location>();
Device.BeginInvokeOnMainThread(async () =>
{
try
{
locationTaskCompletionSource.SetResult(await Geolocation.GetLocationAsync(request));
}
catch(Exception exception)
{
locationTaskCompletionSource.SetException(exception);
locationTaskCompletionSource.SetResult(null);
}
});
return locationTaskCompletionSource.Task;
}
Related
i'm beginner for flutter. i need connect stripe payment and flutter. so i use stripe_payment: ^1.0.6(https://pub.flutter-io.cn/packages/stripe_payment/versions/1.0.6). using this example i tried to build payment gate way. but their has error "Unrecognized app. Please make sure you trust this app before proceeding".
After that press the continuous button it provide,
error.
In my widget button has following codes,
void _payWithCard() {
StripePayment.createSourceWithParams(SourceParams(
type: 'ideal',
amount: 333,
currency: 'eur',
returnURL: 'projectXXXXX://payment_redirect',
)).then((source) {
setState(() {
_source = source;
});
}).catchError(setError);
}
their has some codes related with my Stripe payment gateway.
#override
void initState() {
super.initState();
StripePayment.setOptions(StripeOptions(
publishableKey: "piok_test_pIoKxxxxxxxxxxxxxxTzgP009ywg8JNs",
merchantId: "projectXXXXXsolutions",
androidPayMode: 'test'));
initPlatformState();
}
initPlatformState() async {
if (_type == UniLinksType.string) {
await initPlatformStateForStringUniLinks();
} else {
await initPlatformStateForUriUniLinks();
}
print('init platform state');
}
// Attach a second listener to the stream
getLinksStream().listen((String link) {
print(' got link success: $link');
lartChechOutLoading(context);
}, onError: (err) {
print('got err: $err');
});
// Get the latest link
String initialLink;
Uri initialUri;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
initialLink = await getInitialLink();
print('initial link: $initialLink');
if (initialLink != null) initialUri = Uri.parse(initialLink);
} on PlatformException {
initialLink = 'Failed to get initial link.';
initialUri = null;
} on FormatException {
initialLink = 'Failed to parse the initial link as Uri.';
initialUri = null;
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_latestLink = initialLink;
_latestUri = initialUri;
});
}
// Get the latest Uri
Uri initialUri;
String initialLink;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
initialUri = await getInitialUri();
print('initial uri: ${initialUri?.path}'
' ${initialUri?.queryParametersAll}');
initialLink = initialUri?.toString();
} on PlatformException {
initialUri = null;
initialLink = 'Failed to get initial uri.';
} on FormatException {
initialUri = null;
initialLink = 'Bad parse the initial link as Uri.';
}
-
This little note is shown while operating in TEST mode, and inform your users that your application hasn't gone through the process of being approved in Google Pay's Business Console (see the troubleshooting guide to learn more).
Also, I'd recommend taking a look at the new official Flutter plugin built by the community in collaboration with Stripe. If you are using other payment providers, you can also easily add Apple and Google Pay to your Flutter applications with the pay plugin.
I have a Xamarin app made up of several pages, and I'm using Prism with AutoFac. I'm unable to update Xamarin.Forms without breaking navigation on the Android project only. It works fine on iOS.
I started with Xamarin.Form 3.1, and I cannot update to anything beyond that. My main page is a login page - when that is successful I navigate to the home page like so:
try
{
await _navigationService.NavigateAsync(new Uri($"/NavigationPage/{nameof(HomePage)}", UriKind.Absolute));
}
catch (Exception e)
{
Log.Error(e);
}
The navigation is not throwing any exceptions, and I'm not picking up any errors anywhere. Release notes for Xamarin 3.2 doesn't provide any clues either. I don't even know if this is a Xamarin or Prism issue. A few days of debugging and I feel no closer to figuring this out.
Has anyone else experienced this? or have any idea what could be going wrong?
Edit 1:
I finally isolated the issue - the fix was to call BeginInvokeOnMainThread when I navigate. But a few things still don't make sense to me:
This should raise an exception, so I must be hiding it somewhere. Is there anything obvious in the code below [This is the first time I've used Async, so seems likely I'm doing something wrong there]?
Why did this work with Xamarin 3.1 on not later versions
My logging confirms that the original navigation code was running on the main thread, but it still failed.
The code:
We are doing client-side google authentication with Azure, if that is successful we navigate to the home page.
First step, we connect to GooglePlay and authenticate the user
public void Login(MobileServiceClient client, Action<string, bool> onLoginComplete)
{
_client = client;
_onLoginComplete = onLoginComplete;
var signInIntent = Auth.GoogleSignInApi.GetSignInIntent(_googleApiClient);
((MainActivity)_context).StartActivityForResult(signInIntent, 1);
_googleApiClient.Connect();
}
The result comes to OnActivityResult in MainActivity.cs:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == SignInId)
{
Log.Info("Received result from Google sign in");
var result = Auth.GoogleSignInApi.GetSignInResultFromIntent(data);
DroidLoginProvider.Instance.OnAuthCompleted(result);
}
}
Which calls the OnAuthCompleted method. There are a few paths here. If the token is valid we don't re-authenticate with Azure, and just retrieve the saved user details:
public void OnAuthCompleted(GoogleSignInResult result)
{
if (result.IsSuccess)
{
Log.Trace("Native google log in successful");
var signInAccount = result.SignInAccount;
var accounts = _accountStore.FindAccountsForService("monkey_chat");
if (accounts != null)
{
foreach (var acct in accounts)
{
if (acct.Properties.TryGetValue("token", out var azureToken) && acct.Properties.TryGetValue("email", out var email))
{
if (!IsTokenExpired(azureToken))
{
Log.Trace("Auth token is still valid");
_client.CurrentUser = new MobileServiceUser(acct.Username)
{
MobileServiceAuthenticationToken = azureToken
};
_onLoginComplete?.Invoke(email, true);
return;
}
Log.Trace("Auth token no longer valid");
}
}
}
// Authenticate with Azure & get a new token
var token = new JObject
{
["authorization_code"] = signInAccount.ServerAuthCode,
["id_token"] = signInAccount.IdToken
};
try
{
var mobileUser = Task.Run(async () =>
{
try
{
Log.Trace("Authenticating with Azure");
return await client.LoginAsync(MobileServiceAuthenticationProvider.Google, token).ConfigureAwait(false);
}
catch (Exception e)
{
Log.Error(e);
throw;
}
}).GetAwaiter().GetResult();
var account = new Account(_client.CurrentUser.UserId);
account.Properties.Add("token", _client.CurrentUser.MobileServiceAuthenticationToken);
account.Properties.Add("email", signInAccount.Email);
_accountStore.Save(account, "monkey_chat");
_googleUser = new GoogleUser
{
Name = signInAccount.DisplayName,
Email = signInAccount.Email,
Picture = new Uri((signInAccount.PhotoUrl != null
? $"{signInAccount.PhotoUrl}"
: $"https://autisticdating.net/imgs/profile-placeholder.jpg")),
UserId = SidHelper.ExtractUserId(mobileUser?.UserId),
UserToken = mobileUser?.MobileServiceAuthenticationToken
};
_onLoginComplete?.Invoke(signInAccount.Email, true);
}
catch (Exception ex)
{
_onLoginComplete?.Invoke(string.Empty, false);
Log.Error(ex);
}
}
else
{
_onLoginComplete?.Invoke(string.Empty, false);
}
}
My original OnLoginComplete[Not working]:
private async void OnLoginComplete(bool successful, bool isNewUser)
{
if (successful)
{
try
{
Log.Info("Starting navigation to home page");
await _navigationService.NavigateAsync(new Uri($"/NavigationPage/{nameof(HomePage)}", UriKind.Absolute)).GetAwaiter().GetResult();
}
catch (Exception e)
{
Log.Error(e);
}
}
}
New OnLoginComplete[Working]
private void OnLoginComplete(bool successful, bool isNewUser)
{
Device.BeginInvokeOnMainThread(() =>
{
if (successful)
{
try
{
Log.Info("Starting navigation to home page");
_navigationService.NavigateAsync(new Uri($"/NavigationPage/{nameof(HomePage)}", UriKind.Absolute)).GetAwaiter().GetResult();
}
catch (Exception e)
{
Log.Error(e);
}
}
});
}
When I first log into my app, I go through the following code:
auth = new Xamarin.Auth.OAuth2Authenticator(
"my-google-client-id.apps.googleusercontent.com",
string.Empty,
"openid",
new System.Uri("https://accounts.google.com/o/oauth2/v2/auth"),
new System.Uri("com.enigmadream.storyvoque:/oauth2redirect"),
new System.Uri("https://www.googleapis.com/oauth2/v4/token"),
isUsingNativeUI: true);
auth.Completed += Auth_Completed;
StartActivity(auth.GetUI(this));
Which triggers this activity:
[Activity(Label = "GoodleAuthInterceptor")]
[IntentFilter(actions: new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
DataSchemes = new[] { "com.enigmadream.storyvoque" }, DataPaths = new[] { "/oauth2redirect" })]
public class GoodleAuthInterceptor : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Android.Net.Uri uri_android = Intent.Data;
Uri uri_netfx = new Uri(uri_android.ToString());
MainActivity.auth?.OnPageLoading(uri_netfx);
Finish();
}
}
And finally this code to link the account to Cognito:
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
var idToken = e.Account.Properties["id_token"];
credentials.AddLogin("accounts.google.com", idToken);
AmazonCognitoIdentityClient cli = new AmazonCognitoIdentityClient(credentials, RegionEndpoint.USEast2);
var req = new Amazon.CognitoIdentity.Model.GetIdRequest();
req.Logins.Add("accounts.google.com", idToken);
req.IdentityPoolId = "us-east-2:79ebf8e1-97de-4d1c-959a-xxxxxxxxxxxx";
cli.GetIdAsync(req).ContinueWith((task) =>
{
if ((task.Status == TaskStatus.RanToCompletion) && (task.Result != null))
{
ShowMessage(string.Format("Identity {0} retrieved", task.Result.IdentityId));
}
else
ShowMessage(task.Exception.InnerException != null ? task.Exception.InnerException.Message : task.Exception.Message);
});
}
else
ShowMessage("Login cancelled");
}
This all works great, and after the login, I am able to use my identity/credentials to retrieve data from DynamoDB. With this object:
Amazon.DynamoDBv2.AmazonDynamoDBClient ddbc = new Amazon.DynamoDBv2.AmazonDynamoDBClient(credentials, RegionEndpoint.USEast2);
The second time I run my app, this code runs:
if (!string.IsNullOrEmpty(credentials.GetCachedIdentityId()) || credentials.CurrentLoginProviders.Length > 0)
{
if (!bDidLogin)
{
var idToken = credentials.GetIdentityId();
ShowMessage(string.Format("I still remember you're {0} ", idToken));
And if I try to use the credentials with DynamoDB (or anything, I assume) at this point, I get errors that I don't have access to the identity. I have to logout (credentials.Clear()) and login again to obtain proper credentials.
I could require that a user go through the whole login process every time my app runs, but that's a real pain because the Google login process requires the user to know how to manually close the web browser to get back to the application after authenticating. Is there something I'm missing about the purpose and usage of cached credentials? When I use most apps, they aren't requiring me to log into my Google account every time and close a web browser just to access their server resources.
It looks like the refresh token needs to be submitted back to the OAuth2 provider to get an updated id token to add to the credentials object. First I added some code to save and load the refresh_token in a config.json file:
private Dictionary<string, string> config;
const string CONFIG_FILE = "config.json";
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
var idToken = e.Account.Properties["id_token"];
if (e.Account.Properties.ContainsKey("refresh_token"))
{
if (config == null)
config = new Dictionary<string, string>();
config["refresh_token"] = e.Account.Properties["refresh_token"];
WriteConfig();
}
credentials.AddLogin("accounts.google.com", idToken);
CognitoLogin(idToken).ContinueWith((t) =>
{
try
{
t.Wait();
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
});
}
else
ShowMessage("Login cancelled");
}
void WriteConfig()
{
using (var configWriter = new System.IO.StreamWriter(
Application.OpenFileOutput(CONFIG_FILE, Android.Content.FileCreationMode.Private)))
{
configWriter.Write(ThirdParty.Json.LitJson.JsonMapper.ToJson(config));
configWriter.Close();
}
}
public void Login()
{
try
{
if (!string.IsNullOrEmpty(credentials.GetCachedIdentityId()) || credentials.CurrentLoginProviders.Length > 0)
{
if (!bDidLogin)
{
var idToken = credentials.GetIdentityId();
if (ReadConfig())
{
LoginRefreshAsync().ContinueWith((t) =>
{
try
{
t.Wait();
if (!t.Result)
FullLogin();
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
});
}
else
{
credentials.Clear();
FullLogin();
}
}
}
else
FullLogin();
bDidLogin = true;
}
catch(Exception ex)
{
ShowMessage(string.Format("Error logging in: {0}", ex.Message));
}
}
private bool ReadConfig()
{
bool bFound = false;
foreach (string filename in Application.FileList())
if (string.Compare(filename, CONFIG_FILE, true) == 0)
{
bFound = true;
break;
}
if (!bFound)
return false;
using (var configReader = new System.IO.StreamReader(Application.OpenFileInput(CONFIG_FILE)))
{
config = ThirdParty.Json.LitJson.JsonMapper.ToObject<Dictionary<string, string>>(configReader.ReadToEnd());
return true;
}
}
Then refactored the code that initiates the interactive login into a separate function:
public void FullLogin()
{
auth = new Xamarin.Auth.OAuth2Authenticator(CLIENTID_GOOGLE, string.Empty, "openid",
new Uri("https://accounts.google.com/o/oauth2/v2/auth"),
new Uri("com.enigmadream.storyvoque:/oauth2redirect"),
new Uri("https://accounts.google.com/o/oauth2/token"),
isUsingNativeUI: true);
auth.Completed += Auth_Completed;
StartActivity(auth.GetUI(this));
}
Refactored the code that retrieves a Cognito identity into its own function:
private async Task CognitoLogin(string idToken)
{
AmazonCognitoIdentityClient cli = new AmazonCognitoIdentityClient(credentials, RegionEndpoint.USEast2);
var req = new Amazon.CognitoIdentity.Model.GetIdRequest();
req.Logins.Add("accounts.google.com", idToken);
req.IdentityPoolId = ID_POOL;
try
{
var result = await cli.GetIdAsync(req);
ShowMessage(string.Format("Identity {0} retrieved", result.IdentityId));
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
}
And finally implemented a function that can retrieve a new token based on the refresh token, insert it into the current Cognito credentials, and get an updated Cognito identity.
private async Task<bool> LoginRefreshAsync()
{
string tokenUrl = "https://accounts.google.com/o/oauth2/token";
try
{
using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
{
string contentString = string.Format(
"client_id={0}&grant_type=refresh_token&refresh_token={1}&",
Uri.EscapeDataString(CLIENTID_GOOGLE),
Uri.EscapeDataString(config["refresh_token"]));
System.Net.Http.HttpContent content = new System.Net.Http.ByteArrayContent(
System.Text.Encoding.UTF8.GetBytes(contentString));
content.Headers.Add("content-type", "application/x-www-form-urlencoded");
System.Net.Http.HttpResponseMessage msg = await client.PostAsync(tokenUrl, content);
string result = await msg.Content.ReadAsStringAsync();
string idToken = System.Json.JsonValue.Parse(result)["id_token"];
credentials.AddLogin("accounts.google.com", idToken);
/* EDIT -- discovered this is not necessary! */
// await CognitoLogin(idToken);
return true;
}
}
catch (Exception ex)
{
ShowMessage(ex.Message);
return false;
}
}
I'm not sure if this is optimal or even correct, but it seems to work. I can use the resulting credentials to access DynamoDB without having to prompt the user for permission/credentials again.
There's a very different solution I'm trying to fit with the other answer. But it's so different, I'm adding it as a separate answer.
It appears the problem was not so much related to needing to explicitly use a refresh token to get an updated access token (I think this is done implicitly), but rather needing to remember the identity token. So rather than include all the complexity of manually applying a refresh token, all that's needed is to store the identity token (which can be done in a way similar to how the refresh token was being stored). Then we just need to add that same identity token back to the credentials object when it's missing.
if (!string.IsNullOrEmpty(credentials.GetCachedIdentityId()) || credentials.CurrentLoginProviders.Length > 0)
{
if (config.Read())
{
if (config["id_token"] != null)
credentials.AddLogin(currentProvider.Name, config["id_token"]);
Edit: The problem of needing to use a refresh token does still exist. This code works if the token hasn't expired, but attempting to use these credentials after the token has expired will fail, so there is still some need to use a refresh token somehow in some cases.
I have the following code to make requests to a REST API, using Xamarin and an Android device:
public class ApiBase
{
HttpClient m_HttpClient;
public ApiBase(string baseAddress, string username, string password)
{
if (!baseAddress.EndsWith("/"))
{
baseAddress += "/";
}
var handler = new HttpClientHandler();
if (handler.SupportsAutomaticDecompression)
{
handler.AutomaticDecompression = DecompressionMethods.GZip;
}
m_HttpClient = new HttpClient(handler);
m_HttpClient.BaseAddress = new Uri(baseAddress);
var credentialsString = Convert.ToBase64String(Encoding.UTF8.GetBytes(username + ":" + password));
m_HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", credentialsString);
m_HttpClient.Timeout = new TimeSpan(0, 0, 30);
}
protected async Task<XElement> HttpGetAsync(string method)
{
try
{
HttpResponseMessage response = await m_HttpClient.GetAsync(method);
if (response.IsSuccessStatusCode)
{
// the request was successful, parse the returned string as xml and return the XElement
var xml = await response.Content.ReadAsAsync<XElement>();
return xml;
}
// the request was not successful -> return null
else
{
return null;
}
}
// some exception occured -> return null
catch (Exception)
{
return null;
}
}
}
If i have it like this, the first and the second call to HttpGetAsync work perfectly, but from the 3rd on the GetAsyncstalls and eventually throws an exception due to the timeout. I send these calls consecutively, there are not 2 of them running simultaneously since the results of the previous call are needed to decide the next call.
I tried using the app Packet Capture to look at the requests and responses to find out if i'm sending an incorrect request. But it looks like the request which fails in the end is never even sent.
Through experimentation i found out that everything works fine if don't set the AutomaticDecompression.
It also works fine if i change the HttpGetAsync method to this:
protected async Task<XElement> HttpGetAsync(string method)
{
try
{
// send the request
var response = await m_HttpClient.GetStringAsync(method);
if (string.IsNullOrEmpty(response))
{
return null;
}
var xml = XElement.Parse(response);
return xml;
}
// some exception occured -> return null
catch (Exception)
{
return null;
}
}
So basically using i'm m_HttpClient.GetStringAsync instead of m_HttpClient.GetAsync and then change the fluff around it to work with the different return type. If i do it like this, everything works without any problems.
Does anyone have an idea why GetAsync doesn't work properly (doesn't seem to send the 3rd request) with AutomaticDecompression, where as GetStringAsync works flawlessly?
There are bug reports about this exact issue:
https://bugzilla.xamarin.com/show_bug.cgi?id=21477
The bug is marked as RESOLVED FIXED and the recomended action is to update to the latest stable build. But there are other (newer) bugreports that indicate the same thing that are still open, ex:
https://bugzilla.xamarin.com/show_bug.cgi?id=34747
I made a workaround by implementing my own HttpHandler like so:
public class DecompressionHttpClientHandler : HttpClientHandler
{
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip"));
var msg = await base.SendAsync(request, cancellationToken);
if (msg.Content.Headers.ContentEncoding.Contains("gzip"))
{
var compressedStream = await msg.Content.ReadAsStreamAsync();
var uncompresedStream = new System.IO.Compression.GZipStream(compressedStream, System.IO.Compression.CompressionMode.Decompress);
msg.Content = new StreamContent(uncompresedStream);
}
return msg;
}
}
Note that the code above is just an example and not a final solution. For example the request will not be compressed and all headers will be striped from the result. But you get the idea.
I create app on Xamarin.Android. There is a socket, with it's help I'm getting some data for my app. I'm checking the internet connection like this:
_timer = new Timer(CheckNetworkAvailable, new AutoResetEvent(false), 0, 10000);
It calls in OnCreate method.
cts = new CancellationTokenSource();
var isNetwork = await Task.Run(() => this.NetworkRechableOrNot(), cts.Token);
var linear = SupportActionBar.CustomView.FindViewById<LinearLayout>(Resource.Id.linearForActionBanner);
var identOn = linear.FindViewById<ImageView>(Resource.Id.identificator_on);
var identOff = linear.FindViewById<ImageView>(Resource.Id.identificator_off);
RunOnUiThread(() =>
{
identOn.Visibility = !isNetwork ? ViewStates.Gone : ViewStates.Visible;
identOff.Visibility = !isNetwork ? ViewStates.Visible : ViewStates.Gone;
});
if (isNetwork)
{
if (isNetwork != oldNet)
{
oldNet = isNetwork;
MainDataClass.UpdateSymbolsList();
SocketClass.Start();
}
}
else
{
oldNet = isNetwork;
cts.Cancel();
SocketClass.Stop();
}
Here oldNet - previos status of internet access.
private bool NetworkRechableOrNot()
{
try
{
var connectivityManager = (_Net.ConnectivityManager)GetSystemService(Context.ConnectivityService);
var activeConnection = connectivityManager.ActiveNetworkInfo;
return (activeConnection != null) && activeConnection.IsConnected;
}
catch (Exception)
{
return false;
}
}
And this is the result method for checking.
SocketClass - class for socket and getting data; Start method creating new Task and Start it, socket created via SocketIOClient.Socket; Stop method calls Close method of Socket. And it all works fine until I try to disable internet connection, I got only once NameResolutionFailure. What can be the reason of it? And what should I change for meking it works fine? Thanks.
I think the main reason is your internet is off. You need a internet to try resolve some address.
I solved it, there was not correct realization of socket, it come in loop because when socket gets error it calls itself and doesn't finish that's why it crashes.