How to use CXCallObserver in Xamarin? - xamarin

I need to subscribe an event to handle incoming phone call. Since iOS version 11.0 CTCallCenter is deprecated we have to use CXCallObserver. I successfully implemented solution for CTCallCenter, but I am not able to subscribe event for CXCallObserver. Does anyone have working solution for CXCallObserver?
Here is my code to subscribe event for CTCallCenter..
_callCenter = new CTCallCenter();
_callCenter.CallEventHandler += CallEvent;
private void CallEvent(CTCall call)
{
CoreFoundation.DispatchQueue.MainQueue.DispatchSync(() =>
{
if(call.CallState.Equals(call.StateIncoming))
//Do something
});
}

Implement the delegate for CXCallObserver:
public class MyCXCallObserverDelegate : CXCallObserverDelegate
{
public override void CallChanged(CXCallObserver callObserver, CXCall call)
{
Console.WriteLine(call);
}
}
Then in your code, create a instance of CXCallObserver (maintain a strong reference to this) and then assign the delegate:
cXCallObserver = new CXCallObserver();
cXCallObserver.SetDelegate(new MyCXCallObserverDelegate(), null);

Related

Xamarin Mac KVO model bindings - change fires twice

I am trying to implement KVO bindings in a Xamarin Mac desktop app.
I have followed the docs, and it is working, but the bindings appear to trigger 2 change events each time!
If I create a KVO model with a binding like this...
private int _MyVal;
[Export("MyVal")]
public int MyVal
{
get { return _MyVal; }
set
{
WillChangeValue("MyVal");
this._MyVal = value;
DidChangeValue("MyVal");
}
}
And bind a control to it in Xcode under the bindings section with the path self.SettingsModel.MyValue
It all appears to work fine, the control shows the model value, changing the model value programmatically updates the control and changing the control updates the model value.
However, it runs the change event twice.
I am listening to the change so I can then hit an API with the value.
SettingsModel.AddObserver(this, (NSString)key, NSKeyValueObservingOptions.New, this.Handle);
Then later...
public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
{
switch (keyPath)
{
case "MyValue":
// CODE HERE THAT UPDATES AN API WITH THE VALUE
// But this handler fires twice.
break;
}
}
Im not sure if its Xamarin or XCode that is causing the double trigger.
Interestingly, if you don't specify the Xcode WillChangeValue and DidChangeValue methods, then it doesn't trigger twice - as though Xamarin has automatically triggered the change once. However, it no longer triggers a change when programmatically updating the model value...
[Export("MyVal")]
public int MyVal { get; set }
The above will work for the Xcode controls, they will update the model and trigger a change event.
But programmatically updating it
this.SettingsModel.MyVal = 1;
Does not trigger the change event.
It's very confusing, any idea on how to stop 2 change events firing, as I don't want to hit the API twice every time!
When it fires twice, the stack trace (abridged) for the first has...
MainViewController.ObserveValue
ObjCRuntime.Messaging.void_objc_msgSendSuper_IntPtr()
Foundation.NSObject.DidChangeValue(string forKey)
CameraSettingsModel.set_MyValue(int value)
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
Which looks fine, but the second...
MainViewController.ObserveValue
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
Has no mention of the Setting Model triggering the event
You are hitting this - Receiving 2 KVO notifications for a single KVC change
and need to override AutomaticallyNotifiesObserversForKey it appears.
Cocoa is "doing you a favor" by sending the notifications for you, which is great except you have the managed version also sending notifications.
It looks something like this:
[Export ("automaticallyNotifiesObserversForKey:")]
public static new bool AutomaticallyNotifiesObserversForKey (string key) => false;
bool _checkValue;
[Export("CheckValue")]
public bool CheckValue
{
get { return _checkValue; }
set
{
WillChangeValue("CheckValue");
_checkValue = value;
DidChangeValue("CheckValue");
}
}
public override void ViewDidLoad ()
{
base.ViewDidLoad();
this.AddObserver("CheckValue", NSKeyValueObservingOptions.New, o =>
{
Console.WriteLine($"Observer triggered for {o}");
});
CheckValue = false;
}

How do I use delegates within Xamarin (specifically UNUserNotificationCenterDelegate)

