コード例 #1
0
        /// <summary>
        /// Initializes the <see cref="GooglePlayGames.BackgroundResolution"/> class.
        /// </summary>
        static BackgroundResolution()
        {
            svcSupport = PlayServicesSupport.CreateInstance(
                "Google.GPGS",
                EditorPrefs.GetString("AndroidSdkRoot"),
                "ProjectSettings");

            AddDependencies();
        }
コード例 #2
0
        public void TestNonActiveClient()
        {
            PlayServicesSupport client1 = TestData.CreateInstance(instanceName: "client1");
            PlayServicesSupport client2 = TestData.CreateInstance(instanceName: "client2");

            client1.DependOn(TestData.PackageId.Artifact, "1+");
            client2.DependOn(TestData.PackageId.SubDep, "1.1.0");

            // now make a third client with no dependencies and make sure it
            // sees client1 & 2
            PlayServicesSupport client3 = TestData.CreateInstance(instanceName: "client3");

            // now check that client 2 sees them also
            Dictionary <string, Dependency> deps = client3.ResolveDependencies(true);

            Assert.NotNull(deps);
            Dependency d = deps[TestData.PackageId.Artifact.VersionlessKey()];

            Assert.AreEqual(TestData.PackageId.Artifact.Info().bestVersion, d.BestVersion);

            d = deps[TestData.PackageId.SubDep.VersionlessKey()];
            Assert.AreEqual("1.1.0", d.BestVersion);
        }
コード例 #3
0
        /// <summary>
        /// Find a tool in the Android SDK.
        /// </summary>
        /// <param name="svcSupport">PlayServicesSupport instance used to retrieve the SDK
        /// path. </param>
        /// <param name="toolName">Name of the tool to search for.</param>
        /// <returns>String with the path to the tool if found, null otherwise.</returns>
        internal static string FindAndroidSdkTool(PlayServicesSupport svcSupport, string toolName)
        {
            string toolPath = null;
            string sdkPath  = svcSupport.SDK;

            if (sdkPath == null || sdkPath == "")
            {
                Debug.LogWarning(PlayServicesSupport.AndroidSdkConfigurationError +
                                 "  Will fallback to searching for " + toolName +
                                 " in the system path.");
            }
            else
            {
                toolPath = Path.Combine(
                    sdkPath, Path.Combine(
                        "tools", toolName + CommandLine.GetExecutableExtension()));
            }
            if (toolPath == null || !File.Exists(toolPath))
            {
                toolPath = CommandLine.FindExecutable(toolName);
            }
            return(toolPath);
        }
コード例 #4
0
        public void TestUseLatest()
        {
            PlayServicesSupport support = PlayServicesSupport.CreateInstance(
                "testInstance",
                "../../testData",
                Path.GetTempPath());

            Assert.True(Directory.Exists(support.SDK));

            support.DependOn("test", "artifact", "1+");
            support.DependOn("test", "subdep", "1.1.0");
            support.DependOn("test", "transdep", "LATEST");

            Dictionary <string, Dependency> deps =
                support.ResolveDependencies(true);

            Assert.NotNull(deps);
            Dependency d = deps["test:artifact"];

            Assert.True(d.BestVersion == "8.1.0");
            d = deps["test:subdep"];
            Assert.True(d.BestVersion == "1.1.0");
        }
コード例 #5
0
        public void TestCustomRepoPath()
        {
            string[]            repos   = { Path.Combine(TestData.PATH, "extras/google/m2repository") };
            PlayServicesSupport support = TestData.CreateInstance(
                sdkPath: "..", additionalRepositories: repos);

            Assert.True(Directory.Exists(support.SDK));

            support.ClearDependencies();
            support.DependOn(TestData.PackageId.Artifact, "LATEST");

            Dictionary <string, Dependency> deps = support.ResolveDependencies(false);

            Assert.NotNull(deps);

            // Verify one dependency is returned at the expected version.
            Assert.AreEqual(1, deps.Count);
            IEnumerator <Dependency> iter = deps.Values.GetEnumerator();

            iter.MoveNext();
            Assert.AreEqual(TestData.PackageId.Artifact.Info().bestVersion,
                            iter.Current.BestVersion);
        }
コード例 #6
0
        public void TestNonActiveClient()
        {
            PlayServicesSupport client1 = PlayServicesSupport.CreateInstance(
                "client1",
                "../../testData",
                Path.GetTempPath());

            PlayServicesSupport client2 = PlayServicesSupport.CreateInstance(
                "client2",
                "../../testData",
                Path.GetTempPath());

            client1.ResetDependencies();
            client2.ResetDependencies();

            client1.DependOn("test", "artifact", "1+");
            client2.DependOn("test", "subdep", "1.1.0");

            // now make a third client with no dependencies and make sure it
            // sees client1 & 2
            PlayServicesSupport client3 = PlayServicesSupport.CreateInstance(
                "client3",
                "../../testData",
                Path.GetTempPath());

            // now check that client 2 sees them also
            Dictionary <string, Dependency> deps =
                client3.ResolveDependencies(true);

            Assert.NotNull(deps);
            Dependency d = deps["test:artifact"];

            Assert.True(d.BestVersion == "8.1.0");

            d = deps["test:subdep"];
            Assert.True(d.BestVersion == "1.1.0");
        }
コード例 #7
0
        /// <summary>
        /// Perform the resolution and the exploding/cleanup as needed.
        /// </summary>
        public override void DoResolution(PlayServicesSupport svcSupport,
                                          string destinationDirectory,
                                          PlayServicesSupport.OverwriteConfirmation handleOverwriteConfirmation)
        {
            // Get the collection of dependencies that need to be copied.
            Dictionary <string, Dependency> deps;

            try {
                deps = svcSupport.ResolveDependencies(true);
            } catch (ResolutionException) {
                return;
            }

            // Copy the list
            svcSupport.CopyDependencies(deps,
                                        destinationDirectory,
                                        handleOverwriteConfirmation);

            // we want to look at all the .aars to decide to explode or not.
            // Some aars have variables in their AndroidManifest.xml file,
            // e.g. ${applicationId}.  Unity does not understand how to process
            // these, so we handle it here.
            ProcessAars(destinationDirectory);
        }
コード例 #8
0
        /// <summary>
        /// Find a tool in the Android SDK.
        /// </summary>
        /// <param name="toolName">Name of the tool to search for.</param>
        /// <param name="sdkPath">SDK path to search for the tool.  If this is null or empty, the
        // system path is searched instead.</param>
        /// <returns>String with the path to the tool if found, null otherwise.</returns>
        private static string FindAndroidSdkTool(string toolName, string sdkPath = null)
        {
            if (String.IsNullOrEmpty(sdkPath))
            {
                PlayServicesSupport.Log(String.Format(
                                            "{0}\n" +
                                            "Falling back to searching for the Android SDK tool {1} in the system path.",
                                            PlayServicesSupport.AndroidSdkConfigurationError, toolName));
            }
            else
            {
                var extensions = new List <string> {
                    CommandLine.GetExecutableExtension()
                };
                if (UnityEngine.RuntimePlatform.WindowsEditor ==
                    UnityEngine.Application.platform)
                {
                    extensions.AddRange(new [] { ".bat", ".cmd" });
                }
                foreach (var dir in new [] { "tools", Path.Combine("tools", "bin") })
                {
                    foreach (var extension in extensions)
                    {
                        var currentPath = Path.Combine(sdkPath,
                                                       Path.Combine(dir, toolName + extension));
                        if (File.Exists(currentPath))
                        {
                            return(currentPath);
                        }
                    }
                }
            }
            var toolPath = CommandLine.FindExecutable(toolName);

            return(toolPath != null && File.Exists(toolPath) ? toolPath : null);
        }
コード例 #9
0
        public void TestSimpleResolveDependencies()
        {
            PlayServicesSupport support = PlayServicesSupport.CreateInstance(
                "testInstance",
                "../../testData",
                Path.GetTempPath());

            Assert.True(Directory.Exists(support.SDK));

            // happy path
            support.ResetDependencies();
            support.DependOn("test", "artifact", "LATEST");

            Dictionary <string, Dependency> deps = support.ResolveDependencies(false);

            Assert.NotNull(deps);

            // should be only 1 and version 8.1
            Assert.True(deps.Count == 1);
            IEnumerator <Dependency> iter = deps.Values.GetEnumerator();

            iter.MoveNext();
            Assert.True(iter.Current.BestVersion == "8.1.0");
        }
