From 3263f841e3312077dc296a50f2da5e9fcb81a49d Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Thu, 29 Mar 2018 14:14:27 -0700 Subject: [PATCH] Added Android Sample app + added custom Android device that uses the NMEA stream from the system location provider --- src/NmeaParser.sln | 372 ++++++++++-------- src/NmeaParser/NmeaParser.csproj | 8 +- src/NmeaParser/SystemNmeaDevice.Android.cs | 196 +++++++++ src/SampleApp.Droid/MainActivity.cs | 81 ++++ .../Properties/AndroidManifest.xml | 7 + .../Properties/AssemblyInfo.cs | 30 ++ .../Resources/Resource.Designer.cs | 102 +++++ .../Resources/layout/Main.axml | 21 + .../Resources/values/Strings.xml | 4 + src/SampleApp.Droid/SampleApp.Droid.csproj | 103 +++++ 10 files changed, 751 insertions(+), 173 deletions(-) create mode 100644 src/NmeaParser/SystemNmeaDevice.Android.cs create mode 100644 src/SampleApp.Droid/MainActivity.cs create mode 100644 src/SampleApp.Droid/Properties/AndroidManifest.xml create mode 100644 src/SampleApp.Droid/Properties/AssemblyInfo.cs create mode 100644 src/SampleApp.Droid/Resources/Resource.Designer.cs create mode 100644 src/SampleApp.Droid/Resources/layout/Main.axml create mode 100644 src/SampleApp.Droid/Resources/values/Strings.xml create mode 100644 src/SampleApp.Droid/SampleApp.Droid.csproj diff --git a/src/NmeaParser.sln b/src/NmeaParser.sln index 02a9b2e..bd0b36f 100644 --- a/src/NmeaParser.sln +++ b/src/NmeaParser.sln @@ -1,171 +1,201 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2003 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NmeaParser", "NmeaParser", "{1701F3BA-A09C-4706-A612-24FD9340FC18}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{CF767486-305D-40EE-8845-58EF76C16D85}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.WinDesktop", "SampleApp.WinDesktop\SampleApp.WinDesktop.csproj", "{5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}" - ProjectSection(ProjectDependencies) = postProject - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} = {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Desktop", "Desktop", "{7ABA337E-6748-484E-A0F4-E1715E1C95F1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{28B8E327-C504-4E08-B2CE-09D1CBB8B904}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleApps", "SampleApps", "{A4B9D59A-C8C6-4199-A7F3-F3AF0C748281}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0EBBFC7B-43E8-4478-9951-50C842991A9C}" - ProjectSection(SolutionItems) = preProject - CustomDictionary.xml = CustomDictionary.xml - GlobalSuppressions.cs = GlobalSuppressions.cs - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UWP", "UWP", "{01FEC943-B537-4BCF-945A-6C914B06E448}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.UWP", "SampleApp.UWP\SampleApp.UWP.csproj", "{7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NmeaParser", "NmeaParser\NmeaParser.csproj", "{1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NmeaParser.Tests.UWP", "UnitTests\NmeaParser.Tests.UWP\NmeaParser.Tests.UWP.csproj", "{92CAD93B-6C3B-45A0-A723-BE046DE50FEC}" -EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "NmeaParser.Tests", "UnitTests\NmeaParser.Tests\NmeaParser.Tests.shproj", "{979AE182-EB59-4181-9D45-3FD6E4817F11}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NmeaParser.Tests.NET45", "UnitTests\NmeaParser.Tests.NET45\NmeaParser.Tests.NET45.csproj", "{170EE734-37F0-425F-822B-B865348ECEC6}" - ProjectSection(ProjectDependencies) = postProject - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} = {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} - EndProjectSection -EndProject -Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{170ee734-37f0-425f-822b-b865348ecec6}*SharedItemsImports = 4 - UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{92cad93b-6c3b-45a0-a723-be046de50fec}*SharedItemsImports = 4 - UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{979ae182-eb59-4181-9d45-3fd6e4817f11}*SharedItemsImports = 13 - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|ARM.ActiveCfg = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|ARM.Build.0 = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x64.ActiveCfg = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x64.Build.0 = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x86.ActiveCfg = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x86.Build.0 = Debug|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|Any CPU.Build.0 = Release|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|ARM.ActiveCfg = Release|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|ARM.Build.0 = Release|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x64.ActiveCfg = Release|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x64.Build.0 = Release|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x86.ActiveCfg = Release|Any CPU - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x86.Build.0 = Release|Any CPU - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|Any CPU.ActiveCfg = Debug|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|Any CPU.Build.0 = Debug|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|Any CPU.Deploy.0 = Debug|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|ARM.ActiveCfg = Debug|ARM - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|ARM.Build.0 = Debug|ARM - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|ARM.Deploy.0 = Debug|ARM - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x64.ActiveCfg = Debug|x64 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x64.Build.0 = Debug|x64 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x64.Deploy.0 = Debug|x64 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x86.ActiveCfg = Debug|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x86.Build.0 = Debug|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x86.Deploy.0 = Debug|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|Any CPU.ActiveCfg = Release|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|Any CPU.Build.0 = Release|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|Any CPU.Deploy.0 = Release|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|ARM.ActiveCfg = Release|ARM - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|ARM.Build.0 = Release|ARM - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|ARM.Deploy.0 = Release|ARM - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x64.ActiveCfg = Release|x64 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x64.Build.0 = Release|x64 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x64.Deploy.0 = Release|x64 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x86.ActiveCfg = Release|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x86.Build.0 = Release|x86 - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x86.Deploy.0 = Release|x86 - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|ARM.ActiveCfg = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|ARM.Build.0 = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x64.ActiveCfg = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x64.Build.0 = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x86.ActiveCfg = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x86.Build.0 = Debug|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|Any CPU.Build.0 = Release|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|ARM.ActiveCfg = Release|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|ARM.Build.0 = Release|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x64.ActiveCfg = Release|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x64.Build.0 = Release|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x86.ActiveCfg = Release|Any CPU - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x86.Build.0 = Release|Any CPU - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|Any CPU.ActiveCfg = Debug|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|Any CPU.Build.0 = Debug|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|Any CPU.Deploy.0 = Debug|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|ARM.ActiveCfg = Debug|ARM - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|ARM.Build.0 = Debug|ARM - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|ARM.Deploy.0 = Debug|ARM - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x64.ActiveCfg = Debug|x64 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x64.Build.0 = Debug|x64 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x64.Deploy.0 = Debug|x64 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x86.ActiveCfg = Debug|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x86.Build.0 = Debug|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x86.Deploy.0 = Debug|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|Any CPU.ActiveCfg = Release|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|ARM.ActiveCfg = Release|ARM - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|ARM.Build.0 = Release|ARM - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|ARM.Deploy.0 = Release|ARM - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x64.ActiveCfg = Release|x64 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x64.Build.0 = Release|x64 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x64.Deploy.0 = Release|x64 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.ActiveCfg = Release|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.Build.0 = Release|x86 - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.Deploy.0 = Release|x86 - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|ARM.ActiveCfg = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|ARM.Build.0 = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x64.ActiveCfg = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x64.Build.0 = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x86.ActiveCfg = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x86.Build.0 = Debug|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|Any CPU.Build.0 = Release|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|ARM.ActiveCfg = Release|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|ARM.Build.0 = Release|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x64.ActiveCfg = Release|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x64.Build.0 = Release|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x86.ActiveCfg = Release|Any CPU - {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F} = {7ABA337E-6748-484E-A0F4-E1715E1C95F1} - {7ABA337E-6748-484E-A0F4-E1715E1C95F1} = {A4B9D59A-C8C6-4199-A7F3-F3AF0C748281} - {28B8E327-C504-4E08-B2CE-09D1CBB8B904} = {CF767486-305D-40EE-8845-58EF76C16D85} - {01FEC943-B537-4BCF-945A-6C914B06E448} = {A4B9D59A-C8C6-4199-A7F3-F3AF0C748281} - {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0} = {01FEC943-B537-4BCF-945A-6C914B06E448} - {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} = {1701F3BA-A09C-4706-A612-24FD9340FC18} - {92CAD93B-6C3B-45A0-A723-BE046DE50FEC} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904} - {979AE182-EB59-4181-9D45-3FD6E4817F11} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904} - {170EE734-37F0-425F-822B-B865348ECEC6} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {03788B53-C0BF-485B-AA19-A9EAB0E9AF7B} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2003 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NmeaParser", "NmeaParser", "{1701F3BA-A09C-4706-A612-24FD9340FC18}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{CF767486-305D-40EE-8845-58EF76C16D85}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.WinDesktop", "SampleApp.WinDesktop\SampleApp.WinDesktop.csproj", "{5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}" + ProjectSection(ProjectDependencies) = postProject + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} = {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Desktop", "Desktop", "{7ABA337E-6748-484E-A0F4-E1715E1C95F1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{28B8E327-C504-4E08-B2CE-09D1CBB8B904}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleApps", "SampleApps", "{A4B9D59A-C8C6-4199-A7F3-F3AF0C748281}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0EBBFC7B-43E8-4478-9951-50C842991A9C}" + ProjectSection(SolutionItems) = preProject + CustomDictionary.xml = CustomDictionary.xml + GlobalSuppressions.cs = GlobalSuppressions.cs + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UWP", "UWP", "{01FEC943-B537-4BCF-945A-6C914B06E448}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.UWP", "SampleApp.UWP\SampleApp.UWP.csproj", "{7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NmeaParser", "NmeaParser\NmeaParser.csproj", "{1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NmeaParser.Tests.UWP", "UnitTests\NmeaParser.Tests.UWP\NmeaParser.Tests.UWP.csproj", "{92CAD93B-6C3B-45A0-A723-BE046DE50FEC}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "NmeaParser.Tests", "UnitTests\NmeaParser.Tests\NmeaParser.Tests.shproj", "{979AE182-EB59-4181-9D45-3FD6E4817F11}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NmeaParser.Tests.NET45", "UnitTests\NmeaParser.Tests.NET45\NmeaParser.Tests.NET45.csproj", "{170EE734-37F0-425F-822B-B865348ECEC6}" + ProjectSection(ProjectDependencies) = postProject + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} = {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{456E7573-3324-43CB-8BA0-8D9C300EEB50}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.Droid", "SampleApp.Droid\SampleApp.Droid.csproj", "{48540D33-4349-42D2-9D49-144A7049565A}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{170ee734-37f0-425f-822b-b865348ecec6}*SharedItemsImports = 4 + UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{92cad93b-6c3b-45a0-a723-be046de50fec}*SharedItemsImports = 4 + UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{979ae182-eb59-4181-9d45-3fd6e4817f11}*SharedItemsImports = 13 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|ARM.ActiveCfg = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|ARM.Build.0 = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x64.ActiveCfg = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x64.Build.0 = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x86.ActiveCfg = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Debug|x86.Build.0 = Debug|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|Any CPU.Build.0 = Release|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|ARM.ActiveCfg = Release|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|ARM.Build.0 = Release|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x64.ActiveCfg = Release|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x64.Build.0 = Release|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x86.ActiveCfg = Release|Any CPU + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F}.Release|x86.Build.0 = Release|Any CPU + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|Any CPU.ActiveCfg = Debug|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|Any CPU.Build.0 = Debug|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|Any CPU.Deploy.0 = Debug|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|ARM.ActiveCfg = Debug|ARM + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|ARM.Build.0 = Debug|ARM + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|ARM.Deploy.0 = Debug|ARM + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x64.ActiveCfg = Debug|x64 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x64.Build.0 = Debug|x64 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x64.Deploy.0 = Debug|x64 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x86.ActiveCfg = Debug|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x86.Build.0 = Debug|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Debug|x86.Deploy.0 = Debug|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|Any CPU.ActiveCfg = Release|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|Any CPU.Build.0 = Release|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|Any CPU.Deploy.0 = Release|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|ARM.ActiveCfg = Release|ARM + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|ARM.Build.0 = Release|ARM + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|ARM.Deploy.0 = Release|ARM + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x64.ActiveCfg = Release|x64 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x64.Build.0 = Release|x64 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x64.Deploy.0 = Release|x64 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x86.ActiveCfg = Release|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x86.Build.0 = Release|x86 + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0}.Release|x86.Deploy.0 = Release|x86 + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|ARM.Build.0 = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x64.ActiveCfg = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x64.Build.0 = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x86.ActiveCfg = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Debug|x86.Build.0 = Debug|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|Any CPU.Build.0 = Release|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|ARM.ActiveCfg = Release|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|ARM.Build.0 = Release|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x64.ActiveCfg = Release|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x64.Build.0 = Release|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x86.ActiveCfg = Release|Any CPU + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C}.Release|x86.Build.0 = Release|Any CPU + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|Any CPU.ActiveCfg = Debug|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|Any CPU.Build.0 = Debug|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|Any CPU.Deploy.0 = Debug|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|ARM.ActiveCfg = Debug|ARM + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|ARM.Build.0 = Debug|ARM + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|ARM.Deploy.0 = Debug|ARM + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x64.ActiveCfg = Debug|x64 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x64.Build.0 = Debug|x64 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x64.Deploy.0 = Debug|x64 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x86.ActiveCfg = Debug|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x86.Build.0 = Debug|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Debug|x86.Deploy.0 = Debug|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|Any CPU.ActiveCfg = Release|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|ARM.ActiveCfg = Release|ARM + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|ARM.Build.0 = Release|ARM + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|ARM.Deploy.0 = Release|ARM + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x64.ActiveCfg = Release|x64 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x64.Build.0 = Release|x64 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x64.Deploy.0 = Release|x64 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.ActiveCfg = Release|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.Build.0 = Release|x86 + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.Deploy.0 = Release|x86 + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|ARM.Build.0 = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x64.ActiveCfg = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x64.Build.0 = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x86.ActiveCfg = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Debug|x86.Build.0 = Debug|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|Any CPU.Build.0 = Release|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|ARM.ActiveCfg = Release|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|ARM.Build.0 = Release|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x64.ActiveCfg = Release|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x64.Build.0 = Release|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x86.ActiveCfg = Release|Any CPU + {170EE734-37F0-425F-822B-B865348ECEC6}.Release|x86.Build.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|ARM.Build.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|ARM.Deploy.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|x64.ActiveCfg = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|x64.Build.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|x64.Deploy.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|x86.ActiveCfg = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|x86.Build.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Debug|x86.Deploy.0 = Debug|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|Any CPU.Build.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|Any CPU.Deploy.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|ARM.ActiveCfg = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|ARM.Build.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|ARM.Deploy.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|x64.ActiveCfg = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|x64.Build.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|x64.Deploy.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|x86.ActiveCfg = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|x86.Build.0 = Release|Any CPU + {48540D33-4349-42D2-9D49-144A7049565A}.Release|x86.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5DB6C7C7-A19C-4BE3-AFE6-26E3061DA01F} = {7ABA337E-6748-484E-A0F4-E1715E1C95F1} + {7ABA337E-6748-484E-A0F4-E1715E1C95F1} = {A4B9D59A-C8C6-4199-A7F3-F3AF0C748281} + {28B8E327-C504-4E08-B2CE-09D1CBB8B904} = {CF767486-305D-40EE-8845-58EF76C16D85} + {01FEC943-B537-4BCF-945A-6C914B06E448} = {A4B9D59A-C8C6-4199-A7F3-F3AF0C748281} + {7B252F1E-2E9D-4362-9C14-3376AAB8B5A0} = {01FEC943-B537-4BCF-945A-6C914B06E448} + {1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} = {1701F3BA-A09C-4706-A612-24FD9340FC18} + {92CAD93B-6C3B-45A0-A723-BE046DE50FEC} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904} + {979AE182-EB59-4181-9D45-3FD6E4817F11} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904} + {170EE734-37F0-425F-822B-B865348ECEC6} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904} + {456E7573-3324-43CB-8BA0-8D9C300EEB50} = {A4B9D59A-C8C6-4199-A7F3-F3AF0C748281} + {48540D33-4349-42D2-9D49-144A7049565A} = {456E7573-3324-43CB-8BA0-8D9C300EEB50} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {03788B53-C0BF-485B-AA19-A9EAB0E9AF7B} + EndGlobalSection +EndGlobal diff --git a/src/NmeaParser/NmeaParser.csproj b/src/NmeaParser/NmeaParser.csproj index 5099205..e0f0a7e 100644 --- a/src/NmeaParser/NmeaParser.csproj +++ b/src/NmeaParser/NmeaParser.csproj @@ -1,7 +1,7 @@ - netstandard1.4;net451;monoandroid50;xamarinios10;uap10.0 + netstandard1.4;net451;monoandroid50;monoandroid70;xamarinios10;uap10.0 true true Debug;Release @@ -35,7 +35,11 @@ - $(DefineConstants);XAMARIN + $(DefineConstants);XAMARIN;API_LEVEL_21 + NMEA Parser - Android + + + $(DefineConstants);XAMARIN;API_LEVEL_24 NMEA Parser - Android diff --git a/src/NmeaParser/SystemNmeaDevice.Android.cs b/src/NmeaParser/SystemNmeaDevice.Android.cs new file mode 100644 index 0000000..3a5ee34 --- /dev/null +++ b/src/NmeaParser/SystemNmeaDevice.Android.cs @@ -0,0 +1,196 @@ +#if __ANDROID__ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Android.Content; +using Android.Locations; +using Android.App; +using Android.OS; +using System.Globalization; + +namespace NmeaParser +{ + /// + /// This class provides access to the Android system location service's raw NMEA stream + /// The ACCESS_FINE_LOCATION permission is required. + /// + public class SystemNmeaDevice : NmeaDevice + { + private StringStream stream; + private Listener listener; + private LocationManager manager; + + /// + /// Initializes a new instance of the class. + /// + public SystemNmeaDevice() + { + manager = Application.Context.GetSystemService(Context.LocationService) as LocationManager; + } + + /// + [Android.Runtime.RequiresPermission("android.permission.ACCESS_FINE_LOCATION")] + protected override Task OpenStreamAsync() + { + if(!manager.IsProviderEnabled(LocationManager.GpsProvider)) + { + throw new InvalidOperationException("The GPS Location Provider is not enabled"); + } + + stream = new StringStream(); + listener = new Listener(); + listener.NmeaMessage += (s, e) => stream?.Append(e); + bool success = manager.AddNmeaListener(listener); + manager.RequestLocationUpdates(LocationManager.GpsProvider, 100, .1f, listener ); + + return Task.FromResult(stream); + } + + /// + protected override Task CloseStreamAsync(Stream stream) + { + manager.RemoveNmeaListener(listener); + listener.Dispose(); + listener = null; + stream.Dispose(); + return Task.FromResult(null); + } + + private class Listener : Java.Lang.Object, +#if API_LEVEL_24 + IOnNmeaMessageListener, +#else + GpsStatus.INmeaListener, +#endif + ILocationListener + { + private bool _isNmeaSupported = false; + +#if API_LEVEL_24 + void IOnNmeaMessageListener.OnNmeaMessage(string message, long timestamp) +#else + void GpsStatus.INmeaListener.OnNmeaReceived(long timestamp, string message) +#endif + { + _isNmeaSupported = true; + NmeaMessage?.Invoke(this, message); + } + + public event EventHandler NmeaMessage; + + void ILocationListener.OnLocationChanged(Location location) + { + if (_isNmeaSupported) return; + if (location.Provider != LocationManager.GpsProvider) return; + // Not all Android devices support reporting NMEA, so we'll fallback to just generating + // simple RMC and GGA message so the provider continues to work across multiple devices + // $GPRMC: + List values = new List(12); + values.Add("$GPRMC"); + DateTimeOffset d = DateTimeOffset.FromUnixTimeMilliseconds(location.Time); + values.Add(d.ToString("hhmmss")); + values.Add("A"); + var lat = Math.Floor(Math.Abs(location.Latitude)); + var latfrac = (Math.Abs(location.Latitude) - lat) * 60; + values.Add($"{lat.ToString("00")}{latfrac.ToString(CultureInfo.InvariantCulture)}"); + values.Add(location.Latitude < 0 ? "S" : "N"); + var lon = Math.Floor(Math.Abs(location.Longitude)); + var lonfrac = (Math.Abs(location.Longitude) - lon) * 60; + values.Add($"{lon.ToString("000")}{lonfrac.ToString(CultureInfo.InvariantCulture)}"); + values.Add(location.Longitude < 0 ? "W" : "E"); + values.Add(location.HasSpeed ? location.Speed.ToString(CultureInfo.InvariantCulture) : ""); + values.Add(location.HasBearing ? location.Bearing.ToString(CultureInfo.InvariantCulture) : ""); + values.Add(d.ToString("ddMMyy")); + values.Add(""); //Variation + values.Add(""); //East/West + NmeaMessage?.Invoke(this, string.Join(",", values) + "\n"); + // $GPGGA: + int satellites = 0; + if(location.Extras != null && location.Extras.ContainsKey("satellites")) + { + satellites = Convert.ToInt32(location.Extras.Get("satellites")); + } + values = new List(13); + values.Add("$GPGGA"); + values.Add(d.ToString("hhmmss")); + values.Add($"{lat.ToString("00")}{latfrac.ToString(CultureInfo.InvariantCulture)}"); + values.Add(location.Latitude < 0 ? "S" : "N"); + values.Add($"{lon.ToString("000")}{lonfrac.ToString(CultureInfo.InvariantCulture)}"); + values.Add(location.Longitude < 0 ? "W" : "E"); + values.Add("1"); //Fix Quality: + values.Add(satellites.ToString()); //Number of Satellites + values.Add(""); //HDOP + values.Add(location.HasAltitude ? location.Altitude.ToString(CultureInfo.InvariantCulture) : ""); + values.Add("M"); //Altitude units + values.Add(""); //Height of geoid above WGS84 ellipsoid + values.Add(""); //Geoid height units + values.Add(""); //Time since last DGPS update + values.Add(""); //DGPS reference station id + NmeaMessage?.Invoke(this, string.Join(",", values) + "\n"); + } + + void ILocationListener.OnProviderDisabled(string provider) { } + + void ILocationListener.OnProviderEnabled(string provider) { } + + void ILocationListener.OnStatusChanged(string provider, Availability status, Bundle extras) { } + } + + /// + /// Class for converting streaming strings into a stream + /// + private class StringStream : Stream + { + object lockObject = new object(); + Queue stream = new Queue(); + long position = 0; + public StringStream() { } + + public override bool CanRead => true; + + public override bool CanSeek => false; + + public override bool CanWrite => false; + + public override long Length => throw new NotImplementedException(); + + public override long Position { get => position; set => throw new NotSupportedException(); } + + public void Append(string data) + { + lock (lockObject) + { + foreach (byte b in Encoding.UTF8.GetBytes(data)) + { + stream.Enqueue(b); + } + } + } + + public override void Flush() { } + + public override int Read(byte[] buffer, int offset, int count) + { + lock (lockObject) + { + for (int i = 0; i < count; i++) + { + if (stream.Count == 0) + return i; + buffer[offset + i] = stream.Dequeue(); + } + } + return count; + } + + public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); + + public override void SetLength(long value) => throw new NotSupportedException(); + + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); + } + } +} +#endif \ No newline at end of file diff --git a/src/SampleApp.Droid/MainActivity.cs b/src/SampleApp.Droid/MainActivity.cs new file mode 100644 index 0000000..7f77db2 --- /dev/null +++ b/src/SampleApp.Droid/MainActivity.cs @@ -0,0 +1,81 @@ +using Android.App; +using Android.Widget; +using Android.OS; +using Android; +using Android.Support.V4.App; +using Android.Support.V4.Content; +using Android.Content.PM; +using System; +using System.Collections.Generic; +using System.Linq; +using NmeaParser.Nmea.Gps; +using NmeaParser.Nmea; + +namespace SampleApp.Droid +{ + [Activity(Label = "SampleApp.Droid", MainLauncher = true)] + public class MainActivity : Activity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + + // Set our view from the "main" layout resource + SetContentView(Resource.Layout.Main); + + Start(); + } + + private NmeaParser.SystemNmeaDevice listener; + private TextView status; + private bool launched; + + private async void Start() + { + if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) != Permission.Granted) + { + ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.AccessFineLocation }, 1000); + return; + } + if (launched) + return; + + launched = true; + + listener = new NmeaParser.SystemNmeaDevice(); + listener.MessageReceived += Listener_MessageReceived; + status = FindViewById(Resource.Id.output); + status.Text = "Opening device..."; + await listener.OpenAsync(); + } + + protected override void OnResume() + { + base.OnResume(); + // if it was resumed by the GPS permissions dialog + Start(); + } + + Queue messages = new Queue(100); + private void Listener_MessageReceived(object sender, NmeaParser.NmeaMessageReceivedEventArgs e) + { + var message = e.Message; + RunOnUiThread(() => + { + if (messages.Count == 100) messages.Dequeue(); + messages.Enqueue(message); + status.Text = string.Join("\n", messages.Reverse().Select(n=>n.ToString())); + if(message is Rmc rmc) + { + FindViewById(Resource.Id.latitude).Text = "Latitude = " + rmc.Latitude.ToString(); + FindViewById(Resource.Id.longitude).Text = "Longitude = " + rmc.Longitude.ToString(); + } + else if (message is Gga gga) + { + FindViewById(Resource.Id.altitude).Text = "Altitude = " + gga.Altitude.ToString() + " " + gga.AltitudeUnits.ToString(); + } + }); + } + } +} + diff --git a/src/SampleApp.Droid/Properties/AndroidManifest.xml b/src/SampleApp.Droid/Properties/AndroidManifest.xml new file mode 100644 index 0000000..2f339c4 --- /dev/null +++ b/src/SampleApp.Droid/Properties/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/SampleApp.Droid/Properties/AssemblyInfo.cs b/src/SampleApp.Droid/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4780de0 --- /dev/null +++ b/src/SampleApp.Droid/Properties/AssemblyInfo.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// 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("SampleApp.Droid")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SampleApp.Droid")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// 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")] diff --git a/src/SampleApp.Droid/Resources/Resource.Designer.cs b/src/SampleApp.Droid/Resources/Resource.Designer.cs new file mode 100644 index 0000000..f0c3edc --- /dev/null +++ b/src/SampleApp.Droid/Resources/Resource.Designer.cs @@ -0,0 +1,102 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("SampleApp.Droid.Resource", IsApplication=true)] + +namespace SampleApp.Droid +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f040002 + public const int altitude = 2130968578; + + // aapt resource value: 0x7f040001 + public const int latitude = 2130968577; + + // aapt resource value: 0x7f040000 + public const int longitude = 2130968576; + + // aapt resource value: 0x7f040003 + public const int output = 2130968579; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f020000 + public const int Main = 2130837504; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f030000 + public const int app_name = 2130903040; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/src/SampleApp.Droid/Resources/layout/Main.axml b/src/SampleApp.Droid/Resources/layout/Main.axml new file mode 100644 index 0000000..e24357b --- /dev/null +++ b/src/SampleApp.Droid/Resources/layout/Main.axml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/src/SampleApp.Droid/Resources/values/Strings.xml b/src/SampleApp.Droid/Resources/values/Strings.xml new file mode 100644 index 0000000..5867cb0 --- /dev/null +++ b/src/SampleApp.Droid/Resources/values/Strings.xml @@ -0,0 +1,4 @@ + + + NMEA Parser SampleApp + \ No newline at end of file diff --git a/src/SampleApp.Droid/SampleApp.Droid.csproj b/src/SampleApp.Droid/SampleApp.Droid.csproj new file mode 100644 index 0000000..a2baf9d --- /dev/null +++ b/src/SampleApp.Droid/SampleApp.Droid.csproj @@ -0,0 +1,103 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {48540D33-4349-42D2-9D49-144A7049565A} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + SampleApp.Droid + SampleApp.Droid + 512 + True + Resources\Resource.Designer.cs + Resource + Off + True + v8.1 + Properties\AndroidManifest.xml + Resources + Assets + + + + + PackageReference + + + True + Full + False + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + False + + + True + PdbOnly + True + bin\Release\ + TRACE + prompt + 4 + true + False + SdkOnly + True + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + 27.0.2 + + + + + {1adc3666-1ddb-48c4-9811-1e58b6d09a7c} + NmeaParser + + + + + \ No newline at end of file