@@ -31,11 +31,49 @@ namespace GooglePlayServices {
31
31
internal class GradleTemplateResolver {
32
32
33
33
/// <summary>
34
- /// Path of the Gradle properties file.
34
+ /// Filename of the Custom Gradle Properties Template file.
35
+ /// </summary>
36
+ public static string GradlePropertiesTemplateFilename = "gradleTemplate.properties" ;
37
+
38
+ /// <summary>
39
+ /// Path of the Custom Gradle Properties Template file in the Unity project.
35
40
/// Available only from Unity version 2019.3 onwards
36
41
/// </summary>
37
42
public static string GradlePropertiesTemplatePath =
38
- Path . Combine ( SettingsDialog . AndroidPluginsDir , "gradleTemplate.properties" ) ;
43
+ Path . Combine ( SettingsDialog . AndroidPluginsDir , GradlePropertiesTemplateFilename ) ;
44
+
45
+ /// <summary>
46
+ /// Filename of the Custom Gradle Settings Template file.
47
+ /// </summary>
48
+ public static string GradleSettingsTemplatePathFilename = "settingsTemplate.gradle" ;
49
+
50
+ /// <summary>
51
+ /// Path of the Custom Gradle Settings Template file.
52
+ /// </summary>
53
+ public static string GradleSettingsTemplatePath =
54
+ Path . Combine ( SettingsDialog . AndroidPluginsDir , GradleSettingsTemplatePathFilename ) ;
55
+
56
+ public static string UnityGradleTemplatesDir {
57
+ get {
58
+ if ( unityGradleTemplatesDir == null ) {
59
+ var engineDir = PlayServicesResolver . AndroidPlaybackEngineDirectory ;
60
+ if ( String . IsNullOrEmpty ( engineDir ) ) return null ;
61
+ var gradleTemplateDir =
62
+ Path . Combine ( Path . Combine ( engineDir , "Tools" ) , "GradleTemplates" ) ;
63
+ unityGradleTemplatesDir = gradleTemplateDir ;
64
+ }
65
+ return unityGradleTemplatesDir ;
66
+ }
67
+ }
68
+ private static string unityGradleTemplatesDir = null ;
69
+
70
+ public static string UnityGradleSettingsTemplatePath {
71
+ get {
72
+ return Path . Combine (
73
+ UnityGradleTemplatesDir ,
74
+ GradleSettingsTemplatePathFilename ) ;
75
+ }
76
+ }
39
77
40
78
/// <summary>
41
79
/// Line that indicates the start of the injected properties block in properties template.
@@ -47,11 +85,16 @@ internal class GradleTemplateResolver {
47
85
/// </summary>
48
86
private const string PropertiesEndLine = "# Android Resolver Properties End" ;
49
87
88
+ /// <summary>
89
+ /// Filename of the Custom Main Gradle Template file.
90
+ /// </summary>
91
+ public static string GradleTemplateFilename = "mainTemplate.gradle" ;
92
+
50
93
/// <summary>
51
94
/// Path of the Gradle template file.
52
95
/// </summary>
53
96
public static string GradleTemplatePath =
54
- Path . Combine ( SettingsDialog . AndroidPluginsDir , "mainTemplate.gradle" ) ;
97
+ Path . Combine ( SettingsDialog . AndroidPluginsDir , GradleTemplateFilename ) ;
55
98
56
99
/// <summary>
57
100
/// Line that indicates the start of the injected repos block in the template.
@@ -69,6 +112,12 @@ internal class GradleTemplateResolver {
69
112
private const string ReposInjectionLine =
70
113
@".*apply plugin: 'com\.android\.(application|library)'.*" ;
71
114
115
+ /// <summary>
116
+ /// Line that indicates where to initially inject repos in the settings template.
117
+ /// </summary>
118
+ private const string ReposInjectionLineInGradleSettings =
119
+ @".*flatDir {" ;
120
+
72
121
/// <summary>
73
122
/// Token that indicates where gradle properties should initially be injected.
74
123
/// If this isn't present in the properties template, properties will not be
@@ -108,6 +157,16 @@ internal class GradleTemplateResolver {
108
157
/// </summary>
109
158
private const string PackagingOptionsToken = @"android +{" ;
110
159
160
+ /// <summary>
161
+ /// Whether current of Unity has changed the place to specify Maven repos from
162
+ /// `mainTemplate.gradle` to `settingsTemplate.gradle`.
163
+ /// </summary>
164
+ public static bool UnityChangeMavenRepoInSettingsTemplate {
165
+ get {
166
+ return Google . VersionHandler . GetUnityVersionMajorMinor ( ) >= 2022.2f ;
167
+ }
168
+ }
169
+
111
170
/// <summary>
112
171
/// Copy srcaar files to aar files that are excluded from Unity's build process.
113
172
/// </summary>
@@ -429,7 +488,8 @@ public static bool InjectProperties(){
429
488
}
430
489
431
490
/// <summary>
432
- /// Inject / update dependencies in the gradle template file.
491
+ /// Inject / update additional Maven repository urls specified from `Dependencies.xml` in
492
+ /// the Gradle settings template file.
433
493
/// </summary>
434
494
/// <param name="dependencies">Dependencies to inject.</param>
435
495
/// <returns>true if successful, false otherwise.</returns>
@@ -508,7 +568,9 @@ public static bool InjectDependencies(ICollection<Dependency> dependencies) {
508
568
} ) ;
509
569
}
510
570
}
511
- repoLines . AddRange ( PlayServicesResolver . GradleMavenReposLines ( dependencies ) ) ;
571
+ if ( ! UnityChangeMavenRepoInSettingsTemplate ) {
572
+ repoLines . AddRange ( PlayServicesResolver . GradleMavenReposLines ( dependencies ) ) ;
573
+ }
512
574
513
575
TextFileLineInjector [ ] injectors = new [ ] {
514
576
new TextFileLineInjector ( ReposInjectionLine , ReposStartLine , ReposEndLine ,
@@ -527,5 +589,181 @@ public static bool InjectDependencies(ICollection<Dependency> dependencies) {
527
589
"Gradle Template" , "gradletemplate" ,
528
590
injectors , resolutionMeasurementParameters ) ;
529
591
}
592
+
593
+ /// <summary>
594
+ /// Inject / update dependencies in the gradle template file.
595
+ /// </summary>
596
+ /// <returns>true if successful, false otherwise.</returns>
597
+ public static bool InjectSettings ( ICollection < Dependency > dependencies , out string lastError ) {
598
+ if ( ! UnityChangeMavenRepoInSettingsTemplate ||
599
+ ! PlayServicesResolver . GradleTemplateEnabled ) {
600
+ // Early out since there is no need to patch settings template.
601
+ lastError = "" ;
602
+ return true ;
603
+ }
604
+
605
+ if ( ! EnsureGradleTemplateEnabled ( GradleSettingsTemplatePathFilename ) ) {
606
+ lastError = String . Format (
607
+ "Failed to auto-generate '{0}'. This is required to specify " +
608
+ "additional Maven repos from Unity 2022.2. " +
609
+ "Please manually generate '{2}' through one " +
610
+ "of the following methods:\n " +
611
+ "* For Unity 2022.2.10+, enable 'Custom Gradle Settings Template' " +
612
+ "found under 'Player Settings > Settings for Android -> Publishing " +
613
+ "Settings' menu. \n " +
614
+ "* Manually copy '{1}' to '{2}'\n " +
615
+ "If you like to patch this yourself, simply disable 'Copy and patch " +
616
+ "settingsTemplate.gradle' in Android Resolver settings." ,
617
+ GradleSettingsTemplatePathFilename ,
618
+ UnityGradleSettingsTemplatePath ,
619
+ GradleSettingsTemplatePath ) ;
620
+ return false ;
621
+ }
622
+
623
+ // ReposInjectionLineInGradleSettings
624
+
625
+ var resolutionMeasurementParameters =
626
+ PlayServicesResolver . GetResolutionMeasurementParameters ( null ) ;
627
+ PlayServicesResolver . analytics . Report (
628
+ "/resolve/gradlesettings" , resolutionMeasurementParameters ,
629
+ "Gradle Settings Template Resolve" ) ;
630
+
631
+ var settingsFileDescription = String . Format (
632
+ "gradle settings template " + GradleSettingsTemplatePath ) ;
633
+
634
+ TextFileLineInjector [ ] settingsInjectors = new [ ] {
635
+ new TextFileLineInjector ( ReposInjectionLineInGradleSettings ,
636
+ ReposStartLine , ReposEndLine ,
637
+ GradleMavenReposLinesFromDependencies (
638
+ dependencies : dependencies ,
639
+ addMavenGoogle : false ,
640
+ addMavenCentral : false ,
641
+ addMavenLocal : true ) ,
642
+ "Repo" ,
643
+ settingsFileDescription )
644
+ } ;
645
+ if ( ! PatchFile ( GradleSettingsTemplatePath , settingsFileDescription ,
646
+ "Gradle Settings" , "gradlesettings" ,
647
+ settingsInjectors ,
648
+ resolutionMeasurementParameters ) ) {
649
+ lastError = String . Format ( "Unable to patch " + settingsFileDescription ) ;
650
+ return false ;
651
+ }
652
+
653
+ lastError = "" ;
654
+ return true ;
655
+ }
656
+
657
+ /// <summary>
658
+ /// Get the included dependency repos as lines that can be included in a Gradle file.
659
+ /// </summary>
660
+ /// <returns>Lines that can be included in a gradle file.</returns>
661
+ internal static IList < string > GradleMavenReposLinesFromDependencies (
662
+ ICollection < Dependency > dependencies ,
663
+ bool addMavenGoogle ,
664
+ bool addMavenCentral ,
665
+ bool addMavenLocal ) {
666
+ var lines = new List < string > ( ) ;
667
+ if ( dependencies . Count > 0 ) {
668
+ var exportEnabled = PlayServicesResolver . GradleProjectExportEnabled ;
669
+ var useFullPath = (
670
+ exportEnabled &&
671
+ SettingsDialog . UseFullCustomMavenRepoPathWhenExport ) || (
672
+ ! exportEnabled &&
673
+ SettingsDialog . UseFullCustomMavenRepoPathWhenNotExport ) ;
674
+
675
+ var projectPath = FileUtils . PosixPathSeparators ( Path . GetFullPath ( "." ) ) ;
676
+ var projectFileUri = GradleResolver . RepoPathToUri ( projectPath ) ;
677
+ // projectPath will point to the Unity project root directory as Unity will
678
+ // generate the root Gradle project in "Temp/gradleOut" when *not* exporting a
679
+ // gradle project.
680
+ if ( ! useFullPath ) {
681
+ lines . Add ( String . Format (
682
+ " def unityProjectPath = $/{0}**DIR_UNITYPROJECT**/$" +
683
+ ".replace(\" \\ \\ \" , \" /\" )" , GradleWrapper . FILE_SCHEME ) ) ;
684
+ }
685
+ if ( addMavenGoogle ) {
686
+ lines . Add ( " maven {" ) ;
687
+ lines . Add ( " url \" https://maven.google.com\" " ) ;
688
+ lines . Add ( " }" ) ;
689
+ }
690
+ // Consolidate repos url from Packages folders like
691
+ // "Packages/com.company.pkg1/Path/To/m2repository" and
692
+ // "Packages/com.company.pkg2/Path/To/m2repository"
693
+ Dictionary < string , List < string > > repoUriToSources =
694
+ new Dictionary < string , List < string > > ( ) ;
695
+ foreach ( var repoAndSources in PlayServicesResolver . GetRepos ( dependencies : dependencies ) ) {
696
+ string repoUri ;
697
+ if ( repoAndSources . Key . StartsWith ( projectFileUri ) ) {
698
+ var relativePath = repoAndSources . Key . Substring ( projectFileUri . Length + 1 ) ;
699
+ // Convert "Assets", "Packages/packageid", or
700
+ // "Library/PackageCache/packageid@version" prefix to local maven repo
701
+ // path. Note that local maven repo path only exists if the original repo
702
+ // path contains .srcaar.
703
+ var repoPath = FileUtils . PosixPathSeparators (
704
+ FileUtils . ReplaceBaseAssetsOrPackagesFolder (
705
+ relativePath , GooglePlayServices . SettingsDialog . LocalMavenRepoDir ) ) ;
706
+ if ( ! Directory . Exists ( repoPath ) ) {
707
+ repoPath = relativePath ;
708
+ }
709
+
710
+ if ( useFullPath ) {
711
+ // build.gradle expects file:/// URI so file separator will be "/" in anycase
712
+ // and we must NOT use Path.Combine here because it will use "\" for win platforms
713
+ repoUri = String . Format ( "\" {0}/{1}\" " , projectFileUri , repoPath ) ;
714
+ } else {
715
+ repoUri = String . Format ( "(unityProjectPath + \" /{0}\" )" , repoPath ) ;
716
+ }
717
+ } else {
718
+ repoUri = String . Format ( "\" {0}\" " , repoAndSources . Key ) ;
719
+ }
720
+ List < string > sources ;
721
+ if ( ! repoUriToSources . TryGetValue ( repoUri , out sources ) ) {
722
+ sources = new List < string > ( ) ;
723
+ repoUriToSources [ repoUri ] = sources ;
724
+ }
725
+ sources . Add ( repoAndSources . Value ) ;
726
+ }
727
+ foreach ( var kv in repoUriToSources ) {
728
+ lines . Add ( " maven {" ) ;
729
+ lines . Add ( String . Format ( " url {0} // {1}" , kv . Key ,
730
+ String . Join ( ", " , kv . Value . ToArray ( ) ) ) ) ;
731
+ lines . Add ( " }" ) ;
732
+ }
733
+ if ( addMavenLocal ) {
734
+ lines . Add ( " mavenLocal()" ) ;
735
+ }
736
+ if ( addMavenCentral ) {
737
+ lines . Add ( " mavenCentral()" ) ;
738
+ }
739
+ }
740
+ return lines ;
741
+ }
742
+
743
+ public static bool EnsureGradleTemplateEnabled ( string templateName ) {
744
+ string templatePath = Path . Combine ( SettingsDialog . AndroidPluginsDir , templateName ) ;
745
+ if ( File . Exists ( templatePath ) ) {
746
+ return true ;
747
+ }
748
+
749
+ string templateSourcePath = Path . Combine ( UnityGradleTemplatesDir , templateName ) ;
750
+
751
+ try {
752
+ File . Copy ( templateSourcePath , templatePath ) ;
753
+ } catch ( Exception e ) {
754
+ PlayServicesResolver . Log ( String . Format (
755
+ "Unable to copy '{0}' from Unity engine folder '{1}' to this project " +
756
+ "folder '{2}'. \n {3}" ,
757
+ templateName ,
758
+ UnityGradleTemplatesDir ,
759
+ SettingsDialog . AndroidPluginsDir ,
760
+ e . ToString ( ) ) , LogLevel . Error ) ;
761
+ return false ;
762
+ }
763
+ PlayServicesResolver . Log ( String . Format (
764
+ "Copied '{0}' from Unity engine folder to this project '{1}'" ,
765
+ templateName , SettingsDialog . AndroidPluginsDir ) ) ;
766
+ return true ;
767
+ }
530
768
}
531
769
}
0 commit comments