I am using Xamarin.Essentials to handle connectivity changes, it all works on android
However I have noticed that in iOS it didnt work, I debugged and noticed that
sliding down the screen in iOS Physical device
Put the phone in Plane Mode and remove wifi
Sleep event fired and removed connectivity
//App.Xaml
protected override void OnSleep()
{
Connectivity.ConnectivityChanged -= OnConnectivityChanged;
}
protected override void OnStart()
{
Connectivity.ConnectivityChanged += OnConnectivityChanged;
}
protected override void OnResume()
{
Connectivity.ConnectivityChanged += OnConnectivityChanged;
}
if I comment out
Connectivity.ConnectivityChanged -= OnConnectivityChanged;
it all works.
Am I missing the obvious?
WHere I am supposed to detach the connectivity?
This is because the Forms lifecycle is somewhat different from the declarative lifecycle approach of native platform, and you can do this directly in the native ios lifecycle.
in your ios project AppDelegate.cs :
public override void OnActivated(UIApplication application)
{
Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;
}
public override void DidEnterBackground(UIApplication uiApplication)
{
Connectivity.ConnectivityChanged -= Connectivity_ConnectivityChanged;
}
private void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
{
//do some thing
}
You could refer to the lefecycle.
Note:
on iOS 13 (and later),you need write them to SceneDelegate as well.
Related
I'm changing the orientation(Landscape/Portrait) forcefully for one screen.
For that, I used IsGestureEnabled property.
That property is not working on iOS 16 or above versions.
CODE:
protected override void OnDisappearing()
{
SetGestureEnabled(true);
base.OnDisappearing();
}
protected override void OnAppearing()
{
SetGestureEnabled(false);
base.OnAppearing();
}
private void SetGestureEnabled(bool isSet)
{
if (Application.Current.MainPage is MasterDetailPage masterDetailPage)
{
masterDetailPage.IsGestureEnabled = isSet;
}
}
Please help me to resolve this issue.
MasterDetailPage is obsolete. Try using FlyoutPage instead.
FlyoutPage also has IsGestureEnabled property which could disable or enable the swipe gesture. The default value is true. you could use almost the same code in your question
if (Application.Current.MainPage is FlyoutPage flyoutPage)
{
flyoutPage.IsGestureEnabled = true;
}
For more info, you could refer to Xamarin.Forms FlyoutPage
I want a process to be called each time I navigated to my view to refresh a list.
I am using Xamarin Forms and prism framework.
I made my ViewModel derivate from ContentPage but the following method is never called :
protected override void OnAppearing()
{
//Do things
}
How am I supposed to do to get the event? Is it better to use OnNavigateTo?
Through the document:
There are times in your application where you may want to invoke code
in your ViewModel based on when the Page Appears or Disappears without
Navigation specific consideration. For these times you can utilize the
IPageLifecycleAware interface to properly respond to the Appearing and
Disappearing events from the Page.
public class ViewAViewModel : IPageLifecycleAware
{
public void OnAppearing()
{
Console.WriteLine("We are appearing");
}
public void OnDisappearing()
{
Console.WriteLine("We are disappearing");
}
}
I found a solution to make my code work, I add to do this in my code behind from the page:
protected override void OnAppearing()
{
(BindingContext as IPageLifecycleAware)?.OnAppearing();
}
Still a mystery why I need to add this and it is not in the sample.
at the time of this post, the sample does it differently. It uses Behaviors to achieve expectation
It has a PageLifeCycleAwareBehavior class
private void OnAppearing(object sender, EventArgs e)
{
MvvmHelpers.InvokeViewAndViewModelAction<IPageLifecycleAware>(AssociatedObject, aware => aware.OnAppearing());
}
private void OnDisappearing(object sender, EventArgs e)
{
MvvmHelpers.InvokeViewAndViewModelAction<IPageLifecycleAware>(AssociatedObject, aware => aware.OnDisappearing());
}
You can see the full implementation here
You can also call Initialize is a good alternative
Add ini to your class
public class HelloViewModel : BindableBase, IInitialize
then add the following method
public void Initialize(INavigationParameters parameters)
{
// Do stuff
}
I am working on a Xamarin Forms project for which one requirement is to recognize certain key presses to trigger hot key actions. The devices that we will be deploying the application to have physical keyboards attached. For now, Android is the only platform that is being targeted.
From some research that I did yesterday afternoon, it sounds as though a custom page renderer is what is required. As I played with this concept this morning, I stumbled upon the On* key methods of the Activity class.
I tried adding the following to the MainActivity class in the Android project:
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
{
return base.OnKeyUp(keyCode, e);
}
Placing a breakpoint on this method seems to show that this code is what is needed (read, this method is fired whenever I press a key on the keyboard).
The issue is that this method is also fired when an Entry control on the page has focus. Shouldn't the key press be handled by the Entry control and not bubbled up to the page?
Generally speaking, is this the right approach for what I am trying to accomplish? Are there other approaches that someone can point me to that might work better?
When I was working with hardware devices, I had to do something similar. I created a custom renderer for an entry on the Xamarin.android side. This captures the Enter key press for both hard and soft key in different events. I think creating custom render for a page like you did could work too but this only captures key presses for elements that are in focus. This works for me as I have the entry in focus when user presses the hardware Enter key.
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace Project.Droid.Controls {
public class CustomEntryRenderer : EntryRenderer {
public CustomEntryRenderer(Context context) : base(context) {
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) {
base.OnElementChanged(e);
Control.EditorAction += Control_EditorAction;
Control.KeyPress += NativeEditText_KeyPress;
}
// Fires only for Soft Keyboard
private void Control_EditorAction(object sender, Android.Widget.TextView.EditorActionEventArgs e) {
if (e.ActionId == ImeAction.Done) {
// your code
e.Handled = true;
}
}
// Fires for Hard Keyboard
private void NativeEditText_KeyPress(object sender, KeyEventArgs e) {
if (e.KeyCode == Keycode.Enter && e.Event.Action == KeyEventActions.Up) {
// your code
e.Handled = true;
}
else
e.Handled = false;
}
}
}
FYI: I also tried the MainActivity event that you are using and it did not work for me. I cannot recall why.
I'm developing an app and I need to know when the app gets Stopped, Closed, Exited, whatever interrupts it, in order to stop some services such as WebSocket. How can I get 'access' to those events?
Thanks!
I have tested the following in a small example. (Tested it on UWP and works, the OnSleep() is called, when i close the App). The OnSleep() Method which can be overridden in the App.xaml.cs is the Method you are looking for.
The Xamarin Application LifeCycle offers some methods for your needs.
OnStart - Called when the application starts.
OnSleep - Called each time the application goes to the background.
OnResume - Called when the application is resumed, after being sent to the background.
Note that there is no method for application termination. Under normal
circumstances (ie. not a crash) application termination will happen
from the OnSleep state, without any additional notifications to your
code.
Example:
using System;
using System.Diagnostics;
using Xamarin.Forms;
namespace App1
{
public partial class App : Application
{
public App()
{
InitializeComponent();
if (Device.RuntimePlatform == Device.iOS)
MainPage = new MainPage();
else
MainPage = new NavigationPage(new MainPage());
}
protected override void OnStart() {
Debug.WriteLine("OnStart");
}
protected override void OnSleep() {
Debug.WriteLine("OnSleep");
}
protected override void OnResume() {
Debug.WriteLine("OnResume");
}
}
}
Update
According to this you have to catch unhandled exceptions in the native code. That makes it a lil complicated to shutdown your services.
Example:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity {
protected override void OnCreate(Bundle bundle) {
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
}
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs) {
//crashed by exception
}
}
Further Reading on Unhandled Exceptions: here
So I've been following this Android Tutorial (Youtube) by Derek Banas. Trying to learn to make a NavigationDrawer.
I run into onAttach() being deprecated. I looked at this Stack Overflow link but I'm a beginner in AS and can't understand if it's correct (mainly due to me not sure if I have to instantiate MTitle, mCalled, mHost,etc) and how I can possibly implement it, in my app.
onAttach code:
public void onAttatch(Activity activity) {
super.onAttach(activity);
((MainActivity)activity).onSectionAttached(1);
}
public void onSectionAttached(int number) {
switch(number) {
case 1:
mTitle = getString(R.string.title_section1);
break;
}
Try
public void onAttach(Context context){
super.onAttach(context);
...
}