I need to use the iOS 10 features in UNUserNotificationCenterDelegate. How can I implement this delegate in c# / Xamarin?
When using the an UNUserNotificationCenterDelegate, make sure that you assign it in the WillFinishLaunching or the FinishedLaunching methods in your app's UIApplicationDelegate.
You must assign your delegate object to the UNUserNotificationCenter object no later before your app finishes launching.
Ref: UNUserNotificationCenterDelegate
AppDelegate.cs Example
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
{
// Handle the user approval or refusal of your notifications...
});
UNUserNotificationCenter.Current.Delegate = new MyUNUserNotificationCenterDelegate();
return true;
}
In that example, I am creating/assigning a delegate class named MyUNUserNotificationCenterDelegate, so you need to implement that class.
MyUNUserNotificationCenterDelegate class example:
This UNUserNotificationCenterDelegate example will capture each local notification sent and toggle between showing it on the lock screen or outputting the details to the syslog.
public class MyUNUserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
bool toggle;
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
if (toggle)
completionHandler(UNNotificationPresentationOptions.Alert);
else
{
Console.WriteLine(notification);
completionHandler(UNNotificationPresentationOptions.None);
}
toggle = !toggle;
}
}
Now you will actually need to send some notifications, this sets up a simple repeating notification:
Create/Schedule Local Notification:
// Schedule a repeating Notification...
var content = new UNMutableNotificationContent();
content.Title = new NSString("From SushiHangover");
content.Body = new NSString("StackOverflow rocks");
content.Sound = UNNotificationSound.Default;
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(timeInterval: 60, repeats: true);
var request = UNNotificationRequest.FromIdentifier(identifier: "FiveSecond", content: content, trigger: trigger);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (NSError error) =>
{
if (error != null) Console.WriteLine(error);
});
Every 60 seconds a notification is dispatched and if you are on the lock screen you will receive an alert every 120 seconds...
Recommend reading to understand how you Xamarin.iOS/C# to interact with delegates, protocols, and events:
iOS uses Objective-C delegates to implement the delegation pattern, in which one object passes work off to another. The object doing the work is the delegate of the first object. An object tells its delegate to do work by sending it messages after certain things happen. Sending a message like this in Objective-C is functionally equivalent to calling a method in C#. A delegate implements methods in response to these calls, and so provides functionality to the application.
Ref: Xamarin.iOS and Delegates

Requesting Android permissions in a class (Xamarin)

I'm trying to request a permission at runtime for my app. I use a service provider to talk between the portable class and Android.
I start by calling this code on button press in the PCL:
using (new Busy(this))
{
var locationHelper = scope.Resolve<ILocationHelper>();
locationHelper.GetLocation(this);
}
This calls my Android level service:
public class AndroidLocationHelper : ILocationHelper, ILocationListener
{
readonly string[] PermissionsLocation =
{
Manifest.Permission.AccessCoarseLocation
};
const int RequestLocationId = 0;
public void GetLocation(SearchViewModel viewModel)
{
try
{
const string permission = Manifest.Permission.AccessCoarseLocation;
if (((int)Build.VERSION.SdkInt < 23) || (CheckSelfPermission(permission) == Permission.Granted))
{
}
else
RequestPermissions(PermissionsLocation, RequestLocationId);
}
catch (Exception ex)
{
Debug.WriteLine("Error while getting Location service");
Debug.WriteLine(ex.Message);
Messaging.AlertUser("There was an error with determining your location");
}
}
However, I get two errors on CheckSelfPermission and RequestPermissions. These two methods are only available to activities. The code works fine in MainActivity; however, I want to ask for permissions when the user hits a button, not in OnCreate or OnResume, etc.
Thanks for any help.
In your Android project, You can use this and use the Dependency Service to call it in Xamarin.Forms PCL project later:
var thisActivity = Forms.Context as Activity;
ActivityCompat.RequestPermissions(thisActivity, new string[] {
Manifest.Permission.AccessFineLocation }, 1);
ActivityCompat.RequestPermissions(thisActivity,
new String[] { Manifest.Permission.AccessFineLocation },
1);
You can try with ContextCompat.CheckSelfPermission, passing the application context, like this:
ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission)
Update
In case of ActivityCompat.RequestPermissions, which requires an activity reference, you can keep track of the current activity. There is a very handy lib for that, called "CurrentActivityPlugin". You can find at https://github.com/jamesmontemagno/CurrentActivityPlugin
Rafael came up with a solution but I found another option that is a lot less effort just using MessagingCenter. In the MainActivity's OnCreate add a receiver that runs all the location code, that way you have access to all of the activities methods (and there are a bunch of tutorials on doing location services in MainActivity). Then add the Send inside of your service (the class).
To expound Rafael Steil's answer, I tried the suggested CurrentActivityPlugin and it worked on me. In my case I am trying to execute a voice call which needs CALL_PHONE permission. Here is the code snippet in your case: I used the ContextCompat & ActivityCompat so that I don't need to check the VERSION.SdkInt
using Plugin.CurrentActivity;
public void GetLocation(SearchViewModel viewModel){
var context = CrossCurrentActivity.Current.AppContext;
var activity = CrossCurrentActivity.Current.Activity;
int YOUR_ASSIGNED_REQUEST_CODE = 9;
if (ContextCompat.CheckSelfPermission(context, Manifest.Permission.AccessCoarseLocation) == (int)Android.Content.PM.Permission.Granted)
{
//Permission is granted, execute stuff
}
else
{
ActivityCompat.RequestPermissions(activity, new string[] { Manifest.Permission.AccessCoarseLocation }, YOUR_ASSIGNED_REQUEST_CODE);
}
}
It's dead simple
public bool CheckPermission()
{
const string permission = Manifest.Permission.ReceiveSms;
return ContextCompat.CheckSelfPermission(Forms.Context, permission) == (int) Permission.Granted;
}