コード例 #10
0
 /// <summary>
 /// Processes the aars.
 /// </summary>
 /// <remarks>Each aar copied is inspected and determined if it should be
 /// exploded into a directory or not. Unneeded exploded directories are
 /// removed.
 /// <para>
 /// Exploding is needed if the version of Unity is old, or if the artifact
 /// has been explicitly flagged for exploding.  This allows the subsequent
 /// processing of variables in the AndroidManifest.xml file which is not
 /// supported by the current versions of the manifest merging process that
 /// Unity uses.
 /// </para>
 /// <param name="dir">The directory to process.</param>
 void ProcessAars(string dir)
 {
     string[] files = Directory.GetFiles(dir, "*.aar");
     foreach (string f in files)
     {
         string dirPath    = Path.Combine(dir, Path.GetFileNameWithoutExtension(f));
         string targetPath = Path.Combine(dir, Path.GetFileName(f));
         if (ShouldExplode(f))
         {
             ReplaceVariables(ProcessAar(Path.GetFullPath(dir), f));
             targetPath = dirPath;
         }
         else
         {
             // Clean up previously expanded / exploded versions of the AAR.
             if (Directory.Exists(dirPath))
             {
                 PlayServicesSupport.DeleteExistingFileOrDirectory(dirPath);
             }
         }
         aarExplodeData[f].path     = targetPath;
         aarExplodeData[f].bundleId = PlayerSettings.bundleIdentifier;
     }
 }
コード例 #11
0
        public void TestLatestResolution()
        {
            PlayServicesSupport client1 = PlayServicesSupport.CreateInstance(
                "client1",
                "../../testData",
                Path.GetTempPath());

            client1.ResetDependencies();

            //trans dep needs subdep 0.9
            client1.DependOn("test", "transdep", "1.0.0");

            // so top level require subdep 1.0 or greater
            client1.DependOn("test", "subdep", "1.0+");

            Dictionary <string, Dependency> deps = null;
            // this should fail since we need 0.9 and 1.1.0

            ResolutionException ex = null;

            try
            {
                deps = client1.ResolveDependencies(false);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }

            Assert.NotNull(ex, "Expected exception, but got none");

            // now try with useLatest == true, should have no exception
            ex = null;
            try
            {
                deps = client1.ResolveDependencies(true);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }
            Assert.Null(ex, "unexpected exception");

            Assert.NotNull(deps);

            Assert.IsTrue(deps.Count == 2, "Expected 2 dependencies, got " + deps.Count);

            // now check that that all the dependencies have the correct
            // best version
            Dependency d = deps["test:transdep"];

            Assert.NotNull(d, "could not find transdep");
            Assert.IsTrue(d.BestVersion == "1.0.0", "Expected version 1.0.0, got " + d.BestVersion);

            d = deps["test:subdep"];
            Assert.NotNull(d, "could not find subdep");
            Assert.IsTrue(d.BestVersion == "1.1.0", "Expected version 1.1.0, got " + d.BestVersion);

            // try without wildcard
            client1.ResetDependencies();

            //trans dep needs subdep 0.9
            client1.DependOn("test", "transdep", "1.0.0");

            // so top level requires exactly subdep 1.1.0.
            client1.DependOn("test", "subdep", "1.1.0");

            ex = null;
            try
            {
                deps = client1.ResolveDependencies(false);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }

            Assert.NotNull(ex, "Expected exception, but got none");

            ex = null;
            try
            {
                deps = client1.ResolveDependencies(true);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }
            Assert.Null(ex, "unexpected exception");

            Assert.NotNull(deps);

            Assert.IsTrue(deps.Count == 2, "Expected 2 dependencies, got " + deps.Count);

            // now check that that all the dependencies have the correct
            // best version
            d = deps["test:transdep"];
            Assert.NotNull(d, "could not find transdep");
            Assert.IsTrue(d.BestVersion == "1.0.0", "Expected version 1.0.0, got " + d.BestVersion);

            d = deps["test:subdep"];
            Assert.NotNull(d, "could not find subdep");
            Assert.IsTrue(d.BestVersion == "1.1.0", "Expected version 1.1.0, got " + d.BestVersion);
        }
コード例 #12
0
        /// <summary>
        /// Determined whether an aar file should be exploded (extracted).
        ///
        /// This is required for some aars so that the Unity Jar Resolver can perform variable
        /// expansion on manifests in the package before they're merged by aapt.
        /// </summary>
        /// <returns><c>true</c>, if the aar should be exploded, <c>false</c> otherwise.</returns>
        /// <param name="aarFile">The aar file.</param>
        internal virtual bool ShouldExplode(string aarFile)
        {
            AarExplodeData aarData = null;

            if (!aarExplodeData.TryGetValue(aarFile, out aarData))
            {
                aarData = new AarExplodeData();
            }
            bool explosionEnabled = true;

            // Unfortunately, as of Unity 5.5.0f3, Unity does not set the applicationId variable
            // in the build.gradle it generates.  This results in non-functional libraries that
            // require the ${applicationId} variable to be expanded in their AndroidManifest.xml.
            // To work around this when Gradle builds are enabled, explosion is enabled for all
            // AARs that require variable expansion unless this behavior is explicitly disabled
            // in the settings dialog.
            if (PlayServicesResolver.GradleBuildEnabled &&
                PlayServicesResolver.ProjectExportEnabled &&
                !SettingsDialog.ExplodeAars)
            {
                explosionEnabled = false;
            }
            bool explode = false;

            if (explosionEnabled)
            {
                explode = !SupportsAarFiles;
                if (!explode)
                {
                    System.DateTime modificationTime = File.GetLastWriteTime(aarFile);
                    if (modificationTime.CompareTo(aarData.modificationTime) <= 0)
                    {
                        explode = aarData.explode;
                    }
                }
                if (!explode)
                {
                    string temporaryDirectory = CreateTemporaryDirectory();
                    if (temporaryDirectory == null)
                    {
                        return(false);
                    }
                    string manifestFilename = "AndroidManifest.xml";
                    try
                    {
                        if (ExtractAar(aarFile, new string[] { manifestFilename },
                                       temporaryDirectory))
                        {
                            string manifestPath = Path.Combine(temporaryDirectory,
                                                               manifestFilename);
                            if (File.Exists(manifestPath))
                            {
                                string manifest = File.ReadAllText(manifestPath);
                                explode = manifest.IndexOf("${applicationId}") >= 0;
                            }
                            aarData.modificationTime = File.GetLastWriteTime(aarFile);
                        }
                    }
                    catch (System.Exception e)
                    {
                        Debug.Log("Unable to examine AAR file " + aarFile + ", err: " + e);
                        throw e;
                    }
                    finally
                    {
                        PlayServicesSupport.DeleteExistingFileOrDirectory(temporaryDirectory);
                    }
                }
            }
            aarData.explode         = explode;
            aarExplodeData[aarFile] = aarData;
            return(explode);
        }
