diff --git a/GooglePlayServices.TypeForwarders.sln b/GooglePlayServices.TypeForwarders.sln
new file mode 100644
index 000000000..f93a991f6
--- /dev/null
+++ b/GooglePlayServices.TypeForwarders.sln
@@ -0,0 +1,59 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PlayServices", "PlayServices", "{AFB1EDA0-E0D2-4E95-BAEC-9781B046413E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Basement", "basement\source\Basement.csproj", "{6A38FACF-F0C5-4A49-8A8A-7CE6634207CE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Base", "base\source\Base.csproj", "{3F6BAE25-ADEB-468C-8384-AD655623C341}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tasks", "tasks\source\Tasks.csproj", "{53F87D88-8871-41A2-9F81-B79AB02FEC24}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Firebase", "Firebase", "{1EC5651F-83A6-4862-AED2-6BE5103652D0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Firebase-Common", "firebase-common\source\Firebase-Common.csproj", "{865652D3-8D1A-4779-92FC-4C54719286B7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Firebase-AppIndexing", "firebase-appindexing\source\Firebase-AppIndexing.csproj", "{8D01CC30-64F5-4AD3-B9C8-0970B0F1D562}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppIndexing", "appindexing\source\AppIndexing.csproj", "{1C70BA5A-5819-4823-8BEA-0FFEEA39B1E4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3F6BAE25-ADEB-468C-8384-AD655623C341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F6BAE25-ADEB-468C-8384-AD655623C341}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F6BAE25-ADEB-468C-8384-AD655623C341}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F6BAE25-ADEB-468C-8384-AD655623C341}.Release|Any CPU.Build.0 = Release|Any CPU
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6A38FACF-F0C5-4A49-8A8A-7CE6634207CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6A38FACF-F0C5-4A49-8A8A-7CE6634207CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6A38FACF-F0C5-4A49-8A8A-7CE6634207CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6A38FACF-F0C5-4A49-8A8A-7CE6634207CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {865652D3-8D1A-4779-92FC-4C54719286B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {865652D3-8D1A-4779-92FC-4C54719286B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {865652D3-8D1A-4779-92FC-4C54719286B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {865652D3-8D1A-4779-92FC-4C54719286B7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8D01CC30-64F5-4AD3-B9C8-0970B0F1D562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8D01CC30-64F5-4AD3-B9C8-0970B0F1D562}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8D01CC30-64F5-4AD3-B9C8-0970B0F1D562}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8D01CC30-64F5-4AD3-B9C8-0970B0F1D562}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1C70BA5A-5819-4823-8BEA-0FFEEA39B1E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1C70BA5A-5819-4823-8BEA-0FFEEA39B1E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1C70BA5A-5819-4823-8BEA-0FFEEA39B1E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1C70BA5A-5819-4823-8BEA-0FFEEA39B1E4}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {6A38FACF-F0C5-4A49-8A8A-7CE6634207CE} = {AFB1EDA0-E0D2-4E95-BAEC-9781B046413E}
+ {3F6BAE25-ADEB-468C-8384-AD655623C341} = {AFB1EDA0-E0D2-4E95-BAEC-9781B046413E}
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24} = {AFB1EDA0-E0D2-4E95-BAEC-9781B046413E}
+ {865652D3-8D1A-4779-92FC-4C54719286B7} = {1EC5651F-83A6-4862-AED2-6BE5103652D0}
+ {8D01CC30-64F5-4AD3-B9C8-0970B0F1D562} = {1EC5651F-83A6-4862-AED2-6BE5103652D0}
+ {1C70BA5A-5819-4823-8BEA-0FFEEA39B1E4} = {AFB1EDA0-E0D2-4E95-BAEC-9781B046413E}
+ EndGlobalSection
+EndGlobal
diff --git a/appindexing/nuget/Xamarin.GooglePlayServices.AppIndexing.template.nuspec b/appindexing/nuget/Xamarin.GooglePlayServices.AppIndexing.template.nuspec
new file mode 100644
index 000000000..128e53a0d
--- /dev/null
+++ b/appindexing/nuget/Xamarin.GooglePlayServices.AppIndexing.template.nuspec
@@ -0,0 +1,29 @@
+
+
+
+ Xamarin.GooglePlayServices.AppIndexing
+ Xamarin Google Play Services - AppIndexing
+ $version$
+ Xamarin Inc.
+ Xamarin Inc.
+ true
+ Xamarin.Android Bindings for Google Play Services - AppIndexing $aar-version$
+
+ Xamarin.Android Bindings for Google Play Services - AppIndexing $aar-version$
+
+ NOTE: This is package only contains type forwarders to the types which now exist in Xamarin.Firebase.AppIndexing and is only available for backwards compatibility purposes.
+
+ Copyright © Microsoft Corporation
+ http://components.xamarin.com/view/googleplayservices-appindexing/
+ http://components.xamarin.com/license/googleplayservices-appindexing/
+ https://raw.githubusercontent.com/xamarin/GooglePlayServicesComponents/master/icons/play-services-appindexing_128x128.png
+
+
+
+
+
+
+
+
+
+
diff --git a/appindexing/source/AppIndexing.csproj b/appindexing/source/AppIndexing.csproj
new file mode 100644
index 000000000..880bcce71
--- /dev/null
+++ b/appindexing/source/AppIndexing.csproj
@@ -0,0 +1,90 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {1C70BA5A-5819-4823-8BEA-0FFEEA39B1E4}
+ {10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Xamarin.GooglePlayServices.AppIndexing
+ Resources
+ Assets
+ Xamarin.GooglePlayServices.AppIndexing
+ v7.0
+
+ class-parse
+ 8.0.30703
+ 2.0
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ None
+ false
+
+
+ full
+ true
+ bin\Release
+ prompt
+ 4
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+ Xamarin.Firebase.AppIndexing.dll.generated.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {3F6BAE25-ADEB-468C-8384-AD655623C341}
+ Base
+
+
+ {6A38FACF-F0C5-4A49-8A8A-7CE6634207CE}
+ Basement
+
+
+ {8D01CC30-64F5-4AD3-B9C8-0970B0F1D562}
+ Firebase-AppIndexing
+
+
+ {865652D3-8D1A-4779-92FC-4C54719286B7}
+ Firebase-Common
+
+
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}
+ Tasks
+
+
+
+
+
+
diff --git a/appindexing/source/Properties/AssemblyInfo.cs b/appindexing/source/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..80aab1eee
--- /dev/null
+++ b/appindexing/source/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Android.App;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("Xamarin.GooglePlayServices.AppIndexing")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany ("Microsoft Corporation")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright ("Copyright © Microsoft Corporation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.0")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
diff --git a/appindexing/source/Transforms/EnumFields.xml b/appindexing/source/Transforms/EnumFields.xml
new file mode 100644
index 000000000..75838fe72
--- /dev/null
+++ b/appindexing/source/Transforms/EnumFields.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/appindexing/source/Transforms/EnumMethods.xml b/appindexing/source/Transforms/EnumMethods.xml
new file mode 100644
index 000000000..733d08e22
--- /dev/null
+++ b/appindexing/source/Transforms/EnumMethods.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/appindexing/source/Transforms/Metadata.xml b/appindexing/source/Transforms/Metadata.xml
new file mode 100644
index 000000000..3149c78d7
--- /dev/null
+++ b/appindexing/source/Transforms/Metadata.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/appindexing/source/packages.config b/appindexing/source/packages.config
new file mode 100644
index 000000000..38b52b817
--- /dev/null
+++ b/appindexing/source/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/awareness/nuget/Xamarin.GooglePlayServices.Awareness.template.nuspec b/awareness/nuget/Xamarin.GooglePlayServices.Awareness.template.nuspec
index 9e4f35034..5fb119dfa 100644
--- a/awareness/nuget/Xamarin.GooglePlayServices.Awareness.template.nuspec
+++ b/awareness/nuget/Xamarin.GooglePlayServices.Awareness.template.nuspec
@@ -21,6 +21,7 @@
+
diff --git a/awareness/source/Awareness.csproj b/awareness/source/Awareness.csproj
index c73c4cf7b..abc552da2 100644
--- a/awareness/source/Awareness.csproj
+++ b/awareness/source/Awareness.csproj
@@ -98,6 +98,10 @@
{D42D621B-0370-44F6-A58E-0749629F9F4D}
Places
+
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}
+ Tasks
+
diff --git a/base/source/Transforms/Metadata.xml b/base/source/Transforms/Metadata.xml
index eb2438a2f..7212487d6 100644
--- a/base/source/Transforms/Metadata.xml
+++ b/base/source/Transforms/Metadata.xml
@@ -18,6 +18,7 @@
+
diff --git a/basement/buildtasks.tests/Basement.BuildTasks.Tests.csproj b/basement/buildtasks.tests/Basement.BuildTasks.Tests.csproj
index 09cec4014..833013b37 100644
--- a/basement/buildtasks.tests/Basement.BuildTasks.Tests.csproj
+++ b/basement/buildtasks.tests/Basement.BuildTasks.Tests.csproj
@@ -31,14 +31,18 @@
- ..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll
+ ..\..\packages\NUnit.3.0.1\lib\net45\nunit.framework.dll
+
+
+
-
-
-
+
+
+
+
@@ -46,5 +50,11 @@
Basement-BuildTasks
+
+
+
+
+
+
\ No newline at end of file
diff --git a/basement/buildtasks.tests/BuildTaskTests.cs b/basement/buildtasks.tests/BuildTaskTests.cs
new file mode 100644
index 000000000..65395ed14
--- /dev/null
+++ b/basement/buildtasks.tests/BuildTaskTests.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using Xamarin.ContentPipeline.Tests;
+
+namespace buildtasks.tests
+{
+ class BuildTaskTests : TestsBase
+ {
+ public void AddCoreTargets(ProjectRootElement el)
+ {
+ //var props = Path.Combine(
+ // Path.GetDirectoryName(GetType().Assembly.Location),
+ // "..", "..", "..", "buildtasks", "bin", "Debug", "Xamarin.GooglePlayServices.Basement.props"
+ //);
+ //el.AddImport(props);
+ var targets = Path.Combine(
+ Path.GetDirectoryName(GetType().Assembly.Location),
+ "..", "..", "..", "buildtasks", "bin", "Debug", "Xamarin.GooglePlayServices.Basement.targets"
+ );
+ el.AddImport(targets);
+
+ }
+
+ [Test]
+ public void Test_Skip_Due_To_Newer_Outputs_Than_Inputs()
+ {
+ var googleServicesJsonPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "google-services.json");
+
+ var monoAndroidResDirIntermediate = Path.Combine(TempDir, "Debug");
+
+ Directory.CreateDirectory(monoAndroidResDirIntermediate);
+
+ File.WriteAllText(Path.Combine(monoAndroidResDirIntermediate, "ProcessGoogleServicesJson.stamp"), "STAMPS");
+
+
+ var engine = new ProjectCollection();
+ var prel = ProjectRootElement.Create(Path.Combine(TempDir, "project.csproj"), engine);
+
+ Console.WriteLine("TempDir: {0}", TempDir);
+
+ prel.AddProperty("AndroidApplication", "True");
+ prel.AddProperty("IntermediateOutputPath", monoAndroidResDirIntermediate);
+ prel.AddProperty("MonoAndroidResDirIntermediate", monoAndroidResDirIntermediate);
+ prel.AddProperty("_AndroidPackage", "com.xamarin.sample");
+
+ prel.AddItem("GoogleServicesJson", googleServicesJsonPath);
+
+ AddCoreTargets(prel);
+
+ var project = new ProjectInstance(prel);
+ var log = new MSBuildTestLogger();
+
+ var success = BuildProject(engine, project, "ProcessGoogleServicesJson", log);
+
+ Assert.IsTrue(success);
+ Assert.IsTrue(log.Events.Any(e => e.Message.Contains("ProcessGoogleServicesJson") && e.Message.Contains("skipped")));
+ }
+
+ [Test]
+ public void Test_Inputs_Newer_Than_Outputs()
+ {
+ var googleServicesJsonPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "google-services.json");
+
+ var monoAndroidResDirIntermediate = Path.Combine(TempDir, "Debug");
+
+ Directory.CreateDirectory(monoAndroidResDirIntermediate);
+
+ var engine = new ProjectCollection();
+ var prel = ProjectRootElement.Create(Path.Combine(TempDir, "project.csproj"), engine);
+
+ Console.WriteLine("TempDir: {0}", TempDir);
+
+ prel.AddProperty("AndroidApplication", "True");
+ prel.AddProperty("IntermediateOutputPath", monoAndroidResDirIntermediate);
+ prel.AddProperty("MonoAndroidResDirIntermediate", monoAndroidResDirIntermediate);
+ prel.AddProperty("_AndroidPackage", "com.xamarin.sample");
+
+ prel.AddItem("GoogleServicesJson", googleServicesJsonPath);
+
+ AddCoreTargets(prel);
+
+ var project = new ProjectInstance(prel);
+ var log = new MSBuildTestLogger();
+
+ var success = BuildProject(engine, project, "ProcessGoogleServicesJson", log);
+
+ Assert.IsTrue(success);
+ Assert.IsFalse(log.Events.Any(e => e.Message.Contains("ProcessGoogleServicesJson") && e.Message.Contains("skipped")));
+ }
+ }
+}
diff --git a/basement/buildtasks.tests/Helpers/MSBuildExtensions.cs b/basement/buildtasks.tests/Helpers/MSBuildExtensions.cs
new file mode 100644
index 000000000..d2c1dd0be
--- /dev/null
+++ b/basement/buildtasks.tests/Helpers/MSBuildExtensions.cs
@@ -0,0 +1,50 @@
+// Copyright (c) 2015-2016 Xamarin Inc.
+
+using System.Linq;
+using Microsoft.Build.Construction;
+
+namespace Xamarin.ContentPipeline.Tests
+{
+ //workaround for missing MSBuild API in Mono. Project.AddItem explodes,
+ //so we use ProjectRootElement, which doesn't have SetProperty/GetPropertyValue
+ static class MSBuildExtensions
+ {
+ public static void SetProperty(this ProjectRootElement prel, string name, string value)
+ {
+ var existing = prel.PropertyGroups.SelectMany(g => g.Properties).FirstOrDefault(p => p.Name == name);
+ if (existing != null)
+ existing.Value = value;
+ else
+ prel.AddProperty(name, value);
+ }
+
+ public static string GetPropertyValue(this ProjectRootElement prel, string name)
+ {
+ var existing = prel.Properties.FirstOrDefault(p => p.Name == name);
+ if (existing != null)
+ return existing.Value;
+ return null;
+ }
+
+ public static void RemoveItems(this ProjectRootElement prel, ProjectItemElement pel)
+ {
+ pel.Parent.RemoveChild(pel);
+ }
+
+ public static void SetMetadataValue(this ProjectItemElement pel, string name, string value)
+ {
+ var existing = pel.Metadata.FirstOrDefault(p => p.Name == name);
+ if (existing != null)
+ existing.Value = value;
+ else
+ pel.AddMetadata(name, value);
+ }
+
+ public static void RemoveMetadata(this ProjectItemElement pel, string name)
+ {
+ var existing = pel.Metadata.FirstOrDefault(p => p.Name == name);
+ if (existing != null)
+ pel.RemoveChild(existing);
+ }
+ }
+}
\ No newline at end of file
diff --git a/basement/buildtasks.tests/Helpers/MSBuildTestLogger.cs b/basement/buildtasks.tests/Helpers/MSBuildTestLogger.cs
new file mode 100644
index 000000000..18c739a55
--- /dev/null
+++ b/basement/buildtasks.tests/Helpers/MSBuildTestLogger.cs
@@ -0,0 +1,53 @@
+// Copyright (c) 2015-2016 Xamarin Inc.
+
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Framework;
+
+namespace Xamarin.ContentPipeline.Tests
+{
+ class MSBuildTestLogger : ILogger
+ {
+ IEventSource eventSource;
+
+ public void Initialize(IEventSource eventSource)
+ {
+ this.eventSource = eventSource;
+ Events = new List();
+ eventSource.AnyEventRaised += EventRaised;
+ Verbosity = LoggerVerbosity.Normal;
+ }
+
+ public void Shutdown()
+ {
+ eventSource.AnyEventRaised -= EventRaised;
+ }
+
+ void EventRaised(object sender, BuildEventArgs e)
+ {
+ Events.Add(e);
+ System.Console.WriteLine(e.Message);
+ }
+
+ public List Events { get; private set; }
+
+ public IEnumerable Errors
+ {
+ get
+ {
+ return Events.OfType();
+ }
+ }
+
+ public IEnumerable Warnings
+ {
+ get
+ {
+ return Events.OfType();
+ }
+ }
+
+ public LoggerVerbosity Verbosity { get; set; }
+ public string Parameters { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/basement/buildtasks.tests/Helpers/TestsBase.cs b/basement/buildtasks.tests/Helpers/TestsBase.cs
new file mode 100644
index 000000000..2d6eec69b
--- /dev/null
+++ b/basement/buildtasks.tests/Helpers/TestsBase.cs
@@ -0,0 +1,102 @@
+// Copyright (c) 2015-2016 Xamarin Inc.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Logging;
+using NUnit.Framework;
+
+namespace Xamarin.ContentPipeline.Tests
+{
+ class TestsBase
+ {
+ string originalWorkingDir;
+ string tempDir;
+
+ [OneTimeSetUp]
+ public void SetUp()
+ {
+ originalWorkingDir = Environment.CurrentDirectory;
+ tempDir = Path.GetTempFileName();
+ File.Delete(tempDir);
+ Directory.CreateDirectory(tempDir);
+ Environment.CurrentDirectory = tempDir;
+ }
+
+ [OneTimeTearDown]
+ public void TearDown()
+ {
+ Environment.CurrentDirectory = originalWorkingDir;
+ Directory.Delete(tempDir, true);
+
+ //HACK: touching BuildManager causes Mono to initialize its DefaultBuildManagerand never shut it down
+ StopMonoBuildManager(BuildManager.DefaultBuildManager);
+ }
+
+ public string TempDir { get { return tempDir; } }
+
+ protected string GetTempPath(params string[] components)
+ {
+ return Path.Combine(tempDir, Path.Combine(components));
+ }
+
+ protected static void AssertNoMessagesOrWarnings(MSBuildTestLogger logger)
+ {
+ BuildEventArgs err = logger.Errors.FirstOrDefault();
+ if (err == null)
+ {
+ err = logger.Warnings.FirstOrDefault();
+ if (err == null)
+ {
+ return;
+ }
+ }
+ Assert.Fail(err.Message);
+ }
+
+ // work around Mono's ProjectInstance.Build using a separate BuildManager and not shutting it down
+ // Mono's BuildManager has a non-background worker thread and doesn't shut it down automatically
+ protected bool BuildProject(
+ ProjectCollection projects, ProjectInstance project, string[] targets, IEnumerable loggers,
+ IEnumerable remoteLoggers, out IDictionary targetOutputs)
+ {
+ var parameters = new BuildParameters(projects)
+ {
+ Loggers = loggers,
+ ForwardingLoggers = remoteLoggers,
+ DefaultToolsVersion = projects.DefaultToolsVersion,
+ };
+ var data = new BuildRequestData(project, targets ?? project.DefaultTargets.ToArray());
+ var result = BuildManager.DefaultBuildManager.Build(parameters, data);
+ targetOutputs = result.ResultsByTarget;
+ return result.OverallResult == BuildResultCode.Success;
+ }
+
+ static void StopMonoBuildManager(BuildManager buildManager)
+ {
+ try
+ {
+ const BindingFlags instanceFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
+ PropertyInfo nodeManagerProp = typeof(BuildManager).GetProperty("BuildNodeManager", instanceFlags);
+ var nodeManager = nodeManagerProp.GetValue(buildManager);
+ var stopMeth = nodeManager.GetType().GetMethod("Stop", instanceFlags);
+ stopMeth.Invoke(nodeManager, new object[0]);
+ }
+ catch
+ {
+ }
+ }
+
+ protected bool BuildProject(
+ ProjectCollection projects, ProjectInstance project, string target, ILogger logger)
+ {
+ IDictionary targetOutputs;
+ return BuildProject(projects, project, new[] { target }, new[] { logger }, new ForwardingLoggerRecord[0], out targetOutputs);
+ }
+ }
+}
\ No newline at end of file
diff --git a/basement/buildtasks.tests/packages.config b/basement/buildtasks.tests/packages.config
index c714ef3a2..b183023e1 100644
--- a/basement/buildtasks.tests/packages.config
+++ b/basement/buildtasks.tests/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/basement/buildtasks/ProcessGoogleServicesJson.cs b/basement/buildtasks/ProcessGoogleServicesJson.cs
index 68352ddf7..5b7b95b7e 100644
--- a/basement/buildtasks/ProcessGoogleServicesJson.cs
+++ b/basement/buildtasks/ProcessGoogleServicesJson.cs
@@ -14,8 +14,6 @@ public class ProcessGoogleServicesJson : Task
const string RESFILE_VALUES = "goog_svcs_json.xml";
const string RESFILE_XML = "global_tracker.xml";
- public string IntermediateOutputPrefix { get; set; }
-
[Output]
public ITaskItem[] GoogleServicesGeneratedResources { get; set; }
@@ -141,8 +139,18 @@ public override bool Execute ()
if (outputFiles.Any ())
GoogleServicesGeneratedResources = outputFiles.ToArray ();
-
- Log.LogMessage ("Finished ProcessGoogleServicesJson...");
+
+ Log.LogMessage("Writing stamp file...");
+
+ var stampText = string.Empty;
+ if (wroteXmlPath)
+ stampText += xmlPath + Environment.NewLine;
+ if (wroteValuesPath)
+ stampText += valuesPath + Environment.NewLine;
+
+ File.WriteAllText(Path.Combine(IntermediateOutputPath ?? MonoAndroidResDirIntermediate, "ProcessGoogleServicesJson.stamp"), stampText.Trim());
+
+ Log.LogMessage ("Finished ProcessGoogleServicesJson...");
return true;
}
diff --git a/basement/buildtasks/Xamarin.GooglePlayServices.Basement.targets b/basement/buildtasks/Xamarin.GooglePlayServices.Basement.targets
index 63c2cb54b..11c36342b 100644
--- a/basement/buildtasks/Xamarin.GooglePlayServices.Basement.targets
+++ b/basement/buildtasks/Xamarin.GooglePlayServices.Basement.targets
@@ -37,24 +37,30 @@
+
+ AfterTargets="$(ProcessGoogleServicesJsonAfterTargets)"
+ Inputs="@(GoogleServicesJson)"
+ Outputs="$(IntermediateOutputPath)\ProcessGoogleServicesJson.stamp">
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/basement/source/Transforms/Metadata.xml b/basement/source/Transforms/Metadata.xml
index e2bdcd62f..cd14331fd 100644
--- a/basement/source/Transforms/Metadata.xml
+++ b/basement/source/Transforms/Metadata.xml
@@ -17,6 +17,7 @@
Android.Gms.Ads.Identifier
Android.Gms.Location.Places
Firebase
+ Firebase.Iid
Android.Gms.Flags.Impl
@@ -24,7 +25,7 @@
-
+
@@ -47,10 +48,15 @@
false
false
false
+ false
+ false
+ false
-
+
+
+
diff --git a/build.cake b/build.cake
index cbae62937..b7ea79a82 100644
--- a/build.cake
+++ b/build.cake
@@ -1,6 +1,7 @@
#tool nuget:?package=ILRepack&version=2.0.10
#tool nuget:?package=XamarinComponent
#tool nuget:?package=Cake.MonoApiTools
+#tool nuget:?package=Microsoft.DotNet.BuildTools.GenAPI&version=1.0.0-beta-00081
#addin nuget:?package=Cake.Json
#addin nuget:?package=Cake.XCode
@@ -11,30 +12,39 @@
// To find new URL: https://dl-ssl.google.com/android/repository/addon.xml and search for google_play_services_*.zip\
// FROM: https://dl.google.com/android/repository/addon2-1.xml
-var DOCS_URL = "https://dl-ssl.google.com/android/repository/google_play_services_v8_rc41.zip";
-var M2_REPOSITORY = "https://dl-ssl.google.com/android/repository/google_m2repository_gms_v8_rc42_wear_2_0_rc6.zip";
+var DOCS_URL = "https://dl-ssl.google.com/android/repository/google_play_services_v9_rc41.zip";
+var M2_REPOSITORY = "https://dl-ssl.google.com/android/repository/google_m2repository_gms_v9_1_rc07_wear_2_0_1_rc3.zip";
// We grab the previous release's api-info.xml to use as a comparison for this build's generated info to make an api-diff
var BASE_API_INFO_URL = "https://github.com/xamarin/GooglePlayServicesComponents/releases/download/42.1001.0/api-info.xml";
-var PLAY_COMPONENT_VERSION = "42.1001.0.0";
-var PLAY_NUGET_VERSION = "42.1001.0";
-var PLAY_AAR_VERSION = "10.0.1";
-var VERSION_DESC = "10.0.1";
+// The common suffix for nuget version
+// Sometimes might be "-beta1" for a prerelease, or ".1" if we have a point release for the same actual aar's
+// will be blank for a stable release that has no point release fixes
+var COMMON_NUGET_VERSION = "";
-var WEAR_COMPONENT_VERSION = "2.0.0.0";
-var WEAR_NUGET_VERSION = "2.0.0";
-var WEAR_AAR_VERSION = "2.0.0";
-var WEARABLE_SUPPORT_VERSION = "2.0.0";
+var PLAY_COMPONENT_VERSION = "42.1021.0.0";
+var PLAY_NUGET_VERSION = "42.1021.0" + COMMON_NUGET_VERSION;
+var PLAY_AAR_VERSION = "10.2.1";
+var VERSION_DESC = "10.2.1";
+
+var WEAR_COMPONENT_VERSION = "2.0.1.0";
+var WEAR_NUGET_VERSION = "2.0.1" + COMMON_NUGET_VERSION;
+var WEAR_AAR_VERSION = "2.0.1";
+var WEARABLE_SUPPORT_VERSION = "2.0.1";
var FIREBASE_COMPONENT_VERSION = PLAY_COMPONENT_VERSION;
var FIREBASE_NUGET_VERSION = PLAY_NUGET_VERSION;
var FIREBASE_AAR_VERSION = PLAY_AAR_VERSION;
var TARGET = Argument ("t", Argument ("target", "Default"));
+var BUILD_CONFIG = Argument ("config", "Release");
var CPU_COUNT = System.Environment.ProcessorCount;
-var ALWAYS_MSBUILD = false;
+// MSBuild in < Mono 5.0 has some issues with multi cpu count being specified causing errors
+if (!IsRunningOnWindows())
+ CPU_COUNT = 1;
+var ALWAYS_MSBUILD = true;
LogSystemInfo ();
@@ -133,6 +143,17 @@ if (IsRunningOnWindows ())
var MONO_PATH = "/Library/Frameworks/Mono.framework/Versions/Current";
+var MSCORLIB_PATH = "/Library/Frameworks/Xamarin.Android.framework/Libraries/mono/2.1/";
+if (IsRunningOnWindows ()) {
+
+ var DOTNETDIR = new DirectoryPath (Environment.GetFolderPath (Environment.SpecialFolder.Windows)).Combine ("Microsoft.NET/");
+
+ if (DirectoryExists (DOTNETDIR.Combine ("Framework64")))
+ MSCORLIB_PATH = MakeAbsolute (DOTNETDIR.Combine("Framework64/v4.0.30319/")).FullPath;
+ else
+ MSCORLIB_PATH = MakeAbsolute (DOTNETDIR.Combine("Framework/v4.0.30319/")).FullPath;
+}
+
var buildsOnWinMac = BuildPlatforms.Windows | BuildPlatforms.Mac;
var buildSpec = new BuildSpec {
@@ -286,6 +307,9 @@ var buildSpec = new BuildSpec {
// These are empty packages that depend on others
new NuGetInfo { NuSpec = "./firebase-core/nuget/Xamarin.Firebase.Core.nuspec", Version = PLAY_NUGET_VERSION, RequireLicenseAcceptance = true },
new NuGetInfo { NuSpec = "./firebase-ads/nuget/Xamarin.Firebase.Ads.nuspec", Version = PLAY_NUGET_VERSION, RequireLicenseAcceptance = true },
+
+ // Type forwarder packages for backwards compatibility
+ new NuGetInfo { NuSpec = "./appindexing/nuget/Xamarin.GooglePlayServices.AppIndexing.nuspec", Version = PLAY_NUGET_VERSION, RequireLicenseAcceptance = true },
},
Components = new [] {
@@ -655,11 +679,56 @@ Task ("nuget-setup").IsDependentOn ("buildtasks").Does (() => {
xOrig.Save (MakeAbsolute (targetsFile).FullPath);
}
}
+
+ var extraNuspecTemplates = new [] {
+ new FilePath ("./appindexing/nuget/Xamarin.GooglePlayServices.AppIndexing.template.nuspec"),
+ };
+
+ foreach (var nuspec in extraNuspecTemplates) {
+ var nuspecTxt = FileReadText (nuspec).Replace ("$aar-version$", VERSION_DESC);
+ var newNuspec = nuspec.FullPath.Replace (".template.nuspec", ".nuspec");
+ FileWriteText (newNuspec, nuspecTxt);
+ }
});
Task ("nuget").IsDependentOn ("nuget-setup").IsDependentOn ("nuget-base").IsDependentOn ("libs");
-Task ("libs").IsDependentOn ("nuget-setup").IsDependentOn ("libs-base");
+Task ("libs").IsDependentOn ("nuget-setup").IsDependentOn ("genapi").IsDependentOn ("libs-base");
+
+Task ("genapi").IsDependentOn ("libs-base").IsDependentOn ("externals").Does (() => {
+
+ var GenApiToolPath = GetFiles ("./tools/**/GenAPI.exe").FirstOrDefault ();
+
+ // For some reason GenAPI.exe can't handle absolute paths on mac/unix properly, so always make them relative
+ // GenAPI.exe -libPath:$(MONOANDROID) -out:Some.generated.cs -w:TypeForwards ./relative/path/to/Assembly.dll
+ var libDirPrefix = IsRunningOnWindows () ? "output/" : "";
+
+ var libs = new FilePath [] {
+ "./" + libDirPrefix + "Xamarin.Firebase.AppIndexing.dll",
+ };
+
+ foreach (var lib in libs) {
+ var genName = lib.GetFilename () + ".generated.cs";
+
+ var libPath = IsRunningOnWindows () ? MakeAbsolute (lib).FullPath : lib.FullPath;
+ var monoDroidPath = IsRunningOnWindows () ? "\"" + MONODROID_PATH + "\"" : MONODROID_PATH;
+
+ Information ("GenAPI: {0}", lib.FullPath);
+
+ StartProcess (GenApiToolPath, new ProcessSettings {
+ Arguments = string.Format("-libPath:{0} -out:{1}{2} -w:TypeForwards {3}",
+ monoDroidPath + "," + MSCORLIB_PATH,
+ IsRunningOnWindows () ? "" : "./",
+ genName,
+ libPath),
+ WorkingDirectory = "./output/",
+ });
+ }
+
+ DotNetBuild ("./GooglePlayServices.TypeForwarders.sln", c => c.Configuration = BUILD_CONFIG);
+
+ CopyFile ("./appindexing/source/bin/" + BUILD_CONFIG + "/Xamarin.GooglePlayServices.AppIndexing.dll", "./output/Xamarin.GooglePlayServices.AppIndexing.dll");
+});
Task ("buildtasks").Does (() =>
{
diff --git a/firebase-analytics-impl/nuget/Xamarin.Firebase.Analytics.Impl.template.nuspec b/firebase-analytics-impl/nuget/Xamarin.Firebase.Analytics.Impl.template.nuspec
index 21fa80c02..74f141a0a 100644
--- a/firebase-analytics-impl/nuget/Xamarin.Firebase.Analytics.Impl.template.nuspec
+++ b/firebase-analytics-impl/nuget/Xamarin.Firebase.Analytics.Impl.template.nuspec
@@ -18,6 +18,7 @@
+
diff --git a/firebase-analytics-impl/source/Firebase-Analytics-Impl.csproj b/firebase-analytics-impl/source/Firebase-Analytics-Impl.csproj
index d34968fb9..74eabda38 100644
--- a/firebase-analytics-impl/source/Firebase-Analytics-Impl.csproj
+++ b/firebase-analytics-impl/source/Firebase-Analytics-Impl.csproj
@@ -72,6 +72,10 @@
{B28F65D1-D8DD-45E8-9DD7-74A3BE40B4CE}
Firebase-Iid
+
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}
+ Tasks
+
diff --git a/firebase-analytics/source/Firebase-Analytics.csproj b/firebase-analytics/source/Firebase-Analytics.csproj
index 38832fdbe..8017b4cd3 100644
--- a/firebase-analytics/source/Firebase-Analytics.csproj
+++ b/firebase-analytics/source/Firebase-Analytics.csproj
@@ -72,6 +72,10 @@
{CFB0A03A-F787-4EE9-9EA6-8A2A65E82704}
Firebase-Analytics-Impl
+
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}
+ Tasks
+
diff --git a/firebase-appindexing/nuget/Xamarin.Firebase.AppIndexing.template.nuspec b/firebase-appindexing/nuget/Xamarin.Firebase.AppIndexing.template.nuspec
index d093dcd7d..ff01102de 100644
--- a/firebase-appindexing/nuget/Xamarin.Firebase.AppIndexing.template.nuspec
+++ b/firebase-appindexing/nuget/Xamarin.Firebase.AppIndexing.template.nuspec
@@ -18,6 +18,8 @@
+
+
diff --git a/games/nuget/Xamarin.GooglePlayServices.Games.template.nuspec b/games/nuget/Xamarin.GooglePlayServices.Games.template.nuspec
index 74d231f9c..27f4c2035 100644
--- a/games/nuget/Xamarin.GooglePlayServices.Games.template.nuspec
+++ b/games/nuget/Xamarin.GooglePlayServices.Games.template.nuspec
@@ -22,6 +22,7 @@
+
diff --git a/games/source/Games.csproj b/games/source/Games.csproj
index f3dcf9c81..b90d72885 100644
--- a/games/source/Games.csproj
+++ b/games/source/Games.csproj
@@ -85,6 +85,10 @@
{6A38FACF-F0C5-4A49-8A8A-7CE6634207CE}
Basement
+
+ {53F87D88-8871-41A2-9F81-B79AB02FEC24}
+ Tasks
+
diff --git a/gcm/samples/GCMSample/MainActivity.cs b/gcm/samples/GCMSample/MainActivity.cs
index d8a551064..ca91c9e18 100644
--- a/gcm/samples/GCMSample/MainActivity.cs
+++ b/gcm/samples/GCMSample/MainActivity.cs
@@ -118,7 +118,7 @@ protected override void OnHandleIntent (Intent intent)
[IntentFilter (new [] { InstanceID.IntentFilterAction })]
public class MyInstanceIDListenerService : InstanceIDListenerService
{
- public override async void OnTokenRefresh ()
+ public override void OnTokenRefresh ()
{
MyRegistrationService.Register (this);
}
diff --git a/instantapps/source/Transforms/Metadata.xml b/instantapps/source/Transforms/Metadata.xml
index 9db8247c6..a8108bdf3 100644
--- a/instantapps/source/Transforms/Metadata.xml
+++ b/instantapps/source/Transforms/Metadata.xml
@@ -22,5 +22,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nearby/samples/NearbySample/MainActivity.cs b/nearby/samples/NearbySample/MainActivity.cs
index c5fa5c9e0..cc0a35332 100644
--- a/nearby/samples/NearbySample/MainActivity.cs
+++ b/nearby/samples/NearbySample/MainActivity.cs
@@ -19,9 +19,7 @@ namespace NearbySample
public class MainActivity : Activity,
GoogleApiClient.IConnectionCallbacks,
GoogleApiClient.IOnConnectionFailedListener,
- IConnectionsMessageListener,
- IConnectionsConnectionRequestListener,
- IConnectionsEndpointDiscoveryListener
+ IConnectionsMessageListener
{
class ConnectionResponseCallback : Java.Lang.Object, IConnectionsConnectionResponseCallback
@@ -160,7 +158,10 @@ async void StartAdvertising()
// will construct a default name based on device model such as 'LGE Nexus 5'.
string name = null;
var result = await NearbyClass.Connections.StartAdvertisingAsync (
- mGoogleApiClient, name, appMetadata, TIMEOUT_ADVERTISE, this);
+ mGoogleApiClient, name, appMetadata, TIMEOUT_ADVERTISE, new MyConnectionRequestListener
+ {
+ ConnectionRequestHandler = OnConnectionRequest
+ });
Log ("startAdvertising:onResult:" + result);
@@ -196,7 +197,7 @@ async void StartDiscovery ()
return;
}
- var status = await NearbyClass.Connections.StartDiscoveryAsync (mGoogleApiClient, serviceId, TIMEOUT_DISCOVER, this);
+ var status = await NearbyClass.Connections.StartDiscoveryAsync (mGoogleApiClient, serviceId, TIMEOUT_DISCOVER, new MyEndpointDiscoveryListener { EndpointLostHandler = OnEndpointLost, EndpointFoundHandler = OnEndpointFound });
if (status.IsSuccess) {
Log("startDiscovery:onResult: SUCCESS");
@@ -268,7 +269,7 @@ async void ConnectTo (String endpointId, string endpointName)
Log ("connectTo: " + status.IsSuccess);
}
- public void OnConnectionRequest (string endpointId, string deviceId, string endpointName, byte[] payload)
+ public void OnConnectionRequest (string endpointId, string endpointName, byte[] payload)
{
Log("onConnectionRequest:" + endpointId + ":" + endpointName);
@@ -314,7 +315,7 @@ public void OnDisconnected (string endpointId)
UpdateViewVisibility (NearbyConnectionState.Ready);
}
- public void OnEndpointFound (string endpointId, string deviceId, string serviceId, string endpointName)
+ public void OnEndpointFound (string endpointId, string serviceId, string endpointName)
{
Log ("onEndpointFound:" + endpointId + ":" + endpointName);
@@ -420,6 +421,31 @@ public enum NearbyConnectionState {
Discovering = 1026,
Connected = 1027
}
+
+ public class MyConnectionRequestListener : ConnectionsConnectionRequestListener
+ {
+ public Action ConnectionRequestHandler { get; set; }
+
+ public override void OnConnectionRequest(string remoteEndpointId, string remoteEndpointName, byte[] handshakeData)
+ {
+ ConnectionRequestHandler?.Invoke(remoteEndpointId, remoteEndpointName, handshakeData);
+ }
+ }
+
+ public class MyEndpointDiscoveryListener : ConnectionsEndpointDiscoveryListener
+ {
+ public Action EndpointFoundHandler { get; set; }
+ public override void OnEndpointFound(string endpointId, string serviceId, string name)
+ {
+ EndpointFoundHandler?.Invoke(endpointId, serviceId, name);
+ }
+
+ public Action EndpointLostHandler { get; set; }
+ public override void OnEndpointLost(string endpointId)
+ {
+ EndpointLostHandler?.Invoke(endpointId);
+ }
+ }
}
diff --git a/nearby/source/Additions/IPendingResultExtensions.cs b/nearby/source/Additions/IPendingResultExtensions.cs
index 68f08cc40..5e638ae79 100644
--- a/nearby/source/Additions/IPendingResultExtensions.cs
+++ b/nearby/source/Additions/IPendingResultExtensions.cs
@@ -19,11 +19,11 @@ public static async Task SendConnectionRequestAsync (this IConnections
{
return (await api.SendConnectionRequest (apiClient, name, remoteEndpointId, payload, connectionResponseCallback, messageListener)).JavaCast ();
}
- public static async Task StartAdvertisingAsync (this IConnections api, GoogleApiClient apiClient, string name, Android.Gms.Nearby.Connection.AppMetadata appMetadata, long durationMillis, IConnectionsConnectionRequestListener connectionRequestListener)
+ public static async Task StartAdvertisingAsync (this IConnections api, GoogleApiClient apiClient, string name, Android.Gms.Nearby.Connection.AppMetadata appMetadata, long durationMillis, ConnectionsConnectionRequestListener connectionRequestListener)
{
return (await api.StartAdvertising (apiClient, name, appMetadata, durationMillis, connectionRequestListener)).JavaCast ();
}
- public static async Task StartDiscoveryAsync (this IConnections api, GoogleApiClient apiClient, string serviceId, long durationMillis, IConnectionsEndpointDiscoveryListener listener)
+ public static async Task StartDiscoveryAsync (this IConnections api, GoogleApiClient apiClient, string serviceId, long durationMillis, ConnectionsEndpointDiscoveryListener listener)
{
return (await api.StartDiscovery (apiClient, serviceId, durationMillis, listener)).JavaCast ();
}
diff --git a/tests/GooglePlayServices.Tests.sln b/tests/GooglePlayServices.Tests.sln
new file mode 100644
index 000000000..95022a670
--- /dev/null
+++ b/tests/GooglePlayServices.Tests.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GooglePlayServices.Tests", "GooglePlayServices.Tests\GooglePlayServices.Tests.csproj", "{CCA263F0-8DAA-44F4-B5CE-C03F92FF7FAA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CCA263F0-8DAA-44F4-B5CE-C03F92FF7FAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CCA263F0-8DAA-44F4-B5CE-C03F92FF7FAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CCA263F0-8DAA-44F4-B5CE-C03F92FF7FAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CCA263F0-8DAA-44F4-B5CE-C03F92FF7FAA}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/tests/GooglePlayServices.Tests/Assets/AboutAssets.txt b/tests/GooglePlayServices.Tests/Assets/AboutAssets.txt
new file mode 100644
index 000000000..a9b0638eb
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/Assets/AboutAssets.txt
@@ -0,0 +1,19 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories) and given a Build Action of "AndroidAsset".
+
+These files will be deployed with your package and will be accessible using Android's
+AssetManager, like this:
+
+public class ReadAsset : Activity
+{
+ protected override void OnCreate (Bundle bundle)
+ {
+ base.OnCreate (bundle);
+
+ InputStream input = Assets.Open ("my_asset.txt");
+ }
+}
+
+Additionally, some Android functions will automatically load asset files:
+
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
diff --git a/tests/GooglePlayServices.Tests/GooglePlayServices.Tests.csproj b/tests/GooglePlayServices.Tests/GooglePlayServices.Tests.csproj
new file mode 100644
index 000000000..26782b8cc
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/GooglePlayServices.Tests.csproj
@@ -0,0 +1,269 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {CCA263F0-8DAA-44F4-B5CE-C03F92FF7FAA}
+ {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ GooglePlayServices.Tests
+ AndroidSupport.Tests
+ v7.1
+ True
+ Resources\Resource.designer.cs
+ Resource
+ Properties\AndroidManifest.xml
+ Resources
+ Assets
+ true
+ true
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ None
+ arm64-v8a;armeabi;armeabi-v7a;x86
+
+
+ true
+ pdbonly
+ true
+ bin\Release
+ prompt
+ 4
+ true
+ false
+
+
+
+
+
+
+
+
+ ..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll
+
+
+ ..\..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll
+
+
+ ..\..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll
+
+
+ ..\..\packages\xunit.extensibility.execution.2.2.0\lib\netstandard1.1\xunit.execution.dotnet.dll
+
+
+
+ ..\packages\Xamarin.Android.Support.Compat.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.Compat.dll
+
+
+ ..\packages\Xamarin.Android.Support.Core.UI.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.Core.UI.dll
+
+
+ ..\packages\Xamarin.Android.Support.Core.Utils.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.Core.Utils.dll
+
+
+ ..\packages\Xamarin.Android.Support.Media.Compat.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.Media.Compat.dll
+
+
+ ..\packages\Xamarin.Android.Support.Fragment.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.Fragment.dll
+
+
+ ..\packages\Xamarin.Android.Support.Vector.Drawable.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.Vector.Drawable.dll
+
+
+ ..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.dll
+
+
+ ..\packages\Xamarin.Android.Support.v7.AppCompat.25.1.1\lib\MonoAndroid70\Xamarin.Android.Support.v7.AppCompat.dll
+
+
+ ..\packages\xunit.runner.utility.2.2.0\lib\netstandard1.5\xunit.runner.utility.netstandard15.dll
+
+
+ ..\..\output\Xamarin.Firebase.Analytics.dll
+
+
+ ..\..\output\Xamarin.Firebase.Analytics.Impl.dll
+
+
+ ..\..\output\Xamarin.Firebase.AppIndexing.dll
+
+
+ ..\..\output\Xamarin.Firebase.Auth.dll
+
+
+ ..\..\output\Xamarin.Firebase.Common.dll
+
+
+ ..\..\output\Xamarin.Firebase.Config.dll
+
+
+ ..\..\output\Xamarin.Firebase.Crash.dll
+
+
+ ..\..\output\Xamarin.Firebase.Database.Connection.dll
+
+
+ ..\..\output\Xamarin.Firebase.Database.dll
+
+
+ ..\..\output\Xamarin.Firebase.Iid.dll
+
+
+ ..\..\output\Xamarin.Firebase.Messaging.dll
+
+
+ ..\..\output\Xamarin.Firebase.Storage.Common.dll
+
+
+ ..\..\output\Xamarin.Firebase.Storage.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Ads.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Ads.Lite.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Analytics.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Analytics.Impl.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.AppInvite.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Auth.Base.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Auth.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Awareness.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Base.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Basement.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Cast.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Cast.Framework.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Clearcut.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Drive.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Fitness.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Games.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Gass.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Gcm.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Identity.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Iid.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.InstantApps.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Location.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Maps.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Nearby.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Panorama.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Places.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Plus.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.SafetyNet.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.TagManager.Api.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.TagManager.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.TagManager.V4.Impl.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Tasks.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Vision.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Wallet.dll
+
+
+ ..\..\output\Xamarin.GooglePlayServices.Wearable.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/GooglePlayServices.Tests/MainActivity.cs b/tests/GooglePlayServices.Tests/MainActivity.cs
new file mode 100644
index 000000000..ebf733f31
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/MainActivity.cs
@@ -0,0 +1,143 @@
+using Android.App;
+using Android.Widget;
+using Android.OS;
+using System.Collections.Generic;
+using System.Reflection;
+using Xunit;
+using Xunit.Abstractions;
+using System;
+using Xunit.Runners;
+using System.Threading.Tasks;
+using Android.Support.V7.App;
+using Android.Views;
+
+namespace GooglePlayServices.Tests
+{
+ [Activity(Label = "AndroidSupport.Tests", MainLauncher = true, Theme="@style/Theme.AppCompat.Light", Icon = "@mipmap/icon")]
+ public class MainActivity : AppCompatActivity
+ {
+ public static Activity TestParentActivity { get; set; }
+
+
+ TaskCompletionSource tcsTests = new TaskCompletionSource();
+
+ AssemblyRunner assemblyRunner;
+
+ TestResultsAdapter adapter;
+ ListView listView;
+
+ protected override void OnCreate(Bundle savedInstanceState)
+ {
+ base.OnCreate(savedInstanceState);
+
+ TestParentActivity = this;
+
+ // Set our view from the "main" layout resource
+ SetContentView(Resource.Layout.Main);
+
+ listView = FindViewById(Resource.Id.listView);
+
+ adapter = new TestResultsAdapter { Parent = this };
+ listView.Adapter = adapter;
+
+ assemblyRunner = AssemblyRunner.WithoutAppDomain(Assembly.GetExecutingAssembly().GetName().Name + ".dll");
+ assemblyRunner.OnDiscoveryComplete = DiscoveryCompleteHandler;;
+ assemblyRunner.OnExecutionComplete = ExecutionCompleteHandler;;
+ assemblyRunner.OnTestFailed = TestFailedHandler;;
+ assemblyRunner.OnTestSkipped = TestSkippedHandler;
+ assemblyRunner.OnTestPassed = TestPassedHandler;
+ assemblyRunner.OnTestOutput = TestOutputHandler;
+
+ Console.WriteLine("Discovering...");
+ assemblyRunner.Start ();
+ }
+
+ bool anyFailed = false;
+
+ void DiscoveryCompleteHandler(DiscoveryCompleteInfo obj)
+ {
+ Console.WriteLine("Discovery Complete.");
+ }
+
+ void ExecutionCompleteHandler(ExecutionCompleteInfo obj)
+ {
+ Console.WriteLine("Test Complete: Success={0}", !anyFailed);
+ tcsTests.TrySetResult(anyFailed);
+ }
+
+ void TestFailedHandler(TestFailedInfo obj)
+ {
+ anyFailed = true;
+ adapter.AddResult(new TestResultInfo
+ {
+ Passed = false,
+ DisplayName = obj.TestDisplayName
+ });
+ }
+
+ void TestSkippedHandler(TestSkippedInfo obj)
+ {
+
+ }
+
+ void TestOutputHandler(TestOutputInfo obj)
+ {
+
+ }
+
+ void TestPassedHandler(TestPassedInfo obj)
+ {
+ adapter.AddResult(new TestResultInfo
+ {
+ Passed = true,
+ DisplayName = obj.TestDisplayName
+ });
+ }
+ }
+
+ class TestResultInfo
+ {
+ public bool Passed { get; set; }
+ public string DisplayName { get; set; }
+ }
+
+ class TestResultsAdapter : BaseAdapter
+ {
+ public Activity Parent;
+ List results = new List();
+
+ public void AddResult(TestResultInfo info)
+ {
+ results.Add(info);
+ Parent.RunOnUiThread(() => NotifyDataSetChanged());
+ }
+
+ public override TestResultInfo this[int position]
+ {
+ get { return results[position]; }
+ }
+
+ public override int Count
+ {
+ get { return results.Count; }
+ }
+
+ public override long GetItemId(int position)
+ {
+ return position;
+ }
+
+ public override View GetView(int position, View convertView, ViewGroup parent)
+ {
+ var view = convertView ?? LayoutInflater.From(Parent).Inflate(Android.Resource.Layout.TwoLineListItem, parent, false);
+
+ var r = this[position];
+
+ view.FindViewById(Android.Resource.Id.Text1).Text = r.DisplayName;
+ view.FindViewById(Android.Resource.Id.Text2).Text = r.Passed ? "Passed" : "Failed";
+ view.FindViewById(Android.Resource.Id.Text2).SetTextColor(r.Passed ? Android.Graphics.Color.Green : Android.Graphics.Color.Maroon);
+
+ return view;
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/GooglePlayServices.Tests/Properties/AndroidManifest.xml b/tests/GooglePlayServices.Tests/Properties/AndroidManifest.xml
new file mode 100644
index 000000000..e1198d91d
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/Properties/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/GooglePlayServices.Tests/Properties/AssemblyInfo.cs b/tests/GooglePlayServices.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..dc24fbdda
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Android.App;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("AndroidSupport.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("${AuthorCopyright}")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.0")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
diff --git a/tests/GooglePlayServices.Tests/Resources/AboutResources.txt b/tests/GooglePlayServices.Tests/Resources/AboutResources.txt
new file mode 100644
index 000000000..10f52d460
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/Resources/AboutResources.txt
@@ -0,0 +1,44 @@
+Images, layout descriptions, binary blobs and string dictionaries can be included
+in your application as resource files. Various Android APIs are designed to
+operate on the resource IDs instead of dealing with images, strings or binary blobs
+directly.
+
+For example, a sample Android app that contains a user interface layout (main.axml),
+an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
+would keep its resources in the "Resources" directory of the application:
+
+Resources/
+ drawable/
+ icon.png
+
+ layout/
+ main.axml
+
+ values/
+ strings.xml
+
+In order to get the build system to recognize Android resources, set the build action to
+"AndroidResource". The native Android APIs do not operate directly with filenames, but
+instead operate on resource IDs. When you compile an Android application that uses resources,
+the build system will package the resources for distribution and generate a class called "R"
+(this is an Android convention) that contains the tokens for each one of the resources
+included. For example, for the above Resources layout, this is what the R class would expose:
+
+public class R {
+ public class drawable {
+ public const int icon = 0x123;
+ }
+
+ public class layout {
+ public const int main = 0x456;
+ }
+
+ public class strings {
+ public const int first_string = 0xabc;
+ public const int second_string = 0xbcd;
+ }
+}
+
+You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
+to reference the layout/main.axml file, or R.strings.first_string to reference the first
+string in the dictionary file values/strings.xml.
diff --git a/tests/GooglePlayServices.Tests/Resources/layout/Main.axml b/tests/GooglePlayServices.Tests/Resources/layout/Main.axml
new file mode 100644
index 000000000..83219bdbf
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/Resources/layout/Main.axml
@@ -0,0 +1,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/tests/GooglePlayServices.Tests/Resources/mipmap-hdpi/Icon.png b/tests/GooglePlayServices.Tests/Resources/mipmap-hdpi/Icon.png
new file mode 100644
index 000000000..f4c804644
Binary files /dev/null and b/tests/GooglePlayServices.Tests/Resources/mipmap-hdpi/Icon.png differ
diff --git a/tests/GooglePlayServices.Tests/Resources/mipmap-mdpi/Icon.png b/tests/GooglePlayServices.Tests/Resources/mipmap-mdpi/Icon.png
new file mode 100644
index 000000000..ef1e1ee7d
Binary files /dev/null and b/tests/GooglePlayServices.Tests/Resources/mipmap-mdpi/Icon.png differ
diff --git a/tests/GooglePlayServices.Tests/Resources/mipmap-xhdpi/Icon.png b/tests/GooglePlayServices.Tests/Resources/mipmap-xhdpi/Icon.png
new file mode 100644
index 000000000..b7e2e57aa
Binary files /dev/null and b/tests/GooglePlayServices.Tests/Resources/mipmap-xhdpi/Icon.png differ
diff --git a/tests/GooglePlayServices.Tests/Resources/mipmap-xxhdpi/Icon.png b/tests/GooglePlayServices.Tests/Resources/mipmap-xxhdpi/Icon.png
new file mode 100644
index 000000000..8d20a38d1
Binary files /dev/null and b/tests/GooglePlayServices.Tests/Resources/mipmap-xxhdpi/Icon.png differ
diff --git a/tests/GooglePlayServices.Tests/Resources/mipmap-xxxhdpi/Icon.png b/tests/GooglePlayServices.Tests/Resources/mipmap-xxxhdpi/Icon.png
new file mode 100644
index 000000000..6d9919c41
Binary files /dev/null and b/tests/GooglePlayServices.Tests/Resources/mipmap-xxxhdpi/Icon.png differ
diff --git a/tests/GooglePlayServices.Tests/Resources/values/Strings.xml b/tests/GooglePlayServices.Tests/Resources/values/Strings.xml
new file mode 100644
index 000000000..cc82d40a5
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/Resources/values/Strings.xml
@@ -0,0 +1,5 @@
+
+
+ Hello World, Click Me!
+ AndroidSupport.Tests
+
diff --git a/tests/GooglePlayServices.Tests/Tests.cs b/tests/GooglePlayServices.Tests/Tests.cs
new file mode 100644
index 000000000..5eb88f7da
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/Tests.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading.Tasks;
+using Android.App;
+using Android.OS;
+using Android.Support.V4.App;
+using Xunit;
+using Xunit.Extensions;
+
+namespace GooglePlayServices.Tests
+{
+ public class Tests
+ {
+ [Fact]
+ public void GooglePlayServicesUtil_Exists ()
+ {
+ var versionCode = Android.Gms.Common.GooglePlayServicesUtil.GooglePlayServicesVersionCode;
+
+ Console.WriteLine("Google Play Services Version: {0}", versionCode);
+
+ Assert.True(versionCode > 0);
+ }
+
+ [Fact]
+ public void GoogleApiAvailability_Exists()
+ {
+ var versionCode = Android.Gms.Common.GoogleApiAvailability.GooglePlayServicesVersionCode;
+
+ Console.WriteLine("Google Play Services Version: {0}", versionCode);
+
+ Assert.True(versionCode > 0);
+ }
+ }
+}
diff --git a/tests/GooglePlayServices.Tests/packages.config b/tests/GooglePlayServices.Tests/packages.config
new file mode 100644
index 000000000..895729ade
--- /dev/null
+++ b/tests/GooglePlayServices.Tests/packages.config
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/util/maven-repo-dependency-diff.workbook b/util/maven-repo-dependency-diff.workbook
new file mode 100644
index 000000000..ae7ad85d7
--- /dev/null
+++ b/util/maven-repo-dependency-diff.workbook
@@ -0,0 +1,53 @@
+---
+uti: com.xamarin.workbook
+platforms:
+- Console
+packages:
+- id: MavenNet
+ version: 1.0.5
+---
+
+```csharp
+#r "MavenNet"
+using MavenNet;
+```
+
+```csharp
+const string MAVEN_REPO = "../externals/m2repository/";
+const string OLD_VER = "10.0.1";
+const string NEW_VER = "10.2.1";
+```
+
+```csharp
+var repo = MavenNet.MavenRepository.OpenDirectory (MAVEN_REPO);
+await repo.LoadMetadataAsync ();
+
+foreach (var item in repo.Metadata) {
+
+ var oldProj = await repo.GetProjectAsync (item.GroupId, item.ArtifactId, OLD_VER);
+ var newProj = await repo.GetProjectAsync (item.GroupId, item.ArtifactId, NEW_VER);
+
+ if (oldProj == null && newProj == null)
+ continue;
+ if (newProj == null) {
+ Console.WriteLine (item.ArtifactId + " -> Removed");
+ continue;
+ }
+ if (oldProj == null) {
+ Console.WriteLine (item.ArtifactId + " -> Added");
+ continue;
+ }
+
+ var removedDeps = oldProj.Dependencies.Where (od => !newProj.Dependencies.Any (nd => nd.GroupId == od.GroupId && nd.ArtifactId == od.ArtifactId));
+ var addedDeps = newProj.Dependencies.Where (od => !oldProj.Dependencies.Any (nd => nd.GroupId == od.GroupId && nd.ArtifactId == od.ArtifactId));
+
+ if (removedDeps.Any () || addedDeps.Any ())
+ Console.WriteLine (item.ArtifactId + " dependencies changed!");
+
+ foreach (var rm in removedDeps)
+ Console.WriteLine ($"-> Removed: {rm.ArtifactId}");
+
+ foreach (var ad in addedDeps)
+ Console.WriteLine ($"-> Added: {ad.ArtifactId}");
+}
+```
\ No newline at end of file