How to Poll For Controller Input In UWP App

I'm unsure about the best practice for obtaining and updating input received from a controller monitored using the GamePad class in UWP.
I've seen a couple of examples of people using Dispatch Timers and async loops inside the GamePadAdded event. In Win32 applications, I would have handled input in the WinMain update/message loop, but in UWP apps I don't know of anything similar.
Is there a loop in UWP apps that input should be collected/handled like in Win32 apps? What is the recommended protocol for polling for input from a input device (nominally a Xbox One controller)?
I'm happy to read more about UWP app development but I'm unsure of any guides that reference something like this.
Edit: It would be productive if, instead of downvoting and moving on, you shared thoughts on why this question deserved a downvote.
I've seen a couple of examples of people using Dispatch Timers and async loops inside the GamePadAdded event
This is the right way in UWP app to read Gamepad data. A little suggestion is, move the loop reading part on UI thread if you need to update UI frequently. See the solution in this blog
Is there a loop in UWP apps that input should be collected/handled like in Win32 apps
You may make a wrapper with custom event, see the open source implementation: XBoxGamepad
public class XBoxGamepad
{
private List<Gamepad> _controllers = new List<Gamepad>();
private bool _running = true;
Task backgroundWorkTask;
public event EventHandler<GamepadButtons> OnXBoxGamepadButtonPressA;
//omitted......
public XBoxGamepad()
{
Gamepad.GamepadAdded += Gamepad_GamepadAdded;
Gamepad.GamepadRemoved += Gamepad_GamepadRemoved;
backgroundWorkTask = Task.Run(() => PollGamepad());
}
//omitted......
private void Start()
{
_running = true;
}
public void Stop()
{
_running = false;
}
public async Task PollGamepad()
{
while (true)
{
if (_running)
{
foreach (Gamepad controller in _controllers)
{
if (controller.GetCurrentReading().Buttons == GamepadButtons.A)
{
OnXBoxGamepadButtonPressA(controller, controller.GetCurrentReading().Buttons);
}
//omitted......
}
}
await Task.Delay(50);
}
}
private void Gamepad_GamepadRemoved(object sender, Gamepad e)
{
_controllers.Remove(e);
}
private void Gamepad_GamepadAdded(object sender, Gamepad e)
{
_controllers.Add(e);
}
}

Automatically detect when storing an object with ServiceStack.Redis

I am looking for a way to subscribe to events like Storing a specific object type to ServiceStack.Redis.
For example I may
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.Store(myObject);//<-- I want this to trigger an event somehow
}
Is there anything like a OnStore event which I can hook too, anything out of the box? if not, is there any recommendation about how this should be done?
I don't think there is anything you can hook into (could be wrong).
Two options that came to mind:
1 - Make an extension method
2 - Publish a message to store your object and have a handler that listens for a response and does something. This is probably overkill since it's heading into the publish/subscribe realm. But, I think, worth looking into. (Basic example here and see Pub/Sub here).
Extension Method
public static class RedisClientExtensions
{
public static void StoreWithTrigger<T>(this IRedisTypedClient<T> redisClient, T value, Action<T> trigger)
{
redisClient.Store(value);
trigger(value);
}
}
Using ExtensionMethod
public void MyMethod()
{
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.StoreWithTrigger<MyObject>(new MyObject(), TriggerEvent);//<-- I want this to trigger an event somehow
}
}
private void TriggerEvent<T>(T value)
{
//dosomething
}
Hope this gives you some ideas.

Resources