コード例 #13
0
        // Implementation of OnPostProcessUpdateProjectDeps().
        // NOTE: This is separate from the post-processing method to prevent the
        // Mono runtime from loading the Xcode API before calling the post
        // processing step.
        public static void UpdateProjectDeps(
            BuildTarget buildTarget, string pathToBuiltProject)
        {
            // If the Pods directory does not exist, the pod download step
            // failed.
            var podsDir = Path.Combine(pathToBuiltProject, PODS_DIR);

            if (!Directory.Exists(podsDir))
            {
                return;
            }

            Directory.CreateDirectory(Path.Combine(pathToBuiltProject,
                                                   "Frameworks"));
            Directory.CreateDirectory(Path.Combine(pathToBuiltProject,
                                                   "Resources"));

            string pbxprojPath = GetProjectPath(pathToBuiltProject);
            var    project     = new UnityEditor.iOS.Xcode.PBXProject();

            project.ReadFromString(File.ReadAllText(pbxprojPath));
            string target = project.TargetGuidByName(TARGET_NAME);

            HashSet <string> frameworks = new HashSet <string>();
            HashSet <string> linkFlags  = new HashSet <string>();

            foreach (var frameworkFullPath in
                     Directory.GetDirectories(podsDir, "*.framework",
                                              SearchOption.AllDirectories))
            {
                string frameworkName     = new DirectoryInfo(frameworkFullPath).Name;
                string destFrameworkPath = Path.Combine("Frameworks",
                                                        frameworkName);
                string destFrameworkFullPath = Path.Combine(pathToBuiltProject,
                                                            destFrameworkPath);
                // Only move this framework if it contains a library.
                // Skip frameworks that consist of just resources, they're handled
                // in a separate import step.
                if (!File.Exists(Path.Combine(
                                     frameworkFullPath,
                                     Path.GetFileName(frameworkFullPath)
                                     .Replace(".framework", ""))))
                {
                    continue;
                }

                PlayServicesSupport.DeleteExistingFileOrDirectory(
                    destFrameworkFullPath);
                Directory.Move(frameworkFullPath, destFrameworkFullPath);
                project.AddFileToBuild(
                    target,
                    project.AddFile(destFrameworkPath,
                                    destFrameworkPath,
                                    UnityEditor.iOS.Xcode.PBXSourceTree.Source));

                string moduleMapPath =
                    Path.Combine(Path.Combine(destFrameworkFullPath, "Modules"),
                                 "module.modulemap");

                if (File.Exists(moduleMapPath))
                {
                    // Parse the modulemap, format spec here:
                    // http://clang.llvm.org/docs/Modules.html#module-map-language
                    using (StreamReader moduleMapFile =
                               new StreamReader(moduleMapPath)) {
                        string line;
                        char[] delim = { ' ' };
                        while ((line = moduleMapFile.ReadLine()) != null)
                        {
                            string[] items = line.TrimStart(delim).Split(delim, 2);
                            if (items.Length > 1)
                            {
                                if (items[0] == "link")
                                {
                                    if (items[1].StartsWith("framework"))
                                    {
                                        items = items[1].Split(delim, 2);
                                        frameworks.Add(items[1].Trim(
                                                           new char[] { '\"' }) + ".framework");
                                    }
                                    else
                                    {
                                        linkFlags.Add("-l" + items[1]);
                                    }
                                }
                            }
                        }
                    }
                }

                string resourcesFolder = Path.Combine(destFrameworkFullPath,
                                                      "Resources");
                if (Directory.Exists(resourcesFolder))
                {
                    string[] resFiles   = Directory.GetFiles(resourcesFolder);
                    string[] resFolders =
                        Directory.GetDirectories(resourcesFolder);
                    foreach (var resFile in resFiles)
                    {
                        string destFile = Path.Combine("Resources",
                                                       Path.GetFileName(resFile));
                        File.Copy(resFile, Path.Combine(pathToBuiltProject,
                                                        destFile), true);
                        project.AddFileToBuild(
                            target, project.AddFile(
                                destFile, destFile,
                                UnityEditor.iOS.Xcode.PBXSourceTree.Source));
                    }
                    foreach (var resFolder in resFolders)
                    {
                        string destFolder =
                            Path.Combine("Resources",
                                         new DirectoryInfo(resFolder).Name);
                        string destFolderFullPath =
                            Path.Combine(pathToBuiltProject, destFolder);
                        PlayServicesSupport.DeleteExistingFileOrDirectory(
                            destFolderFullPath);
                        Directory.Move(resFolder, destFolderFullPath);
                        project.AddFileToBuild(
                            target, project.AddFile(
                                destFolder, destFolder,
                                UnityEditor.iOS.Xcode.PBXSourceTree.Source));
                    }
                }
            }

            foreach (var framework in frameworks)
            {
                project.AddFrameworkToProject(target, framework, false);
            }
            foreach (var linkFlag in linkFlags)
            {
                project.AddBuildProperty(target, "OTHER_LDFLAGS", linkFlag);
            }

            // Add all source files found under the pods directory to the project.
            // This is a very crude way of partially supporting source pods.
            var podPathToProjectPaths = new Dictionary <string, string>();

            // Find pod source files and map them to paths relative to the target
            // Xcode project.
            foreach (var filename in
                     FindFilesWithExtensions(podsDir, SOURCE_FILE_EXTENSIONS))
            {
                // Save the path relative to the target project for each path
                // relative to the generated pods Xcode project.
                // +1 in the following expressions to strip the file separator.
                podPathToProjectPaths[filename.Substring(podsDir.Length + 1)] =
                    filename.Substring(pathToBuiltProject.Length + 1);
            }
            // Add a reference to each source file in the target project.
            foreach (var podPathProjectPath in podPathToProjectPaths)
            {
                project.AddFileToBuild(
                    target,
                    project.AddFile(podPathProjectPath.Value,
                                    podPathProjectPath.Value,
                                    UnityEditor.iOS.Xcode.PBXSourceTree.Source));
            }

            // Attempt to read per-file compile / build settings from the Pods
            // project.
            var podsProjectPath = GetProjectPath(podsDir, PODS_PROJECT_NAME);
            var podsProject     = new UnityEditor.iOS.Xcode.PBXProject();

            podsProject.ReadFromString(File.ReadAllText(podsProjectPath));
            foreach (var directory in Directory.GetDirectories(podsDir))
            {
                // Each pod will have a top level directory under the pods dir
                // named after the pod.  Also, some pods have build targets in the
                // xcode project where each build target has the same name as the
                // pod such that pod Foo is in directory Foo with build target Foo.
                // Since we can't read the build targets from the generated Xcode
                // project using Unity's API, we scan the Xcode project for targets
                // to optionally retrieve build settings for each source file
                // the settings can be applied in the target project.
                var podTargetName = Path.GetFileName(directory);
                var podTargetGuid = podsProject.TargetGuidByName(podTargetName);
                Log(String.Format("Looking for target: {0} guid: {1}",
                                  podTargetName, podTargetGuid ?? "null"),
                    verbose: true);
                if (podTargetGuid == null)
                {
                    continue;
                }
                foreach (var podPathProjectPath in podPathToProjectPaths)
                {
                    var podSourceFileGuid = podsProject.FindFileGuidByRealPath(
                        podPathProjectPath.Key);
                    if (podSourceFileGuid == null)
                    {
                        continue;
                    }
                    var podSourceFileCompileFlags =
                        podsProject.GetCompileFlagsForFile(podTargetGuid,
                                                           podSourceFileGuid);
                    if (podSourceFileCompileFlags == null)
                    {
                        continue;
                    }
                    var targetSourceFileGuid = project.FindFileGuidByProjectPath(
                        podPathProjectPath.Value);
                    if (targetSourceFileGuid == null)
                    {
                        Log("Unable to find " + podPathProjectPath.Value +
                            " in generated project", level: LogLevel.Warning);
                        continue;
                    }
                    Log(String.Format(
                            "Setting {0} compile flags to ({1})",
                            podPathProjectPath.Key,
                            String.Join(", ",
                                        podSourceFileCompileFlags.ToArray())),
                        verbose: true);
                    project.SetCompileFlagsForFile(target, targetSourceFileGuid,
                                                   podSourceFileCompileFlags);
                }
            }

            File.WriteAllText(pbxprojPath, project.WriteToString());
        }
