I had a lot of problems when I tried to use FusedLocationApi from my Xamarin activity. The approach used by the code listed here Location Xamarin has been marked obsolete, so it didn't compile. My implementation is as follows. The question I have is, if this is the way to do it or if I am overlooking something much easier? The LocationHandler is used by my activity, e.g. OnCreate, OnResume, OnPause call the connect and disconnect methods. The OnChangedLocation method should of course do something more intelligent.
using System;
using Android.Gms.Common;
using Android.Gms.Common.Apis;
using Android.Gms.Location;
using Android.Locations;
using Android.Util;
using Android.OS;
using Android.Content;
namespace WithKidsAndroid
{
public class LocationHandler : Java.Lang.Object, IGoogleApiClientConnectionCallbacks, IGoogleApiClientOnConnectionFailedListener, Android.Gms.Location.ILocationListener
{
private IGoogleApiClient _googleAPI;
private Context _context;
public LocationHandler(Context context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
else
{
_context = context;
}
initializeGoogleAPI();
LocRequest = new LocationRequest();
}
public LocationHandler(Context context, LocationRequest request)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
else
{
_context = context;
}
initializeGoogleAPI();
LocRequest = request;
}
public LocationRequest LocRequest
{
get;
set;
}
public void connectGoogleAPI()
{
System.Diagnostics.Debug.Assert(_googleAPI != null);
if (!_googleAPI.IsConnectionCallbacksRegistered(this))
{
_googleAPI.RegisterConnectionCallbacks(this);
}
if (!_googleAPI.IsConnectionFailedListenerRegistered(this))
{
_googleAPI.RegisterConnectionFailedListener(this);
}
if (!_googleAPI.IsConnected || !_googleAPI.IsConnecting)
{
_googleAPI.Connect();
}
}
public void disconnectGoogleAPI()
{
if (_googleAPI != null && _googleAPI.IsConnected)
{
if (_googleAPI.IsConnectionCallbacksRegistered(this))
{
_googleAPI.UnregisterConnectionCallbacks(this);
}
if (_googleAPI.IsConnectionFailedListenerRegistered(this))
{
_googleAPI.UnregisterConnectionFailedListener(this);
}
_googleAPI.Disconnect();
}
}
public void OnConnected(Bundle connectionHint)
{
Log.Debug("LocationHandler", "logged connected", connectionHint);
if (LocRequest == null)
{
throw new Exception("Unknown location request. Set this first by using property LocRequest or constructor.");
}
LocationServices.FusedLocationApi.RequestLocationUpdates(_googleAPI, LocRequest, this);
}
public void OnConnectionSuspended(int cause)
{
Log.Debug("LocationHandler", "logged OnConnectionSuspended", cause);
}
public void OnConnectionFailed(ConnectionResult result)
{
Log.Debug("LocationHandler", "logged OnConnectionFailed", result);
}
public void OnLocationChanged(Location location)
{
Log.Debug("LocationHandler", "logged location changed: " + location.ToString());
}
private void initializeGoogleAPI()
{
int queryResult = GooglePlayServicesUtil.IsGooglePlayServicesAvailable(_context);
if (queryResult == ConnectionResult.Success)
{
_googleAPI = new GoogleApiClientBuilder(_context).AddApi(LocationServices.Api).AddConnectionCallbacks(this).AddOnConnectionFailedListener(this).Build();
}
else
{
var errorString = String.Format("There is a problem with Google Play Services on this device: {0} - {1}", queryResult, GooglePlayServicesUtil.GetErrorString(queryResult));
Log.Error("WithKidsAndroid.LocationHandler", errorString);
throw new Exception(errorString);
}
}
}
}
I guess not. I will close the question, but not remove the question as people can then find an example of LocationServices that work.
Related
I am trying to implement SQLite into my Xamarin.Forms Shared Assets project from this article.
https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/databases/
All appears to be set up correctly tyo my novice eyes, however there seems to be a problem in creating the database connection. It says its Not able to implicitly convert type SQLite.SQLiteAsyncConnection to TechsportiseApp.Data.TechsportiseData
I can't work out why this is. Any ideas?
using System;
using System.Collections.Generic;
using System.Text;
using SQLite;
using Xamarin.Forms;
using static TechsportiseApp.Helpers.GlobalFunctions;
using TechsportiseApp.Models;
using System.Threading.Tasks;
namespace TechsportiseApp.Data
{
class TechsportiseData
{
public TechsportiseData(string dbPath)
{
database = new SQLite.SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<Scan>().Wait();
database.CreateTableAsync<Timing>().Wait();
}
static TechsportiseData database;
public static TechsportiseData Database
{
get
{
if (database == null)
{
database = new TechsportiseData(DependencyService.Get<IFileHelper>().GetLocalFilePath("TechsportiseData.db3"));
}
return database;
}
}
public Task<List<Timing>> GetTimingsAsync()
{
return database.Table<Timing>().ToListAsync();
}
public Task<List<Timing>> GetTimingsNotUploadedAsync()
{
return database.QueryAsync<Timing>("SELECT * FROM [Timing] WHERE [Uploaded] = 0");
}
public Task<Timing> GetTimingAsync(int id)
{
return database.Table<Timing>().Where(i => i.ID == id).FirstOrDefaultAsync();
}
public Task<int> SaveTimingAsync(Timing timing)
{
if (timing.ID != 0)
{
return database.UpdateAsync(timing);
}
else
{
return database.InsertAsync(timing);
}
}
public Task<int> DeleteTimingAsync(Timing timing)
{
return database.DeleteAsync(timing);
}
public Task<int> DeleteAllTimingsAsync()
{
return database.DeleteAllAsync(timing);
}
public Task<List<Scan>> GetScansAsync()
{
return database.Table<Scan>().ToListAsync();
}
public Task<List<Scan>> GetScansNotUploadedAsync()
{
return database.QueryAsync<Timing>("SELECT * FROM [Scan] WHERE [Uploaded] = 0");
}
public Task<Scan> GetScanAsync(int id)
{
return database.Table<Scan>().Where(i => i.ID == id).FirstOrDefaultAsync();
}
public Task<int> SaveScanAsync(Scan scan)
{
if (scan.ID != 0)
{
return database.UpdateAsync(scan);
}
else
{
return database.InsertAsync(scan);
}
}
public Task<int> DeleteScanAsync(Scan scan)
{
return database.DeleteAsync(scan);
}
public Task<int> DeleteAllScanssAsync()
{
return database.DeleteAllAsync(scan);
}
}
}
The first and most obvious thing is this doesn't make sense
static TechsportiseData database;
change it to this
readonly SQLiteAsyncConnection database;
So it turns out the section of code
static TechsportiseData database;
public static TechsportiseData Database
{
get
{
if (database == null)
{
database = new TechsportiseData(DependencyService.Get<IFileHelper>().GetLocalFilePath("TechsportiseData.db3"));
}
return database;
}
}
Needed to be in App.cs which I didn't realize. Seems good now!
I'm deriving from UIApplication and overriding SendEvent to capture user taps.
Everything works fine, except when closing modals of type IMvxModalIosView.
Here's the method:
public override void SendEvent(UIEvent uievent)
{
NSSet touches = uievent.AllTouches;
if (touches != null)
{
UITouch touch = (UITouch)touches.AnyObject;
switch (touch.Phase)
{
case UITouchPhase.Ended:
StartDoingStuffAgain();
break;
default:
StopDoingStuff();
break;
}
}
base.SendEvent(uievent);
}
Debugging this while closing an IMvxModalIosView, if I set a breakpoint at the start of the method, as well as StartDoingStuffAgain(), the latter gets hit. If however I only set a breakpoint at StartDoingStuffAgain(), it never gets hit. StopDoingStuff() gets hit regardless.
Why is this?
Edit 1: As per nmilcoff's request for more code:
[Register("AppDelegate")]
public partial class AppDelegate : MvxApplicationDelegate
{
//...
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
//...
_app = application as MyUIApplication;
//...
}
//...
}
[Register("MyUIApplication")]
public class MyUIApplication : UIApplication
{
//...
// Bit of code in original question goes here.
//...
}
//The iPad view presenter (iPhone has MyIPhoneViewPresenter)
public class MyIPadViewPresenter : MvxBaseIosViewPresenter
{
//...
private UINavigationController _navController;
private UINavigationController _modalNavController;
private IMvxMessenger _messenger;
protected readonly SemaphoreSlim _autoLock = new SemaphoreSlim(1, 1);
//...
public override async void Show(MvxViewModelRequest request)
{
await _autoLock.WaitAsync();
//...
if(_messenger == null)
{
_messenger = Mvx.Resolve<IMvxMessenger>();
}
// Among other things, the following method checks if the page
// corresponding to the VM request is a Xamarin.Forms or a native view.
var presentation = MvxIOSPresentationHelpers.CreateView(request, TargetIdiom.Tablet);
switch(presentation.Type)
{
//...
case ViewType.ModalWithNav:
showNavModalView(presentation.ViewController);
break;
//...
}
messenger.Publish(new ViewModelShowMessage(request.ViewModelType, presentation.ViewController, this));
//..
_autoLock.Release();
}
//...
private void showNavModalView(UIViewController viewController)
{
if(_modalNavController == null)
{
_modalNavController = new ModalNavController(viewController);
_modalNavController.ModalPresentationStyle = viewController.ModalPresentationStyle;
_navController.PresentViewController(_modalNavController, false, delegate { });
}
else
{
_modalNavController.PushViewController(viewController, true);
}
//...
}
//...
public override async void ChangePresentation(MvxPresentationHint hint)
{
var close_hint = hint as MvxClosePresentationHint;
if (close_hint != null)
{
await _autoLock.WaitAsync();
close(close_hint.ViewModelToClose);
_autoLock.Release();
}
else
{
//...
}
}
//...
protected void close(IMvxViewModel toClose)
{
//...
_messenger.Publish(new MvxMessage(this));
//...
if (_modalNavController != null)
{
if(_modalNavController.ChildViewControllers.Length <= 1)
{
// This is where the close sequence comes down to.
_modalNavController.DismissViewController(true, delegate{ });
_modalNavController = null;
}
else
{
//...
}
return;
}
//..
}
//...
}
// The VM corresponding to the IMvxModalIosView
public class MyProblematicModalVM : MvxViewModel
{
//...
public ICommand CloseCommand
{
get { return new MvxCommand(() => Close(this)); }
}
//...
}
I'm developing an application for detecting motion within webcam frames.
For this, I'm using IBasicVideoEffect for extracting frames one by one from MediaCapture. I have created class CustomEffect which inherits IBasicVideoEffect. I have used OpenCV for motion detection, it is working fine. It is also giving me motion detection level. I want to raise event from CustomEffect if motion level is greater than threshold.
But for videoDefination code is:
var videoDefinition = new VideoEffectDefinition(typeof(CustomEffect).ToString());
Here for videoDefinition constructor it is asking for ClassID,
How can i get event from CustomEffect object.
I want to raise custom event from CustomEffect (eg.: MotionDetectedEvent )
Here is my CustomEffect class:
public sealed class CustomEffect : IBasicVideoEffect
{
private OpenCVHelper _helper;
private IPropertySet _configuration;
internal event EventHandler<EventArgs> MotionDetected;
public void SetProperties(IPropertySet configuration)
{
_configuration = configuration;
}
public void SetEncodingProperties(VideoEncodingProperties encodingProperties,
IDirect3DDevice device)
{
}
private bool IsToDetectMotion
{
get
{
object val;
if (_configuration != null &&
_configuration.TryGetValue("IsToDetectMotion", out val))
return (bool) val;
return false;
}
}
public void ProcessFrame(ProcessVideoFrameContext context)
{
var tempBitmap = context.OutputFrame.SoftwareBitmap;
context.InputFrame.SoftwareBitmap.CopyTo(tempBitmap);
var originalBitmap = SoftwareBitmap.Convert(tempBitmap, BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight);
var outputBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8,
originalBitmap.PixelWidth, originalBitmap.PixelHeight,
BitmapAlphaMode.Straight);
if (!IsToDetectMotion)
{
context.InputFrame.SoftwareBitmap.CopyTo(context.OutputFrame.SoftwareBitmap);
return;
}
if (_helper == null)
_helper = new OpenCVHelper();
var level = _helper.MotionDetector(tempBitmap, outputBitmap);
RaiseMotionDetectedEvent();
Debug.WriteLine(level.ToString());
outputBitmap.CopyTo(context.OutputFrame.SoftwareBitmap);
}
private void RaiseMotionDetectedEvent()
{
if (MotionDetected != null)
MotionDetected(this, new EventArgs());
}
public void Close(MediaEffectClosedReason reason)
{
}
public void DiscardQueuedFrames()
{
}
public bool IsReadOnly { get; }
public IReadOnlyList<VideoEncodingProperties> SupportedEncodingProperties
{
get
{
var encodingProperties = new VideoEncodingProperties();
encodingProperties.Subtype = "ARGB32";
return new List<VideoEncodingProperties> {encodingProperties};
// If the list is empty, the encoding type will be ARGB32.
// return new List<VideoEncodingProperties>();
}
}
public MediaMemoryTypes SupportedMemoryTypes { get; }
public bool TimeIndependent { get; }
}
//in Windows Runtime Component
public sealed class FrameArgs
{
public FrameArgs(int frameCount)
{
FrameCount = frameCount;
}
public int FrameCount
{ get; }
}
public sealed partial class CustomEffect
{
#region ProcessFrameCompleted
public EventHandler<Object> ProcessFrameCompleted
{
get
{
object val;
if (configuration != null && configuration.TryGetValue(nameof(ProcessFrameCompleted), out val))
{
return (EventHandler<Object>)val;
}
return null;
}
}
public void RaiseProcessFrameCompleted(FrameArgs args)
{
ProcessFrameCompleted?.Invoke(null, (Object)args);
}
#endregion
//call as necessary
//RaiseProcessFrameCompleted(new FrameArgs(frameCount));
}
//in your app
public static async Task<IMediaExtension> AddCustomEffect(MediaCapture mediaCapture, EventHandler<FrameArgs> callBack)
{
if (mediaCapture == null)
{
throw new ArgumentException("Parameter cannot be null", nameof(mediaCapture));
}
var videoEffectDefinition =
// ReSharper disable once AssignNullToNotNullAttribute
new VideoEffectDefinition(typeof(CustomEffect).FullName);
var videoEffect =
await mediaCapture.AddVideoEffectAsync(videoEffectDefinition, MediaStreamType.VideoPreview);
videoEffect.SetProperties(
new PropertySet()
{
{
"ProcessFrameCompleted",
new EventHandler<object>((sender, e) =>
{
var args = (FrameArgs)e;
int frameCount = args.FrameCount;
callBack?.Invoke(sender, args);
})
}
});
return videoEffect;
}
I need to implement automatic UI Tests for a Delphi Application with Visual Studio Coded UI Tests. I have already implemented the IAccessible Interface to my Delphi-Contols. It works fine and i get the AccessibleName from the Control.
Then i implemented an extension for visual studio. In this extension i have my own PropertyProvider-, ExtensionPackage- and WinControl-Class.
PropertyProvider:
namespace CUITExtension
{
public class AccessibleNamePropertyProvider : UITestPropertyProvider
{
private static Dictionary<string, UITestPropertyDescriptor> accessibleNamePropertyMap = null;
private static Dictionary<string, UITestPropertyDescriptor> AccessibleNamePropertyMap
{
get
{
if (accessibleNamePropertyMap == null)
{
UITestPropertyAttributes read = UITestPropertyAttributes.Readable
| UITestPropertyAttributes.DoNotGenerateProperties;
accessibleNamePropertyMap = new Dictionary<string, UITestPropertyDescriptor>
(StringComparer.OrdinalIgnoreCase);
accessibleNamePropertyMap.Add("AccessibleName", new UITestPropertyDescriptor(typeof(string), read));
}
return accessibleNamePropertyMap;
}
}
public override UITestPropertyDescriptor GetPropertyDescriptor(UITestControl uiTestControl, string propertyName)
{
return AccessibleNamePropertyMap[propertyName];
}
public override ICollection<string> GetPropertyNames(UITestControl uiTestControl)
{
if (uiTestControl.ControlType.NameEquals("Custom"))
{
// the keys of the property map are the collection of property names
return AccessibleNamePropertyMap.Keys;
}
throw new NotSupportedException();
}
public override object GetPropertyValue(UITestControl uiTestControl, string propertyName)
{
if (String.Equals(propertyName, "AccessibleName", StringComparison.OrdinalIgnoreCase))
{
object[] native = uiTestControl.NativeElement as object[];
IAccessible acc = native[0] as IAccessible;
return acc.accName;
}
throw new NotSupportedException();
}
public override int GetControlSupportLevel(UITestControl uiTestControl)
{
if (string.Equals(uiTestControl.TechnologyName, "MSAA",
StringComparison.OrdinalIgnoreCase) &&
uiTestControl.ControlType.NameEquals("Custom"))
{
return (int)ControlSupport.ControlSpecificSupport;
}
// This is not my control, so return NoSupport
return (int)ControlSupport.NoSupport;
}
public override string[] GetPredefinedSearchProperties(Type specializedClass)
{
return null;
}
public override string GetPropertyForAction(UITestControl uiTestControl, UITestAction action)
{
return null;
}
public override string[] GetPropertyForControlState(UITestControl uiTestControl, ControlStates uiState, out bool[] stateValues)
{
stateValues = null;
return null;
}
public override Type GetPropertyNamesClassType(UITestControl uiTestControl)
{
if (uiTestControl.ControlType.NameEquals("Custom"))
return typeof(AccessibleControl.PropertyNames);
return null;
}
public override Type GetSpecializedClass(UITestControl uiTestControl)
{
if (uiTestControl.ControlType.NameEquals("Custom"))
return typeof(AccessibleControl);
return null;
}
public override void SetPropertyValue(UITestControl uiTestControl, string propertyName, object value)
{
return;
}
}
}
ExtensionPackage:
[assembly: Microsoft.VisualStudio.TestTools.UITest.Extension.UITestExtensionPackage(
"AccessibleNameExtensionPackage",
typeof(CUITExtension.AccessibleNameExtensionPackage))]
namespace CUITExtension
{
class AccessibleNameExtensionPackage : UITestExtensionPackage
{
public override string PackageDescription
{
get { return "Supports coded UI testing by using the AccessibleName"; }
}
public override string PackageName
{
get { return "AccessibleName Extension Package"; }
}
public override string PackageVendor
{
get { return "Microsoft (sample)"; }
}
public override Version PackageVersion
{
get { return new Version(1, 0); }
}
public override Version VSVersion
{
get { return new Version(14, 0); }
}
public override void Dispose() { }
public override object GetService(Type serviceType)
{
if (serviceType == typeof(UITestPropertyProvider))
{
if (propertyProvider == null)
{
propertyProvider = new AccessibleNamePropertyProvider();
}
return propertyProvider;
}
return null;
}
private UITestPropertyProvider propertyProvider = null;
}
}
WinControl:
namespace CUITExtension
{
public class AccessibleControl : WinControl
{
public AccessibleControl(UITestControl c) : base(c)
{
TechnologyName = "MSAA";
SearchProperties.Add(UITestControl.PropertyNames.ControlType, "Custom");
}
public virtual string AccessibleName
{
get
{
return (string)GetProperty("AccessibleName");
}
}
}
}
Now the Coded UI Test Builder is showing the AccessibleName and is also generating AccessibleName as a SearchProperty.
UIMap:
public AccessibleControl UIItemCustom
{
get
{
if ((this.mUIItemCustom == null))
{
this.mUIItemCustom = new AccessibleControl(this);
#region Search Criteria
this.mUIItemCustom.SearchProperties["AccessibleName"] = "UniqueName1";
this.mUIItemCustom.SearchProperties[WinControl.PropertyNames.ClassName] = "TEdit";
this.mUIItemCustom.WindowTitles.Add("Title");
#endregion
}
return this.mUIItemCustom;
}
}
*I have changed the Searchproperties here (only for the post, i didnt changed the generated code)
Now when I start the test, I get an exception that says that AccessibleName is not an valid searchproperty. I got this exception before, when i havent implemented the extension yet. But I thougth by implementing the propertyprovider AccessibleName should be a valid searchproperty now.
I tried to debug it, but it seems like by searching the Control it doesnt use the propertyprovider and i have no idea why?
I hope you can help me and if you need more information just ask.
Paul
I got the problem with the valid searchproperty to work.
I overrode the GetValidSearchProperties method from WinControl.
protected override Dictionary<string, bool> GetValidSearchProperties()
{
Dictionary<string, bool> searchProperties = base.GetValidSearchProperties();
if (!searchProperties.ContainsKey("AccessibleName"))
searchProperties.Add("AccessibleName", true);
return searchProperties;
}
I have the following class structure:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
namespace contractsTest
{
class Program
{
static void Main(string[] args)
{
IService s = new Service();
s.sendMessage(MessagesCreator.TestMessage);
}
}
class Service : IService
{
public void DoSomething(Message m)
{
}
}
static class MessageNames
{
public static string TestMessage
{
get
{
Contract.Ensures(!string.IsNullOrWhiteSpace(Contract.Result<string>()));
return "TestMessage";
}
}
}
class Message
{
public Message(string _name)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_name));
Contract.Ensures(this.Name == _name);
this.Name = _name;
}
public string Name { get; private set; }
}
static class MessagesCreator
{
public static Message TestMessage
{
get
{
Contract.Ensures(Contract.Result<Message>() != null);
Contract.Ensures(Contract.Result<Message>().Name == MessageNames.TestMessage);
return new Message(MessageNames.TestMessage);
}
}
}
static class Extensions
{
public static void sendMessage(this IService service, Message m)
{
Contract.Requires<ArgumentNullException>(service != null);
Contract.Requires<ArgumentNullException>(m != null);
Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(m.Name));
service.DoSomething(m);
}
}
[ContractClass(typeof(IServiceContract))]
interface IService
{
void DoSomething(Message m);
}
[ContractClassFor(typeof(IService))]
abstract class IServiceContract : IService
{
public void DoSomething(Message m)
{
Contract.Requires<ArgumentNullException>(m != null);
Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(m.Name));
// Do Something
}
}
}
In Main i get the following Warning CodeContracts: requires unproven: !string.IsNullOrWhiteSpace(m.Name)
Any idea how to fix it?
If I change main to:
static void Main(string[] args)
{
IService s = new Service();
Message messagesCreatorTestMessage = MessagesCreator.TestMessage;
if (string.IsNullOrWhiteSpace(messagesCreatorTestMessage.Name))
throw new InvalidOperationException();
s.sendMessage(messagesCreatorTestMessage);
}
the warning disappears, but there should be other more elegant ways of doing this.
The Ensures in the Message constructor only specifies that the condition will be true when the constructor finishes; it does not indicate that the condition will be true for the life of the Message instance.
To do this, use the Contract.Invariant method:
class Message
{
[ContractInvariantMethod]
private void MessageInvariants()
{
Contract.Invariant(!string.IsNullOrWhiteSpace(Name));
}
public Message(string _name)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_name));
Contract.Ensures(this.Name == _name);
this.Name = _name;
}
public string Name { get; private set; }
}
It's possible that this is the problem:
// In the Message constructor
Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_componentName));
I suspect you mean:
Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_name));
It's not clear to me where _componentName even comes from...