Disallow page closing in Xamarin.iOS during background actions - xamarin.ios

In my IoT mobile app, I created a page showed on iOS device as UIModalPresentationStyle.PageSheet.
During the page load I don't want the page will react to user interaction, in particular I don't want the page will be closed, because the app interacts with a physical device.
The page will be enabled to be closed once all the background tasks will be completed.
I tried to set the page property IsEnabled to false, but again I'm able to close the page.
That's a code snippet from the page constructor
public ParametersListPage(ControlUnitParametersCategory parametersCategory, bool isParametersListReadOnly = false)
{
InitializeComponent();
IsEnabled = false;
On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.PageSheet);
MessagingCenter.Subscribe<ListParamsViewModel>(this, Constants.ACTION, async (sender) =>
{
IsEnabled = true;
await DisplayAlert(Resource.DoAct, Resource.DoActMsg, "OK");
}
);
What Am I missing?
Thank you

Do you want to disable user actions during interaction? If so, you can try setting the UserInteractionEnabled property to false to disable the user's actions so that the user will never be able to trigger any events (including touchscreens).
For Xamarin.Forms you can refer to the following code:
MyPageRenderer:
[assembly:ExproRenderer(typeof(ParametersListPage),typeof(ParametersListPageRenderer))]
namespace FormsDemo.iOS
{
public class ParametersListPageRenderer:PageRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
this.View.UserInteractionEnabled=false;
}
}
}
If you just want the user not to close the page during interaction, it is better to set a popup reminder.

Related

callkit with pushkit in xamarin

I'm trying to integrate callkit with pushkit in one of my app in xamarin using Twilio voip. I was able to do so by defining required classes and delegates.
I can receive a call when my app is in foreground. but when my app is backgrounded or killed, its not received.
I have this method in my appdelegate:
[Export("pushRegistry:didReceiveIncomingPushWithPayload:forType:withCompletionHandler:")]
[Preserve(Conditional = true)]
public void DidReceiveIncomingPush(PKPushRegistry registry, PKPushPayload payload, string type, Action completion)
{
try
{
Console.WriteLine("My push is coming (Inside Action method!");
var callerid = payload.DictionaryPayload["twi_from"].ToString();
Console.WriteLine($"from: {callerid}");
completion= delegate {
if (payload != null)
{
TwilioService.Setnotification(payload);
}
};
completion.Invoke();
// Tried using only this
// completion(); but it didn't work.
}catch(Exception ex)
{
Console.WriteLine(ex.message);
}
}
So question is how to bring Native dialer when call is arriving and app is in background or killed. I don't understand how to use "Action" parameter of above method.
I see this error in my device logs:
Info (114) / callservicesd: Application <private> will not be launched because it failed to report an incoming call too many times (or repeatedly crashed.)
Thanks.

How to update Blazor (hosted) upon socket receive event

Hello i have a blazor page in which i want to display a variable.
This variable gets updated from another thread (Task- which receives data over a websocket) and i want to display it in a thread-safe manner:
Blazor Page
#page "/new"
#inherits NewBase
<button onclick="#(async()=>await OnRunPressed())" class="control-button">Run</button>
NewValue :#socketString
public class NewBase:BlazorComponent
{
[Inject] protected BenchService service { get; set; }
protected CancellationTokenSource src = new CancellationTokenSource();
protected string socketString;
protected async Task OnRunPressed()
{
Task updateTask= Task.Run(async () =>
{
var buffer =new byte[1024];
ClientWebSocket socket = new ClientWebSocket();
await socket.ConnectAsync(new Uri("ws://localhost:8500/monitor"), CancellationToken.None);
while (true)
{
await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
this.socketString = Encoding.UTF8.GetString(buffer);
this.StateHasChanged();
}
},src.Token);
await this.service.HitServerAsync(); //does some stuff while the above task works
src.Cancel();
}
}
Update
Thanks to #Dani now i finally at least get an error :
blazor.server.js:16 POST http://localhost:8500/_blazor/negotiate 500 (Internal Server Error)
Error: Failed to start the connection: Error: Internal Server Error
You may be lacking StateHasChanged(); at the end of the OnRunPressed method
I guess this is a server-side Blazor, right ?
If not, then you should know that Mono on WASM is currently single-threaded...
They are no problem about to call StateHasChanged(); after receive data via websocket. All should to run. I have tested it (as server side) and it runs without issues:
https://github.com/ctrl-alt-d/blazorTestingWebSocketsServerSide/tree/master
Also, I have tested it as client side wasm, and they are several issues:
You are using ArrayPool that is a non netstandard2.0 class.
WebSocket is not able to connect from wasm.

auth0 callback doesn't set profile date after login angular2