コード例 #14
0
        /// <summary>
        /// Resolve dependencies.
        /// </summary>
        /// <param name="resolutionComplete">Delegate called when resolution is complete
        /// with a parameter that indicates whether it succeeded or failed.</param>
        /// <param name="forceResolution">Whether resolution should be executed when no dependencies
        /// have changed.  This is useful if a dependency specifies a wildcard in the version
        /// expression.</param>
        private static void ResolveUnsafe(Action <bool> resolutionComplete = null,
                                          bool forceResolution             = false)
        {
            JavaUtilities.CheckJdkForApiLevel();

            if (!buildConfigChanged)
            {
                DeleteFiles(Resolver.OnBuildSettings());
            }

            xmlDependencies.ReadAll(logger);

            if (forceResolution)
            {
                DeleteLabeledAssets();
            }
            else
            {
                // Only resolve if user specified dependencies changed or the output files
                // differ to what is present in the project.
                var currentState  = DependencyState.GetState();
                var previousState = DependencyState.ReadFromFile();
                if (previousState != null)
                {
                    if (currentState.Equals(previousState))
                    {
                        if (resolutionComplete != null)
                        {
                            resolutionComplete(true);
                        }
                        return;
                    }
                    // Delete all labeled assets to make sure we don't leave any stale transitive
                    // dependencies in the project.
                    DeleteLabeledAssets();
                }
            }

            System.IO.Directory.CreateDirectory(GooglePlayServices.SettingsDialog.PackageDir);
            PlayServicesSupport.Log("Resolving...", verbose: true);

            lastError = "";
            Resolver.DoResolution(svcSupport, GooglePlayServices.SettingsDialog.PackageDir,
                                  (oldDependency, newDependency) => {
                return(Resolver.ShouldReplaceDependency(oldDependency,
                                                        newDependency));
            },
                                  () => {
                System.Action complete = () => {
                    bool succeeded = String.IsNullOrEmpty(lastError);
                    AssetDatabase.Refresh();
                    DependencyState.GetState().WriteToFile();
                    PlayServicesSupport.Log(String.Format(
                                                "Resolution {0}.\n\n{1}",
                                                succeeded ? "Succeeded" : "Failed",
                                                lastError), verbose: true);
                    if (resolutionComplete != null)
                    {
                        resolutionComplete(succeeded);
                    }
                };
                updateQueue.Enqueue(complete);
            });
        }
 /// <summary>
 /// Programmatically add dependencies.
 /// NOTE: This is the deprecated way of adding dependencies and will likely be removed in
 /// future.
 /// </summary>
 private static void SetupDependencies()
 {
     PlayServicesSupport.CreateInstance("Test", null, "ProjectSettings").DependOn(
         "com.google.firebase", "firebase-common", "16.0.0");
 }
コード例 #16
0
        // Private method to avoid too deeply nested code in "DoResolution".
        private void GradleResolve(AndroidSdkPackageCollection packages,
                                   PlayServicesSupport svcSupport, string destinationDirectory,
                                   System.Action resolutionComplete)
        {
            string errorOutro = "make sure you have the latest version of this plugin and if you " +
                                "still get this error, report it in a a bug here:\n" +
                                "https://github.com/googlesamples/unity-jar-resolver/issues\n";
            string errorIntro = null;

            int    targetSdkVersion  = UnityCompat.GetAndroidTargetSDKVersion();
            string buildToolsVersion = null;

            if (targetSdkVersion < 0)
            {
                // A value of -1 means the targetSDK Version enum returned "Auto"
                // instead of an actual version, so it's up to us to actually figure it out.
                targetSdkVersion = GetLatestInstalledAndroidPlatformVersion(packages);
                PlayServicesResolver.Log(
                    String.Format("TargetSDK is set to Auto-detect, and the latest Platform has " +
                                  "been detected as: android-{0}", targetSdkVersion),
                    level: LogLevel.Verbose);

                errorIntro = String.Format("The Target SDK is set to automatically pick the highest " +
                                           "installed platform in the Android Player Settings, which appears to be " +
                                           "\"android-{0}\". This requires build-tools with at least the same version, " +
                                           "however ", targetSdkVersion);
            }
            else
            {
                errorIntro = String.Format("The target SDK version is set in the Android Player " +
                                           "Settings to \"android-{0}\" which requires build tools with " +
                                           "at least the same version, however ", targetSdkVersion);
            }

            // You can use a higher version of the build-tools than your compileSdkVersion, in order
            // to pick up new/better compiler while not changing what you build your app against. --Xav
            // https://stackoverflow.com/a/24523113
            // Implicitly Xav is also saying, you can't use a build tool version less than the
            // platform level you're building. This is backed up from testing.
            if (targetSdkVersion > TESTED_BUILD_TOOLS_VERSION_MAJOR)
            {
                buildToolsVersion = GetLatestMinorBuildToolsVersion(packages, targetSdkVersion);

                if (buildToolsVersion == null)
                {
                    PlayServicesResolver.Log(
                        errorIntro + String.Format("no build-tools are available " +
                                                   "at this level in the sdk manager. This plugin has been tested with " +
                                                   "platforms up to android-{0} using build-tools {0}.{1}.{2}. You can try " +
                                                   "selecting a lower targetSdkVersion in the Android Player Settings.  Please ",
                                                   TESTED_BUILD_TOOLS_VERSION_MAJOR, TESTED_BUILD_TOOLS_VERSION_MINOR,
                                                   TESTED_BUILD_TOOLS_VERSION_REV) + errorOutro,
                        level: LogLevel.Error);
                    return;
                }
                else
                {
                    PlayServicesResolver.Log(
                        errorIntro + String.Format("this plugin has only been " +
                                                   "tested with build-tools up to version {0}.{1}.{2}. Corresponding " +
                                                   "build-tools version {3} will be used, however this is untested with this " +
                                                   "plugin and MAY NOT WORK! If you have trouble, please select a target SDK " +
                                                   "version at or below \"android-{0}\". If you need to get this working with " +
                                                   "the latest platform, please ",
                                                   TESTED_BUILD_TOOLS_VERSION_MAJOR,
                                                   TESTED_BUILD_TOOLS_VERSION_MINOR,
                                                   TESTED_BUILD_TOOLS_VERSION_REV,
                                                   buildToolsVersion) + errorOutro, level: LogLevel.Warning);
                }
            }

            if (buildToolsVersion == null)
            {
                // Use the tested build tools version, which we know will be able to handle
                // this targetSDK version.
                buildToolsVersion = String.Format("{0}.{1}.{2}", TESTED_BUILD_TOOLS_VERSION_MAJOR,
                                                  TESTED_BUILD_TOOLS_VERSION_MINOR,
                                                  TESTED_BUILD_TOOLS_VERSION_REV);
                // We don't have to bother with checking if it's installed because gradle actually
                // does that for us.
            }

            string minSdkVersion = UnityCompat.GetAndroidMinSDKVersion().ToString();

            var config = new Dictionary <string, string>()
            {
                { "app_id", UnityCompat.ApplicationId },
                { "sdk_version", targetSdkVersion.ToString() },
                { "min_sdk_version", minSdkVersion },
                { "build_tools_version", buildToolsVersion },
                { "android_sdk_dir", svcSupport.SDK }
            };

            // This creates an enumerable of strings with the json lines for each dep like this:
            // "[\"namespace\", \"package\", \"version\"]"
            var dependencies = PlayServicesSupport.GetAllDependencies();
            var depLines     = from d in dependencies
                               select "[" + ToJSONList(DepsVersionAsArray(d.Value)) + "]";
            // Get a flattened list of dependencies, excluding any with the "$SDK" path variable,
            // since those will automatically be included in the gradle build.
            var repoLines = new HashSet <string>(
                dependencies.SelectMany(d => d.Value.Repositories)
                .Where(s => !s.Contains(PlayServicesSupport.SdkVariable)));

            var proguard_config_paths = new List <string>()
            {
                Path.Combine(GRADLE_SCRIPT_LOCATION, PROGUARD_UNITY_CONFIG),
                Path.Combine(GRADLE_SCRIPT_LOCATION, PROGUARD_MSG_FIX_CONFIG)
            };

            // Build the full json config as a string.
            string json_config = @"{{
""config"": {{
{0}
}},
""project_deps"": [
{1}
],
""extra_m2repositories"": [
{2}
],
""extra_proguard_configs"": [
{3}
]
}}";

            json_config = String.Format(json_config, ToJSONDictionary(config),
                                        ToJSONList(depLines, ",\n", 4, true),
                                        ToJSONList(repoLines, ",\n", 4),
                                        ToJSONList(proguard_config_paths, ",\n", 4));

            // Escape any literal backslashes (such as those from paths on windows), since we want to
            // preserve them when reading the config as backslashes and not interpret them
            // as escape characters.
            json_config = json_config.Replace(@"\", @"\\");

            System.IO.File.WriteAllText(GENERATE_CONFIG_PATH, json_config);
            var outDir = Path.Combine(destinationDirectory, GENERATE_GRADLE_OUTPUT_DIR);

            RunGenGradleScript(
                " -c \"" + GENERATE_CONFIG_PATH + "\"" +
                " -b \"" + GENERATE_GRADLE_BUILD_PATH + "\"" +
                " -o \"" + outDir + "\"",
                (result) => {
                if (result.exitCode == 0)
                {
                    var currentAbi = PlayServicesResolver.AndroidTargetDeviceAbi;
                    var activeAbis = GetSelectedABIDirs(currentAbi);
                    var libsDir    = Path.Combine(outDir, "libs");
                    if (Directory.Exists(libsDir))
                    {
                        foreach (var directory in Directory.GetDirectories(libsDir))
                        {
                            var abiDir = Path.GetFileName(directory).ToLower();
                            if (!activeAbis.Contains(abiDir))
                            {
                                FileUtils.DeleteExistingFileOrDirectory(directory);
                            }
                        }
                    }
                    if (Directory.Exists(outDir))
                    {
                        PlayServicesResolver.LabelAssets(new [] { outDir }, true, true);
                    }
                    AssetDatabase.Refresh();
                    resolutionComplete();
                }
            });
        }
