I am running into problems consuming a rest web service hosted on Azure in an Android Xamarin Application.
async Task ViewTimetableAsync(object sender, EventArgs e)
{
await DependencyService.Get<ITimetableService>().GetTimetableAsync(_user);
}
This is the code that is called in the XAML.cs class, it is a button event.
try
{
using (var client = new HttpClient(new NativeMessageHandler()))
{
var response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
}
else
{
var result = "Fail";
}
}
}
catch(Exception e)
{
var reson = e.Data;
}
This is the relevant code that is being used to call the REST web service. The code is hanging when GetAsync is called. No error is thrown, don't get any discernible information in the output.
I have included internet as a required permission in the Android manifest. I have included System.net.http as a NuGet package.
I am getting no traffic in Azure, so it is clearly not even reaching the web service. So why is this Http Client not sending the request? I am having to debug on an Android phone connected by USB using Visual Studio, and that seems to be running fine, the only issue being the inability to send out this request. The API is accessible from the phone as I brought it up in a browser, is it a setting in the phone itself that is possibly causing this?
Any help would be greatly appreciated.
Related
Following the official guidance, I've implemented the WebAuthenticator in my .NET Maui Android App to handle SSO auth with Facebook.
It's a fairly straightforward implementation, I've added the .Net core backend on a website with the mobile auth endpoint implemented as directed, and that appears to be working.
However when the WebAuthenticator.AuthenticateAsync method is calling the API, it's hanging:
private void OnFacebookClicked(object sending, EventArgs e)
{
try
{
WebAuthenticatorResult authResult = WebAuthenticator.Default.AuthenticateAsync(
new Uri("https://testwebsite.azurewebsites.net/mobileauth/Facebook"),
new Uri("xamarinessentials://")).Result;
string accessToken = authResult?.AccessToken;
}
catch (TaskCanceledException)
{
// User stopped auth
}
}
I don't get any kind of response back - no timeout, no exception, nothing just a straight hang.
Any advice?
I am able to run my ionic app on my laptop by using the ionic lab command.
The app makes calls to the IMDB api, & displays data retrieved from it.
Now, I am trying to run the app on an android device.
by using the following command: ionic cordova run android --device.
The app appears on my phone, but when I search for IMDB data, no results are appearing.
Below is the service I am using to make calls to the API:
export class MovieService {
url = 'http://www.omdbapi.com/';
apiKey = 'myKey';
constructor(private http: HttpClient) { }
searchData(title: string, type: SearchType): Observable<any> {
return this.http.get(`${this.url}?s=${encodeURI(title)}&type=${type}&apikey=${this.apiKey}`)
.pipe(
map(results => {
console.log('RAW', results);
return results['Search'];
})
);
}
getDetails(id): Observable<any> {
return this.http.get(`${this.url}?i=${id}&plot=full&apikey=${this.apiKey}`);
}
}
Can someone please tell me why the app is working on my laptop, but when I try to use it on my phone it isn't working as expected?
Probably one reason is that you are using http not https.
Android restricted access to non-secure feeds in a recent security update.
Try:
url = 'https://www.omdbapi.com/';
The current Azure ADB2C Mobile app example here that forcibly opens a browser component outside the app and after Sign-In redirects back to the app.
Is there any way to skip this ugly and clunky Sign-In page altogether and do Sign-In/Sign-up directly from a mobile app component? I want to create my own Sign-In Activity so I only go to the portal to get the token through a REST uri and never have to open a browser outside my app.
You can create a resource owner policy that enables you to gather a user credential in your mobile app and then validate it in your Azure AD B2C tenant.
You can use a client library, such as AppAuth for Android or AppAuth for iOS, to manage the policy invocation for you.
This is an old question, but the question still resonated with me a year later. There is an answer to this:
.WithUseEmbeddedWebView(true)
The full snippet (taken and adapted from an Azure GitHub sample) is:
async void OnLoginButtonClicked(object sender, EventArgs e)
{
AuthenticationResult result;
try
{
//bool useEmbeddedWebView = !App.IsSystemWebViewAvailable;
result = await App.AuthenticationClient
.AcquireTokenInteractive(Constants.Scopes)
.WithPrompt(Prompt.SelectAccount)
.WithParentActivityOrWindow(App.UIParent)
.WithUseEmbeddedWebView(true)
.ExecuteAsync();
await Navigation.PushAsync(new LogoutPage(result));
}
catch (MsalException ex)
{
if (ex.Message != null && ex.Message.Contains("AADB2C90118"))
{
result = await OnForgotPassword();
await Navigation.PushAsync(new LogoutPage(result));
}
else if (ex.ErrorCode != "authentication_canceled")
{
await DisplayAlert("An error has occurred", "Exception message: " + ex.Message, "Dismiss");
}
}
}
Note that this isn't a complete working solution, but it does force the B2C template to load into a WebView rather than opening a browser and revealing your domain name. Put it in the shared code project.
You don't get to use your own login page, but it does at least appear to be part of your app.
Reference: Xamarin Considerations
Hopefully Microsoft will address this failing in future releases.
My need: connect my Android device to a local SQL Server database.
My problem: an exception occurs when trying to connect ("An error occurred while sending the request")
What I use: Visual Studio 2017 and Xamarin Forms with MVVM architecture.
What works: I do a POST from Postman and it works perfectly, returning the user's token.
My project uses a REST API to connect to the DB. The API is published as FileSystem and run with IISExpress and as I said, with Postman it works.
I have tried:
http://localhost:50965
http://192.168.1.106:50965 (my PC IP)
My connection string on API Web.config
<add name="DefaultConnection" connectionString="Data Source=192.168.1.106; Initial Catalog=Gesuro; Integrated Security=True; User ID = sergio; Password=xxxxxxxx" providerName="System.Data.SqlClient" />
My call to the API:
var token = await this.apiService.GetToken(
"http://localhost:50965",
this.Email,
this.Password);
My API method:
public async Task<TokenResponse> GetToken(
string urlBase,
string username,
string password)
{
try
{
var client = new HttpClient();
client.BaseAddress = new Uri(urlBase);
var response = await client.PostAsync("Token",
new StringContent(string.Format(
"grant_type=password&username={0}&password={1}",
username, password),
Encoding.UTF8, "application/x-www-form-urlencoded"));
var resultJSON = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<TokenResponse>(
resultJSON);
return result;
}
catch (Exception e)
{
var pepe = e.Message;
return null;
}
}
I've been searching Google for three days and trying different solutions ... without results.
I hope I have been specific with my query. Some help, please?
Thanks in advance.
Try changing compile using Android version (Target Framework)
Change it android 6.0 might work
I faced the same issue changing the target framework solved this for me.
You haven't provided enough details, but I'm going to guess.
Your db server is running on your PC, then run
$ adb reverse tcp:50965 tcp:50965
on it, and then when you access
localhost:50965
on your device it will be redirected to same port on your PC
EDIT
If you want to test that reverse works, do
$ adb reverse tcp:3456 tcp:80
and if you are running a web server on port 80 on your PC when you open Chrome on the device and enter
http://127.0.0.1:3456
you will see the home page
I am building a game on Ionic using Socket.io for communicating plays between clients. I have tried connecting to an Express server running on local host as well as the same one on Digital Ocean:
var express = require('express');
var app = express();
var socketio = require('socket.io');
var server = app.listen(8080);
var io = require('socket.io').listen(server);
io.sockets.on('connect', function(socket) {
});
It works fantastic with ionic serve, and when I emulate on iOS, howerver, when I run or emulate on Android it can't connect, giving me the following errors:
Failed to load resource: the server responded with a status of 404 (Not Found) http:// my server /socket.io/?EIO=3&transport=polling&t=1434658858975-0
Failed to load resource: the server responded with a status of 404 (Not Found) http:// my server /socket.io/?EIO=3&transport=polling&t=1434658860600-1
Failed to load resource: the server responded with a status of 404 (Not Found) http:// my server /socket.io/?EIO=3&transport=polling&t=1434658862535-2
I am connecting through a Factory
.factory('socket', function($rootScope) {
var socket = io.connect( server );
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});
I am completely blank on this. Is there a setting somewhere that, if changed, would allow me to connect?
You could try building in MeteorJS which is a Node/Express based app framework that uses socket.io It has a really good Ionic package (full support) and Cordova support with built in OAuth as well. I've built a few mobile apps and it's a good stack. Check MeteorJS.com and packages at atmosphere.com
Don't know if you are still looking, but I may have come across a solution to this issue.
I was having the exact same problem where the app would work correctly on iOS but not on android. I was able to get it to work by listening not to the localhost but to the ip of my computer pointed to the same port.
Inside of the socket factory, I had been using
var socket = io.connect('http://localhost:3000')
Instead try
var socket = io.connect('http://192.168.12.3:3000').
or whatever your computer's ip address is.