Skip to content
Browse files

Initial hack at creating an Rx version of Geolocator

  • Loading branch information...
1 parent 6bdb4e8 commit 861d5b58b5ae4275f8f1245a3ff17283ed8dd3a6 @paulcbetts paulcbetts committed
View
106 ReactiveUI.Mobile/Geolocation.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
+using System.Reactive.Subjects;
+using System.Reactive.Threading.Tasks;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Xamarin.Geolocation;
+
+namespace ReactiveUI.Mobile_WinRT
+{
+ public interface IReactiveGeolocator
+ {
+ IObservable<Position> Listen(int minUpdateTime, double minUpdateDist, bool includeHeading = false);
+ IObservable<Position> GetPosition(bool includeHeading = false);
+ }
+
+ public static class ReactiveGeolocator
+ {
+ [ThreadStatic] static IReactiveGeolocator _UnitTestImplementation;
+ static IReactiveGeolocator _Implementation;
+
+ internal static IReactiveGeolocator Implementation {
+ get { return _UnitTestImplementation ?? _Implementation; }
+ set {
+ if (RxApp.InUnitTestRunner()) {
+ _UnitTestImplementation = value;
+ _Implementation = _Implementation ?? value;
+ } else {
+ _Implementation = value;
+ }
+ }
+ }
+
+ public static IObservable<Position> Listen(int minUpdateTime, double minUpdateDist, bool includeHeading = false)
+ {
+ if (Implementation != null) {
+ return Implementation.Listen(minUpdateTime, minUpdateDist, includeHeading);
+ }
+
+ var ret = Observable.Create<Position>(subj => {
+ var geo = new Geolocator();
+ var disp = new CompositeDisposable();
+ bool isDead = false;
+
+ if (!geo.IsGeolocationAvailable || !geo.IsGeolocationEnabled) {
+ return Observable.Throw<Position>(new Exception("Geolocation isn't available")).Subscribe(subj);
+ }
+
+ // NB: This isn't very Functional, but I'm lazy.
+ disp.Add(Observable.FromEventPattern<PositionEventArgs>(x => geo.PositionChanged += x, x => geo.PositionChanged -= x).Subscribe(x => {
+ if (isDead) return;
+ subj.OnNext(x.EventArgs.Position);
+ }));
+
+ disp.Add(Observable.FromEventPattern<PositionErrorEventArgs>(x => geo.PositionError += x, x => geo.PositionError -= x).Subscribe(ex => {
+ isDead = true;
+ var toDisp = Interlocked.Exchange(ref disp, null);
+ if (toDisp != null) toDisp.Dispose();
+ subj.OnError(new GeolocationException(ex.EventArgs.Error));
+ }));
+
+ return disp;
+ });
+
+ return ret.Multicast(new Subject<Position>()).RefCount();
+ }
+
+ public static IObservable<Position> GetPosition(bool includeHeading = false)
+ {
+ if (Implementation != null) {
+ return Implementation.GetPosition(includeHeading);
+ }
+
+ var ret = Observable.Create<Position>(subj => {
+ var geo = new Geolocator();
+ var cts = new CancellationTokenSource();
+ var disp = new CompositeDisposable();
+
+ if (!geo.IsGeolocationAvailable || !geo.IsGeolocationEnabled) {
+ return Observable.Throw<Position>(new Exception("Geolocation isn't available")).Subscribe(subj);
+ }
+
+ disp.Add(new CancellationDisposable(cts));
+ disp.Add(geo.GetPositionAsync(cts.Token, includeHeading).ToObservable().Subscribe(subj));
+ return disp;
+ }).Multicast(new AsyncSubject<Position>());
+
+ ret.Connect();
+ return ret;
+ }
+ }
+
+ public class GeolocationException : Exception
+ {
+ public GeolocationException(GeolocationError error)
+ {
+ Info = error;
+ }
+
+ public GeolocationError Info { get; protected set; }
+ }
+}
View
29 ReactiveUI.Mobile/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ReactiveUI.Mobile_WinRT")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ReactiveUI.Mobile_WinRT")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
View
148 ReactiveUI.Mobile/ReactiveUI.Mobile_WinRT.csproj
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ReactiveUI.Mobile_WinRT</RootNamespace>
+ <AssemblyName>ReactiveUI.Mobile_WinRT</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System.Reactive.Core">
+ <HintPath>..\ext\winrt\System.Reactive.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.Interfaces">
+ <HintPath>..\ext\winrt\System.Reactive.Interfaces.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.Linq">
+ <HintPath>..\ext\winrt\System.Reactive.Linq.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.PlatformServices">
+ <HintPath>..\ext\winrt\System.Reactive.PlatformServices.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.Windows.Threading">
+ <HintPath>..\ext\winrt\System.Reactive.Windows.Threading.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.WindowsRuntime">
+ <HintPath>..\ext\winrt\System.Reactive.WindowsRuntime.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.Mobile">
+ <HintPath>..\ext\winrt\Xamarin.Mobile.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\ReactiveUI.Xaml\ReactiveUI.Xaml_WinRT.csproj">
+ <Project>{689ec7c5-2d81-4124-929e-397b330cc358}</Project>
+ <Name>ReactiveUI.Xaml_WinRT</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ReactiveUI\ReactiveUI_WinRT.csproj">
+ <Project>{3db4ef6f-ccbc-4115-9c33-20e52a024534}</Project>
+ <Name>ReactiveUI_WinRT</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '11.0' ">
+ <VisualStudioVersion>11.0</VisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
22 ReactiveUI.sln
@@ -80,6 +80,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactiveUI.Blend_WP8", "Rea
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactiveUI.Blend_Net45", "ReactiveUI.Blend\ReactiveUI.Blend_Net45.csproj", "{7866B5B1-5457-43A2-976A-E784EB10F2DA}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactiveUI.Mobile_WinRT", "ReactiveUI.Mobile\ReactiveUI.Mobile_WinRT.csproj", "{30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}"
+EndProject
Global
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = ReactiveUI.vsmdi
@@ -620,6 +622,26 @@ Global
{7866B5B1-5457-43A2-976A-E784EB10F2DA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{7866B5B1-5457-43A2-976A-E784EB10F2DA}.Release|x64.ActiveCfg = Release|Any CPU
{7866B5B1-5457-43A2-976A-E784EB10F2DA}.Release|x86.ActiveCfg = Release|Any CPU
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|ARM.ActiveCfg = Debug|ARM
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|ARM.Build.0 = Debug|ARM
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|x64.ActiveCfg = Debug|x64
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|x64.Build.0 = Debug|x64
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|x86.ActiveCfg = Debug|x86
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Debug|x86.Build.0 = Debug|x86
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|ARM.ActiveCfg = Release|ARM
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|ARM.Build.0 = Release|ARM
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|Mixed Platforms.Build.0 = Release|x86
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|x64.ActiveCfg = Release|x64
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|x64.Build.0 = Release|x64
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|x86.ActiveCfg = Release|x86
+ {30540F2B-0F4C-40A0-B3B6-FFDDFA09D8FD}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

0 comments on commit 861d5b5

Please sign in to comment.
Something went wrong with that request. Please try again.