I have an angular 2 app which uses auth0 for authentication. The issue I'm having is that when a successful login occurs, it seems like the lock callback is not being called. Only after I do a manually refresh of the page will the profile data be sent to local storage.
When a user logs in, I need to grab that profile object and use it within the component class. This code works only after I manually refresh the page following a successful login. Here is my code (only including the important parts).
auth.service
lock = new Auth0Lock('.....9cNzyzJ3DZc2VpDyXSYF5', '.....12.auth0.com', {});
user: any;
constructor() {
// Add callback for lock `authenticated` event
this.user = JSON.parse(localStorage.getItem('profile'));
this.lock.on("authenticated", (authResult:any) => {
this.lock.getProfile(authResult.idToken, function(error: any, profile: any){
if(error){
throw new Error(error);
}
localStorage.setItem('id_token', authResult.idToken);
localStorage.setItem('profile', JSON.stringify(profile));
this.user = profile;
});
});
}
public login() {
// Call the show method to display the widget.
this.lock.show();
console.log('login func');
};
nav.component
constructor(private auth: Auth, private groupsService: GroupsService){
}
ngOnInit(){
// need to access the profile object here. Ocject is correctly logged only after refreshing.
console.log(JSON.parse(localStorage.getItem('profile')));
this.groupsService.getGroups(this.userId).subscribe(groups => {
this.groups = groups;
// sort the groups
this.groups.sort((a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime());
});
}
According to the documentation for ngOnInit:
ngOnInit is called right after the directive's data-bound properties have been checked for the first time, and before any of its children have been checked. It is invoked only once when the directive is instantiated.
(emphasis is mine)
Which indicates that when its run there isn't a user profile available yet because the authentication was still not processed. If you cause a page refresh after authentication, the user profile is already available in Web Storage and the manual refresh causes the ngOnInit to be executed leading to the behavior you described.

Azure Active Directory: Where can I insert a function to run after a user is signed in?

I've been following this example https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-devquickstarts-web-dotnet/ and I'm pretty certain that in the SignIn method I can put my function there to run, but I'm not sure how you would go
In that top portion of the AccountController.cs example:
namespace WebApp_OpenIDConnect_DotNet_B2C.Controllers
{
public class AccountController : Controller
{
public void SignIn()
{
if (!Request.IsAuthenticated)
{
// To execute a policy, you simply need to trigger an OWIN challenge.
// You can indicate which policy to use by adding it to the AuthenticationProperties using the PolicyKey provided.
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties (
new Dictionary<string, string>
{
{Startup.PolicyKey, Startup.SignInPolicyId}
})
{
RedirectUri = "/",
}, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
Where do I insert toDoAfterSignedIn(); method ? or is this the wrong way of doing it, is there some listener or event emitter that will notify me when a user has successfully signed in?
https://github.com/AzureADQuickStarts/B2C-WebApp-OpenIdConnect-DotNet
The correct place to plug-in yourself is the Startup.Auth.cs file. And register yourself for one of the OpenIdConnectNotifications. The notification you need is SecurityTokenValidated. And you will need to add it similarly to the other two notifications which are already in the sample. Or just add the following line within the the OpenIdConnectnotifications initializer:
SecurityTokenValidated = (notification) => {
return Task.Delay(0);
}
The notification parameter you get contains everything you need to know about the end user and his/her successfull authentication.

After first scuccessful login & logout windows live sign in button is not working on windows phone

Am creating an application which used Windows Phone Live Account & I referred Windows Live Sdk sample code for doing that.
xaml
<Grid x:Name="LayoutRoot" Background="Transparent">
<my:SignInButton Name="btnSignin" ClientId="CLIENT_ID" Scopes="wl.signin wl.basic" Branding="Windows" TextType="SignIn" SessionChanged="btnSignin_SessionChanged" HorizontalAlignment="Left" VerticalAlignment="Top" />
</Grid>
Here is the logout code
public void LogOut()
{
var authClient = new LiveAuthClient(ClientId);
authClient.Logout();
}
But after my first successful login & logout, i could not login to the live account means Sign In button is not working even it is not disabled at all. And Every time am getting a LiveConnectSessionStatus.Unknown state on SessionChanged event when i navigated to the login page. What will be the reason for this? Do i need to do anything more in the logout operation? Please confirm.
Thanks
Everything you have to do is:
private LiveConnectClient client;
private async void btnSignin_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
if (e.Status == LiveConnectSessionStatus.Connected)
{
client = new LiveConnectClient(e.Session);
}
else
{
infoTextBlock.Text = "Not signed in.";
}
}
You don't have to program your own Logout - after you signin, the buton changes itself to logout. After SignIn and session changed you have Client - with what you can do what you need.
as you in logout you are creating new session with
public void LogOut()
{
var authClient = new LiveAuthClient(ClientId);
authClient.Logout();
}
you have to use session from which you logged in
and for that you will get logout automatically in session changed handler

Resources