コード例 #17
0
        /// <summary>
        /// Does the resolution of the play-services aars.
        /// </summary>
        /// <param name="svcSupport">Svc support.</param>
        /// <param name="destinationDirectory">Destination directory.</param>
        /// <param name="handleOverwriteConfirmation">Handle overwrite confirmation.</param>
        /// <param name="resolutionComplete">Delegate called when resolution is complete.</param>
        public override void DoResolution(PlayServicesSupport svcSupport, string destinationDirectory,
                                          PlayServicesSupport.OverwriteConfirmation handleOverwriteConfirmation,
                                          System.Action resolutionComplete)
        {
            string targetSdkVersion  = UnityCompat.GetAndroidPlatform().ToString();
            string minSdkVersion     = UnityCompat.GetAndroidMinSDKVersion().ToString();
            string buildToolsVersion = UnityCompat.GetAndroidBuildToolsVersion();

            var config = new Dictionary <string, string>()
            {
                { "app_id", UnityCompat.ApplicationId },
                { "sdk_version", targetSdkVersion },
                { "min_sdk_version", minSdkVersion },
                { "build_tools_version", buildToolsVersion },
                { "android_sdk_dir", svcSupport.SDK }
            };

            // This creates an enumerable of strings with the json lines for each dep like this:
            // "[\"namespace\", \"package\", \"version\"]"
            var dependencies = svcSupport.LoadDependencies(true, true, false);
            var depLines     = from d in dependencies
                               select "[" + ToJSONList(DepsVersionAsArray(d.Value)) + "]";
            // Get a flattened list of dependencies, excluding any with the "$SDK" path variable,
            // since those will automatically be included in the gradle build.
            var repoLines = new HashSet <string>(
                dependencies.SelectMany(d => d.Value.Repositories)
                .Where(s => !s.Contains(PlayServicesSupport.SdkVariable)));

            var proguard_config_paths = new List <string>()
            {
                Path.Combine(GRADLE_SCRIPT_LOCATION, PROGUARD_UNITY_CONFIG),
                Path.Combine(GRADLE_SCRIPT_LOCATION, PROGUARD_MSG_FIX_CONFIG)
            };

            // Build the full json config as a string.
            string json_config = @"{{
""config"": {{
{0}
}},
""project_deps"": [
{1}
],
""extra_m2repositories"": [
{2}
],
""extra_proguard_configs"": [
{3}
]
}}";

            json_config = String.Format(json_config, ToJSONDictionary(config),
                                        ToJSONList(depLines, ",\n", 4, true),
                                        ToJSONList(repoLines, ",\n", 4),
                                        ToJSONList(proguard_config_paths, ",\n", 4));

            System.IO.File.WriteAllText(GENERATE_CONFIG_PATH, json_config);

            RunGenGradleScript(
                " -c \"" + GENERATE_CONFIG_PATH + "\"" +
                " -b \"" + GENERATE_GRADLE_BUILD_PATH + "\"" +
                " -o \"" + Path.Combine(destinationDirectory, GENERATE_GRADLE_OUTPUT_DIR) + "\"");
        }
コード例 #18
0
        /// <summary>
        /// Perform the resolution and the exploding/cleanup as needed.
        /// </summary>
        public override void DoResolution(
            PlayServicesSupport svcSupport, string destinationDirectory,
            PlayServicesSupport.OverwriteConfirmation handleOverwriteConfirmation,
            System.Action resolutionComplete)
        {
            System.Action resolve = () => {
                DoResolutionNoAndroidPackageChecks(svcSupport, destinationDirectory,
                                                   handleOverwriteConfirmation);
                resolutionComplete();
            };

            // Set of packages that need to be installed.
            Dictionary <string, bool> installPackages = new Dictionary <string, bool>();
            // Retrieve the set of required packages and whether they're installed.
            Dictionary <string, Dictionary <string, bool> > requiredPackages =
                new Dictionary <string, Dictionary <string, bool> >();

            foreach (Dependency dependency in
                     svcSupport.LoadDependencies(true, keepMissing: true).Values)
            {
                if (dependency.PackageIds != null)
                {
                    foreach (string packageId in dependency.PackageIds)
                    {
                        Dictionary <string, bool> dependencySet;
                        if (!requiredPackages.TryGetValue(packageId, out dependencySet))
                        {
                            dependencySet = new Dictionary <string, bool>();
                        }
                        dependencySet[dependency.Key] = false;
                        requiredPackages[packageId]   = dependencySet;
                        // If the dependency is missing, add it to the set that needs to be
                        // installed.
                        if (System.String.IsNullOrEmpty(dependency.BestVersionPath))
                        {
                            installPackages[packageId] = false;
                        }
                    }
                }
            }

            // If no packages need to be installed or Android SDK package installation is disabled.
            if (installPackages.Count == 0 || !AndroidPackageInstallationEnabled())
            {
                // Report missing packages as warnings and try to resolve anyway.
                foreach (string pkg in requiredPackages.Keys)
                {
                    string depString = System.String.Join(
                        ", ", CollectionToArray(requiredPackages[pkg].Keys));
                    if (installPackages.ContainsKey(pkg) && depString.Length > 0)
                    {
                        Debug.LogWarning(pkg + " not installed or out of date!  This is " +
                                         "required by the following dependencies " + depString);
                    }
                }
                // Attempt resolution.
                resolve();
                return;
            }

            // Find the Android SDK manager.
            string sdkPath     = svcSupport.SDK;
            string androidTool = FindAndroidSdkTool(svcSupport, "android");

            if (androidTool == null || sdkPath == null || sdkPath == "")
            {
                Debug.LogError("Unable to find the Android SDK manager tool.  " +
                               "Required Android packages (" +
                               System.String.Join(", ", CollectionToArray(installPackages.Keys)) +
                               ") can not be installed.  " +
                               PlayServicesSupport.AndroidSdkConfigurationError);
                return;
            }

            // Get the set of available and installed packages.
            GetAvailablePackages(
                androidTool, svcSupport,
                (Dictionary <string, bool> packageInfo) => {
                if (packageInfo == null)
                {
                    return;
                }

                // Filter the set of packages to install by what is available.
                foreach (string pkg in requiredPackages.Keys)
                {
                    bool installed   = false;
                    string depString = System.String.Join(
                        ", ", CollectionToArray(requiredPackages[pkg].Keys));
                    if (packageInfo.TryGetValue(pkg, out installed))
                    {
                        if (!installed)
                        {
                            installPackages[pkg] = false;
                            Debug.LogWarning(pkg + " not installed or out of date!  " +
                                             "This is required by the following " +
                                             "dependencies " + depString);
                        }
                    }
                    else
                    {
                        Debug.LogWarning(pkg + " referenced by " + depString +
                                         " not available in the Android SDK.  This " +
                                         "package will not be installed.");
                        installPackages.Remove(pkg);
                    }
                }

                if (installPackages.Count == 0)
                {
                    resolve();
                    return;
                }

                // Start installation.
                string installPackagesString = System.String.Join(
                    ",", CollectionToArray(installPackages.Keys));
                string packagesCommand   = "update sdk -a -u -t " + installPackagesString;
                CommandLineDialog window = CommandLineDialog.CreateCommandLineDialog(
                    "Install Android SDK packages");
                window.summaryText   = "Retrieving licenses...";
                window.modal         = false;
                window.progressTitle = window.summaryText;
                window.RunAsync(
                    androidTool, packagesCommand,
                    (CommandLine.Result getLicensesResult) => {
                    // Get the start of the license text.
                    int licenseTextStart = getLicensesResult.stdout.IndexOf("--------");
                    if (getLicensesResult.exitCode != 0 || licenseTextStart < 0)
                    {
                        window.Close();
                        Debug.LogError("Unable to retrieve licenses for packages " +
                                       installPackagesString);
                        return;
                    }

                    // Remove the download output from the string.
                    string licenseText = getLicensesResult.stdout.Substring(
                        licenseTextStart);
                    window.summaryText = ("License agreement(s) required to install " +
                                          "Android SDK packages");
                    window.bodyText = licenseText;
                    window.yesText  = "agree";
                    window.noText   = "decline";
                    window.result   = false;
                    window.Repaint();
                    window.buttonClicked = (TextAreaDialog dialog) => {
                        if (!dialog.result)
                        {
                            window.Close();
                            return;
                        }

                        window.summaryText        = "Installing Android SDK packages...";
                        window.bodyText           = "";
                        window.yesText            = "";
                        window.noText             = "";
                        window.buttonClicked      = null;
                        window.progressTitle      = window.summaryText;
                        window.autoScrollToBottom = true;
                        window.Repaint();
                        // Kick off installation.
                        ((CommandLineDialog)window).RunAsync(
                            androidTool, packagesCommand,
                            (CommandLine.Result updateResult) => {
                            window.Close();
                            if (updateResult.exitCode == 0)
                            {
                                resolve();
                            }
                            else
                            {
                                Debug.LogError("Android SDK update failed.  " +
                                               updateResult.stderr + "(" +
                                               updateResult.exitCode.ToString() + ")");
                            }
                        },
                            ioHandler: (new LicenseResponder(true)).AggregateLine,
                            maxProgressLines: 500);
                    };
                },
                    ioHandler: (new LicenseResponder(false)).AggregateLine,
                    maxProgressLines: 250);
            });
        }
