Can anyone please give me any idea for show badge count in Xamarin iOS when application in background
Actually In background there are no any method trigger in Xamarin iOS when notification come.
public class UserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
#region Constructors
public UserNotificationCenterDelegate()
{
}
#endregion
#region Override Methods
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
/// here we can add badge
}
}
*****************
public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions)
{
UNUserNotificationCenter.Current.Delegate = new UserNotificationCenterDelegate();
----------
------------
}
Related
I am using Xamarin (C#) code for a macOS app. I have created the WKWebView and have outlet, added Navigation and UI delegates and trying to open an URL.
The Navigation delegates methods are getting called, but not sure what am I missing that UI Delegates method is not getting called.
Any help / guidance what to look for, or what mistake I am doing here, please.
Here's the code and image of same:
public override void ViewDidLoad()
{
base.ViewDidLoad();
var url = new NSUrl("https://google.com");
var request = new NSMutableUrlRequest(url);
_webView.UIDelegate = new WebViewDelegate();
_webView.NavigationDelegate = new WebViewNavigationDelegate();
_webView.LoadRequest(request);
}
}
internal class WebViewDelegate : WKUIDelegate
{
public override WKWebView CreateWebView(WKWebView webView, WKWebViewConfiguration configuration, WKNavigationAction navigationAction, WKWindowFeatures windowFeatures)
{
Console.WriteLine("this doesn't reach");
return null;
}
}
internal class WebViewNavigationDelegate : WKNavigationDelegate
{
public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
Console.WriteLine("this prints");
}
}
Context: I am handed this massive enterprise iOS & Android Xamarin Native applications that doesn't use ViewModels or any MVVM framework. It does have a separated Network services layer and it has a lot of pages, so starting over won't make any sense.
Why the change is needed: No MVVM, the services layer is called directly from the UI classes (Fragments & ViewControllers), and there is no good abstraction. So I will start with 1 view and then create TechDebt to transform the rest of the app.
What I know:
Adding MVVM frameworks require creating extensive changes, especially to use Navigation services for Navigating the views, and are best done if added when green-fielding the application.
As seen here, Android has an easy way of using a ViewModel but I won't be able to use that for iOS then.
I also know that I can launch a Xamarin Forms page instead and that will be all ready for MVVM, since I can just assign the BindingContext property to an instance of the ViewModel.
What I need: I need to create one new page for iOS & one for Android. I want to be able to create a ViewModel that's shared between iOS & Android. I want to be able to use it for a single view that I am creating and it should be initialized when the page is loaded.
How can I add 1 viewmodel that's shared by a ViewController & a Fragment? Am I missing something, is it much easier than I am making it?
Ended up being able to use MvvmLight for this. Added the Nuget package to the projects, Created a ViewModelBase in the Core Shared Library Project:
public abstract class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase
{
private PropertyChangedEventHandler propertyChangedEventHandler;
protected bool IsLoading { get; set; }
public bool RegisteredPropertyEventHandler { get; set; }
public const string ErrorMessagePropertyName = "ErrorMessage";
public string ErrorMessage { get; set; }
public string SuccessMessage { get; set; }
public void RegisterPropertyEventHandler(PropertyChangedEventHandler propertyChangedEventHandler)
{
this.propertyChangedEventHandler = propertyChangedEventHandler;
this.PropertyChanged += propertyChangedEventHandler;
this.RegisteredPropertyEventHandler = true;
}
public void UnegisterPropertyEventHandler()
{
if (this.RegisteredPropertyEventHandler)
{
this.PropertyChanged -= propertyChangedEventHandler;
this.RegisteredPropertyEventHandler = false;
this.propertyChangedEventHandler = null;
}
}
public void TearDown()
{
this.UnegisterPropertyEventHandler();
}
protected void NotifyError (string message)
{
this.ErrorMessage = message;
RaisePropertyChanged (() => ErrorMessage);
}
}
and a ViewModelLocator
public class ViewModelLocator
{
public const string ABCPageKey = "ABCPage";
public ABCViewModel ABC
{
get
{
return ServiceLocator.Current.GetInstance<ABCViewModel> ();
}
}
public ViewModelLocator ()
{
ServiceLocator.SetLocatorProvider (() => SimpleIoc.Default);
// Register all of the view models
SimpleIoc.Default.Register<ABCViewModel> ();
}
public static void Cleanup ()
{
}
public T GetViewModel<T> ()
{
return ServiceLocator.Current.GetInstance<T> ();
}
}
On the iOS side, I already had a BaseUIViewController, so I created a BaseViewModelUIViewController on top of it
public abstract partial class BaseViewModelUIViewController<T> : BaseUIViewController where T : ViewModelBase
{
public T ViewModel
{
get
{
return App.Locator.GetViewModel<T> ();
}
}
public BaseViewModelUIViewController (IntPtr handle) : base (handle)
{
}
internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
switch (e.PropertyName)
{
default:
break;
}
}
}
And then Android, similarly I already had a BaseFragment, so I created a BaseViewModelFragment on top of it
public class BaseViewModelFragment<T> : BaseFragment where T : ViewModelBase
{
public T ViewModel
{
get
{
return App.Locator.GetViewModel<T> ();
}
}
public BaseViewModelFragment (string title) : base (title)
{
}
internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
switch (e.PropertyName)
{
default:
break;
}
}
public override void OnDestroyView ()
{
this.ViewModel.TearDown ();
base.OnDestroyView ();
}
}
I hope it makes sense to other people looking for solutions.
Creating ViewModels: So naturally, for every new ViewModel created, I had to register it in the ViewModelLocator.
Using ViewModels: In terms of usage, you can simply use the ViewModel in the UI by inheriting from the ": BaseViewModelUIViewController" for iOS or from ": BaseViewModelFragment" for Android
Unfortunately you don't miss anything, all your claims are proper and you have properly listed various directions that you can take (and that you don't like).
Xamarin.Android and Xamarin.iOS are not made with data binding in mind, but rather with using the native interfaces, only Xamarin.Forms is made for the data binding. The capabilities of native platforms to use the data binding is limited (if it existed it would be incompatible among the platforms and you would have to make separate view models, and there is not data binding for iOS as of now anyway).
So basically there is no data binding in Xamarin.iOS and Xamarin.Android. It is completely up to you to abstract the shared business model and connect it with the user interface.
I am using Xamarin.Mac, and I am writing a text to speech project.
In Xamarin.Mac, the class NSSpeechSynthesizer does not provide the event DidFinishSpeaking. May I know how I can get notified when the speaking is finished?
Thank you very much
NSSpeechSynthesizer provides a delegate in the form of an interface (INSSpeechSynthesizerDelegate) that contains the DidFinishSpeaking method:
public partial class ViewController : NSViewController, INSSpeechSynthesizerDelegate
{
~~~~~~
public override void ViewDidLoad()
{
base.ViewDidLoad();
var s = new NSSpeechSynthesizer(NSSpeechSynthesizer.DefaultVoice)
{
Delegate = this
};
s.StartSpeakingString("StackOverflow");
}
[Export("speechSynthesizer:didFinishSpeaking:")]
public void DidFinishSpeaking(NSSpeechSynthesizer sender, bool finishedSpeaking)
{
Console.WriteLine("Done speaking");
}
~~~~~~
}
I am implementing WKWebView in iOS Xamarin and i want to do something when load start and load finish. I have implemented IWKNavigationDelegate and added the following functions but non of them gets called. Am i missing something
Class definition
public partial class MasterViewController : UIViewController,IScanSuccessCallback, IWKScriptMessageHandler, IWKNavigationDelegate
{ }
Navigation Delegate functions
public void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
Console.WriteLine ("DidFinishNavigation");
}
public void DidFailNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailNavigation");
}
public void DidFailProvisionalNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailProvisionalNavigation");
}
public void DidStartProvisionalNavigation( WKWebView webView, WKNavigation navigation )
{
// When navigation starts, this gets called
Console.WriteLine("DidStartProvisionalNavigation");
}
complementing Jason's answer.
You are missing the required ExportAttribute for optional delegate methods, Xamarin Studio auto completion engine should generate this for you each time you implement any IFooInterface when Foo is an ObjC delegate and you type override (it should list optional and not optional members). ExportAttribute is only required for optional members (non abstract members in the c# interface).
In this particular case all members of WKNavigationDelegate ObjC protocol are optional so you need the Export attribute and the ObjC selector as its parameter.
You need to add using Foundation to your using statements, ExportAttribute is inside it.
[Export ("webView:didFinishNavigation:")]
public void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
Console.WriteLine ("DidFinishNavigation");
}
[Export ("webView:didFailNavigation:withError:")
public void DidFailNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailNavigation");
}
[Export ("webView:didFailProvisionalNavigation:withError:")]
public void DidFailProvisionalNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailProvisionalNavigation");
}
[Export ("webView:didStartProvisionalNavigation:")]
public void DidStartProvisionalNavigation( WKWebView webView, WKNavigation navigation )
{
// When navigation starts, this gets called
Console.WriteLine("DidStartProvisionalNavigation");
}
Hope this helps.
You need to explicitly assign the NavigationDelegate class to webview
WKWebView web = new WKWebView();
// if the current class implements IWKNavigationDelegate, you can do this
web.NavigationDelegate = this;
// or you can create a separate class that implements IWKNavigationDelegate
web.NavigationDelegate = new MyWebDelegate();
I can use - (BOOL)applicationShouldTerminateAfterLastWindowClosed: method to quit cocoa app when window closes by using the method in application's delegate.
How can I do the same thing with MonoMac? In general, how can I map objective-c method to MonoMac's C# function?
I found this code, I see that I can use the same function in the delegate.
namespace AnimatingViews
{
public partial class AppDelegate : NSApplicationDelegate
{
AnimatingViewsWindowController animatingViewsWindowController;
public AppDelegate ()
{
}
public override void FinishedLaunching (NSObject notification)
{
animatingViewsWindowController = new AnimatingViewsWindowController ();
animatingViewsWindowController.Window.MakeKeyAndOrderFront (this);
}
public override bool ApplicationShouldTerminateAfterLastWindowClosed (NSApplication sender)
{
return true;
}
}
}