コード例 #19
0
        /// <summary>
        /// Registers the dependencies.
        /// </summary>
        public static void RegisterDependencies()
        {
            // Setup the resolver using reflection as the module may not be
            // available at compile time.
            Type playServicesSupport = VersionHandler.FindClass(
                "Google.JarResolver", "Google.JarResolver.PlayServicesSupport");

            if (playServicesSupport == null)
            {
                return;
            }

            if (svcSupport == null)
            {
                svcSupport = (PlayServicesSupport)VersionHandler.InvokeStaticMethod(
                    playServicesSupport, "CreateInstance",
                    new object[]
                {
                    "GooglePlayGames",
                    EditorPrefs.GetString("AndroidSdkRoot"),
                    "ProjectSettings"
                });
            }

            VersionHandler.InvokeInstanceMethod(
                svcSupport, "DependOn",
                new object[]
            {
                "com.google.android.gms", "play-services-games",
                PluginVersion.PlayServicesVersionConstraint
            },
                new Dictionary <string, object>
            {
                { "packageIds", new[] { "extra-google-m2repository" } }
            });

            VersionHandler.InvokeInstanceMethod(
                svcSupport, "DependOn",
                new object[]
            {
                "com.google.android.gms", "play-services-nearby",
                PluginVersion.PlayServicesVersionConstraint
            },
                new Dictionary <string, object>
            {
                { "packageIds", new[] { "extra-google-m2repository" } }
            });

            // Auth is needed for getting the token and email.
            VersionHandler.InvokeInstanceMethod(
                svcSupport, "DependOn",
                new object[]
            {
                "com.google.android.gms", "play-services-auth",
                PluginVersion.PlayServicesVersionConstraint
            },
                new Dictionary <string, object>
            {
                { "packageIds", new[] { "extra-google-m2repository" } }
            });

            // if google+ is needed, add it
            if (GameInfo.RequireGooglePlus())
            {
                VersionHandler.InvokeInstanceMethod(
                    svcSupport, "DependOn",
                    new object[]
                {
                    "com.google.android.gms", "play-services-plus",
                    PluginVersion.PlayServicesVersionConstraint
                },
                    new Dictionary <string, object>
                {
                    { "packageIds", new[] { "extra-google-m2repository" } }
                });
            }

            VersionHandler.InvokeInstanceMethod(
                svcSupport, "DependOn",
                new object[] { "com.android.support", "support-v4", "23.1+" },
                new Dictionary <string, object>
            {
                { "packageIds", new[] { "extra-android-m2repository" } }
            });
        }
コード例 #20
0
 /// <summary>
 /// Compatibility method for synchronous implementations of DoResolution().
 /// </summary>
 /// <param name="svcSupport">Svc support.</param>
 /// <param name="destinationDirectory">Destination directory.</param>
 public virtual void DoResolution(PlayServicesSupport svcSupport,
                                  string destinationDirectory)
 {
     DoResolution(svcSupport, destinationDirectory, () => {});
 }
コード例 #21
0
        public void TestResolveDependencies()
        {
            PlayServicesSupport support = PlayServicesSupport.CreateInstance(
                "testInstance",
                "../../testData",
                Path.GetTempPath());

            Assert.True(Directory.Exists(support.SDK));

            support.ResetDependencies();

            // happy path
            support.DependOn("test", "artifact", "LATEST");

            Dictionary <string, Dependency> deps =
                support.ResolveDependencies(false);

            Assert.NotNull(deps);

            // should be only 1 and version 8.1
            Assert.True(deps.Count == 1);
            IEnumerator <Dependency> iter = deps.Values.GetEnumerator();

            iter.MoveNext();
            Assert.True(iter.Current.BestVersion == "8.1.0");

            // check dependency that has transitive dependencies
            support.DependOn("test", "transdep", "1.0");

            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);

            // 1 is the previous test, then 2 for transdep and subdep.
            Assert.True(deps.Count == 3);
            Dependency d = deps["test:artifact"];

            Assert.True(d.BestVersion == "8.1.0");
            d = deps["test:transdep"];
            Assert.AreEqual(d.BestVersion, "1.0.0");
            d = deps["test:subdep"];
            Assert.True(d.BestVersion == "0.9");

            // check constraining down to a later version - the LATEST
            // will make this fail.
            support.DependOn("test", "artifact", "7.0.0");

            ResolutionException ex = null;

            try
            {
                deps = support.ResolveDependencies(false);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }

            Assert.NotNull(ex);

            // Now add it as 7+ and LATEST and it will work.
            support.ResetDependencies();

            support.DependOn("test", "artifact", "LATEST");
            support.DependOn("test", "artifact", "7+");
            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);
            d = deps["test:artifact"];
            Assert.True(d.BestVersion == "8.1.0");

            // Test downversioning.
            support.ResetDependencies();

            support.DependOn("test", "artifact", "1+");
            support.DependOn("test", "artifact", "2+");
            support.DependOn("test", "artifact", "7.0.0");

            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);
            d = deps["test:artifact"];
            Assert.True(d.BestVersion == "7.0.0");

            // test the transitive dep influencing a top level
            support.ResetDependencies();

            support.DependOn("test", "artifact", "1+");
            support.DependOn("test", "subdep", "0+");
            support.DependOn("test", "transdep", "LATEST");

            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);
            d = deps["test:artifact"];
            Assert.True(d.BestVersion == "8.1.0");
            d = deps["test:subdep"];
            Assert.True(d.BestVersion == "0.9");
        }
コード例 #22
0
        public void TestLatestResolution()
        {
            PlayServicesSupport client1 = TestData.CreateInstance();

            // TransDep needs SubDep 0.9.
            client1.DependOn(TestData.PackageId.TransDep, "1.0.0");

            // We'll set the top level dependency to require SubDep 1.0 or greater.
            client1.DependOn(TestData.PackageId.SubDep, "1.0+");

            Dictionary <string, Dependency> deps = null;

            // The following should fail since we need SubDep 0.9 and SubDep 1.1.0.
            ResolutionException ex = null;

            try
            {
                deps = client1.ResolveDependencies(false);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }

            Assert.NotNull(ex, "Expected exception, but got none");

            // now try with useLatest == true, should have no exception
            ex = null;
            try
            {
                deps = client1.ResolveDependencies(true);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }
            Assert.Null(ex, "unexpected exception");

            Assert.NotNull(deps);

            // Should have TransDep and SubDep.
            Assert.AreEqual(2, deps.Count,
                            String.Join(", ", new List <string>(deps.Keys).ToArray()));

            // Now check that that all the dependencies have the correct best version.
            Dependency d = deps[TestData.PackageId.TransDep.VersionlessKey()];

            Assert.NotNull(d, "could not find transdep");
            Assert.AreEqual(TestData.PackageId.TransDep.Info().bestVersion, d.BestVersion);

            d = deps[TestData.PackageId.SubDep.VersionlessKey()];
            Assert.NotNull(d, "could not find subdep");
            Assert.AreEqual("1.1.0", d.BestVersion);

            // Try without version wildcard.
            client1.ClearDependencies();

            // TransDep needs subdep 0.9.
            client1.DependOn(TestData.PackageId.TransDep, "1.0.0");

            // Configure top level dependency to require exactly subdep 1.1.0.
            client1.DependOn(TestData.PackageId.SubDep, "1.1.0");

            ex = null;
            try
            {
                deps = client1.ResolveDependencies(false);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }

            Assert.NotNull(ex, "Expected exception, but got none");

            ex = null;
            try
            {
                deps = client1.ResolveDependencies(true);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }
            Assert.Null(ex, "unexpected exception");

            Assert.NotNull(deps);

            // Should contain TransDep and SubDep.
            Assert.AreEqual(2, deps.Count);

            // now check that that all the dependencies have the correct
            // best version
            d = deps[TestData.PackageId.TransDep.VersionlessKey()];
            Assert.NotNull(d, "could not find transdep");
            Assert.AreEqual(TestData.PackageId.TransDep.Info().bestVersion, d.BestVersion);

            d = deps[TestData.PackageId.SubDep.VersionlessKey()];
            Assert.NotNull(d, "could not find subdep");
            Assert.AreEqual("1.1.0", d.BestVersion);
        }
コード例 #23
0
        public void TestResolveDependencies()
        {
            PlayServicesSupport support = TestData.CreateInstance();

            Assert.True(Directory.Exists(support.SDK));

            support.DependOn(TestData.PackageId.Artifact, "LATEST");

            Dictionary <string, Dependency> deps =
                support.ResolveDependencies(false);

            Assert.NotNull(deps);

            // Verify one dependency is returned at the expected version.
            Assert.AreEqual(1, deps.Count);
            IEnumerator <Dependency> iter = deps.Values.GetEnumerator();

            iter.MoveNext();
            Assert.AreEqual(TestData.PackageId.Artifact.Info().bestVersion,
                            iter.Current.BestVersion);

            // Check dependency with has transitive dependencies.
            support.DependOn(TestData.PackageId.TransDep, "1.0");

            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);

            // One dependency should be present from the previous test and an additional two
            // for the transdep and subdep.
            Assert.AreEqual(3, deps.Count);
            Dependency d = deps[TestData.PackageId.Artifact.VersionlessKey()];

            Assert.AreEqual(TestData.PackageId.Artifact.Info().bestVersion, d.BestVersion);
            d = deps[TestData.PackageId.TransDep.VersionlessKey()];
            Assert.AreEqual(TestData.PackageId.TransDep.Info().bestVersion, d.BestVersion);
            d = deps[TestData.PackageId.SubDep.VersionlessKey()];
            Assert.AreEqual(TestData.PackageId.SubDep.Info().bestVersion, d.BestVersion);

            // check constraining down to a later version - the LATEST
            // will make this fail.
            support.DependOn(TestData.PackageId.Artifact, "7.0.0");

            ResolutionException ex = null;

            try
            {
                deps = support.ResolveDependencies(false);
            }
            catch (ResolutionException e)
            {
                ex = e;
            }

            Assert.NotNull(ex);

            // Now add it as 7+ and LATEST and it will work.
            support.ClearDependencies();

            support.DependOn(TestData.PackageId.Artifact, "LATEST");
            support.DependOn(TestData.PackageId.Artifact, "7+");
            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);
            d = deps[TestData.PackageId.Artifact.VersionlessKey()];
            Assert.AreEqual(TestData.PackageId.Artifact.Info().bestVersion, d.BestVersion);

            // Test downversioning.
            support.ClearDependencies();

            support.DependOn(TestData.PackageId.Artifact, "1+");
            support.DependOn(TestData.PackageId.Artifact, "2+");
            support.DependOn(TestData.PackageId.Artifact, "7.0.0");

            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);
            d = deps[TestData.PackageId.Artifact.VersionlessKey()];
            Assert.AreEqual("7.0.0", d.BestVersion);

            // test the transitive dep influencing a top level
            support.ClearDependencies();

            support.DependOn(TestData.PackageId.Artifact, "1+");
            support.DependOn(TestData.PackageId.SubDep, "0+");
            support.DependOn(TestData.PackageId.TransDep, "LATEST");

            deps = support.ResolveDependencies(false);
            Assert.NotNull(deps);
            d = deps[TestData.PackageId.Artifact.VersionlessKey()];
            Assert.AreEqual(TestData.PackageId.Artifact.Info().bestVersion, d.BestVersion);
            d = deps[TestData.PackageId.SubDep.VersionlessKey()];
            Assert.AreEqual(TestData.PackageId.SubDep.Info().bestVersion, d.BestVersion);
        }
コード例 #24
0
        public static void OnPostProcessUpdateProjectDeps(
            BuildTarget buildTarget, string pathToBuiltProject)
        {
            if (!InjectDependencies())
            {
                return;
            }

            // If the Pods directory does not exist, the pod download step
            // failed.
            var podsDir = Path.Combine(pathToBuiltProject, "Pods");

            if (!Directory.Exists(podsDir))
            {
                return;
            }

            Directory.CreateDirectory(Path.Combine(pathToBuiltProject,
                                                   "Frameworks"));
            Directory.CreateDirectory(Path.Combine(pathToBuiltProject,
                                                   "Resources"));

            string pbxprojPath = GetProjectPath(pathToBuiltProject);
            var    project     = new UnityEditor.iOS.Xcode.PBXProject();

            project.ReadFromString(File.ReadAllText(pbxprojPath));
            string target = project.TargetGuidByName(TARGET_NAME);

            HashSet <string> frameworks = new HashSet <string>();
            HashSet <string> linkFlags  = new HashSet <string>();

            foreach (var frameworkFullPath in
                     Directory.GetDirectories(podsDir, "*.framework",
                                              SearchOption.AllDirectories))
            {
                string frameworkName     = new DirectoryInfo(frameworkFullPath).Name;
                string destFrameworkPath = Path.Combine("Frameworks",
                                                        frameworkName);
                string destFrameworkFullPath = Path.Combine(pathToBuiltProject,
                                                            destFrameworkPath);
                // Only move this framework if it contains a library.
                // Skip frameworks that consist of just resources, they're handled
                // in a separate import step.
                if (!File.Exists(Path.Combine(
                                     frameworkFullPath,
                                     Path.GetFileName(frameworkFullPath)
                                     .Replace(".framework", ""))))
                {
                    continue;
                }

                PlayServicesSupport.DeleteExistingFileOrDirectory(
                    destFrameworkFullPath);
                Directory.Move(frameworkFullPath, destFrameworkFullPath);
                project.AddFileToBuild(
                    target,
                    project.AddFile(destFrameworkPath,
                                    destFrameworkPath,
                                    UnityEditor.iOS.Xcode.PBXSourceTree.Source));

                string moduleMapPath =
                    Path.Combine(Path.Combine(destFrameworkFullPath, "Modules"),
                                 "module.modulemap");

                if (File.Exists(moduleMapPath))
                {
                    // Parse the modulemap, format spec here:
                    // http://clang.llvm.org/docs/Modules.html#module-map-language
                    using (StreamReader moduleMapFile =
                               new StreamReader(moduleMapPath)) {
                        string line;
                        char[] delim = { ' ' };
                        while ((line = moduleMapFile.ReadLine()) != null)
                        {
                            string[] items = line.TrimStart(delim).Split(delim, 2);
                            if (items.Length > 1)
                            {
                                if (items[0] == "link")
                                {
                                    if (items[1].StartsWith("framework"))
                                    {
                                        items = items[1].Split(delim, 2);
                                        frameworks.Add(items[1].Trim(
                                                           new char[] { '\"' }) + ".framework");
                                    }
                                    else
                                    {
                                        linkFlags.Add("-l" + items[1]);
                                    }
                                }
                            }
                        }
                    }
                }

                string resourcesFolder = Path.Combine(destFrameworkFullPath,
                                                      "Resources");
                if (Directory.Exists(resourcesFolder))
                {
                    string[] resFiles   = Directory.GetFiles(resourcesFolder);
                    string[] resFolders =
                        Directory.GetDirectories(resourcesFolder);
                    foreach (var resFile in resFiles)
                    {
                        string destFile = Path.Combine("Resources",
                                                       Path.GetFileName(resFile));
                        File.Copy(resFile, Path.Combine(pathToBuiltProject,
                                                        destFile), true);
                        project.AddFileToBuild(
                            target, project.AddFile(
                                destFile, destFile,
                                UnityEditor.iOS.Xcode.PBXSourceTree.Source));
                    }
                    foreach (var resFolder in resFolders)
                    {
                        string destFolder =
                            Path.Combine("Resources",
                                         new DirectoryInfo(resFolder).Name);
                        string destFolderFullPath =
                            Path.Combine(pathToBuiltProject, destFolder);
                        PlayServicesSupport.DeleteExistingFileOrDirectory(
                            destFolderFullPath);
                        Directory.Move(resFolder, destFolderFullPath);
                        project.AddFileToBuild(
                            target, project.AddFile(
                                destFolder, destFolder,
                                UnityEditor.iOS.Xcode.PBXSourceTree.Source));
                    }
                }
            }

            foreach (var framework in frameworks)
            {
                project.AddFrameworkToProject(target, framework, false);
            }
            foreach (var linkFlag in linkFlags)
            {
                project.AddBuildProperty(target, "OTHER_LDFLAGS", linkFlag);
            }
            File.WriteAllText(pbxprojPath, project.WriteToString());
        }
コード例 #25
0
 public void SetUp()
 {
     PlayServicesSupport.ResetDependencies();
 }
コード例 #26
0
 /// <summary>
 /// Does the resolution of the play-services aars.
 /// </summary>
 /// <param name="svcSupport">Svc support.</param>
 /// <param name="destinationDirectory">Destination directory.</param>
 /// <param name="resolutionComplete">Delegate called when resolution is complete.</param>
 public virtual void DoResolution(PlayServicesSupport svcSupport,
                                  string destinationDirectory,
                                  System.Action resolutionComplete)
 {
     resolutionComplete();
 }
コード例 #27
0
        /// <summary>
        /// Explodes a single aar file.  This is done by calling the
        /// JDK "jar" command, then moving the classes.jar file.
        /// </summary>
        /// <param name="dir">the parent directory of the plugin.</param>
        /// <param name="aarFile">Aar file to explode.</param>
        /// <param name="antProject">true to explode into an Ant style project or false
        /// to repack the processed AAR as a new AAR.</param>
        /// <param name="abi">ABI of the AAR or null if it's universal.</param>
        /// <returns>true if successful, false otherwise.</returns>
        internal virtual bool ProcessAar(string dir, string aarFile, bool antProject,
                                         out string abi)
        {
            PlayServicesSupport.Log(String.Format("ProcessAar {0} {1} antProject={2}",
                                                  dir, aarFile, antProject), verbose: true);
            abi = null;
            string workingDir = Path.Combine(dir, Path.GetFileNameWithoutExtension(aarFile));

            PlayServicesSupport.DeleteExistingFileOrDirectory(workingDir, includeMetaFiles: true);
            Directory.CreateDirectory(workingDir);
            if (!ExtractAar(aarFile, null, workingDir))
            {
                return(false);
            }
            ReplaceVariables(workingDir);

            string nativeLibsDir = null;

            if (antProject)
            {
                // Create the libs directory to store the classes.jar and non-Java shared
                // libraries.
                string libDir = Path.Combine(workingDir, "libs");
                nativeLibsDir = libDir;
                Directory.CreateDirectory(libDir);

                // Move the classes.jar file to libs.
                string classesFile       = Path.Combine(workingDir, "classes.jar");
                string targetClassesFile = Path.Combine(libDir, Path.GetFileName(classesFile));
                if (File.Exists(targetClassesFile))
                {
                    File.Delete(targetClassesFile);
                }
                if (File.Exists(classesFile))
                {
                    File.Move(classesFile, targetClassesFile);
                }
                else
                {
                    // Generate an empty classes.jar file.
                    string temporaryDirectory = CreateTemporaryDirectory();
                    if (temporaryDirectory == null)
                    {
                        return(false);
                    }
                    ArchiveAar(targetClassesFile, temporaryDirectory);
                }
            }

            // Copy non-Java shared libraries (.so) files from the "jni" directory into the
            // lib directory so that Unity's legacy (Ant-like) build system includes them in the
            // built APK.
            string jniLibDir = Path.Combine(workingDir, "jni");

            nativeLibsDir = nativeLibsDir ?? jniLibDir;
            if (Directory.Exists(jniLibDir))
            {
                if (jniLibDir != nativeLibsDir)
                {
                    PlayServicesSupport.CopyDirectory(jniLibDir, nativeLibsDir);
                    PlayServicesSupport.DeleteExistingFileOrDirectory(jniLibDir,
                                                                      includeMetaFiles: true);
                }
                // Remove shared libraries for all ABIs that are not required for the selected
                // target ABI.
                var currentAbi = PlayServicesResolver.AndroidTargetDeviceAbi;
                var activeAbis = GetSelectedABIDirs(currentAbi);
                foreach (var directory in Directory.GetDirectories(nativeLibsDir))
                {
                    var abiDir = Path.GetFileName(directory);
                    if (!activeAbis.Contains(abiDir))
                    {
                        PlayServicesSupport.DeleteExistingFileOrDirectory(
                            directory, includeMetaFiles: true);
                    }
                }
                abi = currentAbi;
            }

            if (antProject)
            {
                // Create the project.properties file which indicates to
                // Unity that this directory is a plugin.
                string projectProperties = Path.Combine(workingDir, "project.properties");
                if (!File.Exists(projectProperties))
                {
                    File.WriteAllLines(projectProperties, new [] {
                        "# Project target.",
                        "target=android-9",
                        "android.library=true"
                    });
                }
                // Clean up the aar file.
                PlayServicesSupport.DeleteExistingFileOrDirectory(Path.GetFullPath(aarFile),
                                                                  includeMetaFiles: true);
                // Add a tracking label to the exploded files.
                PlayServicesResolver.LabelAssets(new [] { workingDir });
            }
            else
            {
                // Add a tracking label to the exploded files just in-case packaging fails.
                PlayServicesResolver.LabelAssets(new [] { workingDir });
                // Create a new AAR file.
                PlayServicesSupport.DeleteExistingFileOrDirectory(Path.GetFullPath(aarFile),
                                                                  includeMetaFiles: true);
                if (!ArchiveAar(aarFile, workingDir))
                {
                    return(false);
                }
                // Clean up the exploded directory.
                PlayServicesSupport.DeleteExistingFileOrDirectory(workingDir,
                                                                  includeMetaFiles: true);
            }
            return(true);
        }
コード例 #28
0
 /// <summary>
 /// Does the resolution of the play-services aars.
 /// </summary>
 /// <param name="svcSupport">Svc support.</param>
 /// <param name="destinationDirectory">Destination directory.</param>
 /// <param name="handleOverwriteConfirmation">Handle overwrite confirmation.</param>
 public abstract void DoResolution(PlayServicesSupport svcSupport,
                                   string destinationDirectory,
                                   PlayServicesSupport.OverwriteConfirmation handleOverwriteConfirmation);
コード例 #29
0
 /// <summary>
 /// Registers the android dependencies.
 /// </summary>
 public static void RegisterAndroidDependencies()
 {
     svcSupport = PlayServicesSupport.CreateInstance("FuseSDK", EditorPrefs.GetString("AndroidSdkRoot"), "ProjectSettings");
     svcSupport.ClearDependencies();
     svcSupport.DependOn("com.google.android.gms", "play-services-basement", "10+", packageIds: new string[] { "extra-google-m2repository" });
 }