diff --git a/ExtraPluginCfgs/Android/enjoypay/AndroidManifest.xml b/ExtraPluginCfgs/Android/enjoypay/AndroidManifest.xml
index 7be0ed5..1b5bddb 100644
--- a/ExtraPluginCfgs/Android/enjoypay/AndroidManifest.xml
+++ b/ExtraPluginCfgs/Android/enjoypay/AndroidManifest.xml
@@ -1,54 +1,12 @@
-
-
-
-
-
-
-
-
-
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
diff --git a/ExtraPluginCfgs/Android/enjoypay/mainTemplate.gradle b/ExtraPluginCfgs/Android/enjoypay/mainTemplate.gradle
index 4fbd509..362edc6 100644
--- a/ExtraPluginCfgs/Android/enjoypay/mainTemplate.gradle
+++ b/ExtraPluginCfgs/Android/enjoypay/mainTemplate.gradle
@@ -18,6 +18,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':channel_manifest_lib')
api "com.android.support:support-v4:28.0.0"
api "com.android.support:appcompat-v7:28.0.0"
diff --git a/ExtraPluginCfgs/Android/enjoypay/settingsTemplate.gradle b/ExtraPluginCfgs/Android/enjoypay/settingsTemplate.gradle
index c68dae5..c147ec0 100644
--- a/ExtraPluginCfgs/Android/enjoypay/settingsTemplate.gradle
+++ b/ExtraPluginCfgs/Android/enjoypay/settingsTemplate.gradle
@@ -10,6 +10,10 @@ pluginManagement {
include ':launcher', ':unityLibrary'
**INCLUDES**
+def channelUnityProjectPath = $/**DIR_UNITYPROJECT**/$.replace("\\", "/")
+include ':channel_manifest_lib'
+project(':channel_manifest_lib').projectDir = new File(channelUnityProjectPath, 'Assets/Plugins/Android/channel_manifest_lib')
+
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
diff --git a/ExtraPluginCfgs/Android/flexion/AndroidManifest.xml b/ExtraPluginCfgs/Android/flexion/AndroidManifest.xml
index 5b6df90..f7c6509 100644
--- a/ExtraPluginCfgs/Android/flexion/AndroidManifest.xml
+++ b/ExtraPluginCfgs/Android/flexion/AndroidManifest.xml
@@ -1,69 +1,21 @@
-
-
-
-
-
-
-
-
-
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
diff --git a/ExtraPluginCfgs/Android/flexion/mainTemplate.gradle b/ExtraPluginCfgs/Android/flexion/mainTemplate.gradle
index 798a65a..0182215 100644
--- a/ExtraPluginCfgs/Android/flexion/mainTemplate.gradle
+++ b/ExtraPluginCfgs/Android/flexion/mainTemplate.gradle
@@ -18,6 +18,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':channel_manifest_lib')
api "com.android.support:support-v4:28.0.0"
api "com.android.support:appcompat-v7:28.0.0"
diff --git a/ExtraPluginCfgs/Android/flexion/settingsTemplate.gradle b/ExtraPluginCfgs/Android/flexion/settingsTemplate.gradle
index 6637c13..e05aa0b 100644
--- a/ExtraPluginCfgs/Android/flexion/settingsTemplate.gradle
+++ b/ExtraPluginCfgs/Android/flexion/settingsTemplate.gradle
@@ -10,6 +10,10 @@ pluginManagement {
include ':launcher', ':unityLibrary'
**INCLUDES**
+def channelUnityProjectPath = $/**DIR_UNITYPROJECT**/$.replace("\\", "/")
+include ':channel_manifest_lib'
+project(':channel_manifest_lib').projectDir = new File(channelUnityProjectPath, 'Assets/Plugins/Android/channel_manifest_lib')
+
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
diff --git a/ExtraPluginCfgs/Android/googleplay/mainTemplate.gradle b/ExtraPluginCfgs/Android/googleplay/mainTemplate.gradle
index 28d7325..666e2c6 100644
--- a/ExtraPluginCfgs/Android/googleplay/mainTemplate.gradle
+++ b/ExtraPluginCfgs/Android/googleplay/mainTemplate.gradle
@@ -18,6 +18,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':channel_manifest_lib')
api "com.android.support:support-v4:28.0.0"
api "com.android.support:appcompat-v7:28.0.0"
diff --git a/ExtraPluginCfgs/Android/googleplay/settingsTemplate.gradle b/ExtraPluginCfgs/Android/googleplay/settingsTemplate.gradle
index fa73a11..a28dd34 100644
--- a/ExtraPluginCfgs/Android/googleplay/settingsTemplate.gradle
+++ b/ExtraPluginCfgs/Android/googleplay/settingsTemplate.gradle
@@ -10,6 +10,10 @@ pluginManagement {
include ':launcher', ':unityLibrary'
**INCLUDES**
+def channelUnityProjectPath = $/**DIR_UNITYPROJECT**/$.replace("\\", "/")
+include ':channel_manifest_lib'
+project(':channel_manifest_lib').projectDir = new File(channelUnityProjectPath, 'Assets/Plugins/Android/channel_manifest_lib')
+
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
diff --git a/ExtraPluginCfgs/Android/rustore/AndroidManifest.xml b/ExtraPluginCfgs/Android/rustore/AndroidManifest.xml
index 158c23e..0d17e70 100644
--- a/ExtraPluginCfgs/Android/rustore/AndroidManifest.xml
+++ b/ExtraPluginCfgs/Android/rustore/AndroidManifest.xml
@@ -1,42 +1,8 @@
-
-
-
-
-
-
-
-
-
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
diff --git a/ExtraPluginCfgs/Android/rustore/mainTemplate.gradle b/ExtraPluginCfgs/Android/rustore/mainTemplate.gradle
index fa27a5b..911cb7a 100644
--- a/ExtraPluginCfgs/Android/rustore/mainTemplate.gradle
+++ b/ExtraPluginCfgs/Android/rustore/mainTemplate.gradle
@@ -18,6 +18,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':channel_manifest_lib')
api "com.android.support:support-v4:28.0.0"
api "com.android.support:appcompat-v7:28.0.0"
diff --git a/ExtraPluginCfgs/Android/rustore/settingsTemplate.gradle b/ExtraPluginCfgs/Android/rustore/settingsTemplate.gradle
index 10e312c..4ca778e 100644
--- a/ExtraPluginCfgs/Android/rustore/settingsTemplate.gradle
+++ b/ExtraPluginCfgs/Android/rustore/settingsTemplate.gradle
@@ -10,6 +10,10 @@ pluginManagement {
include ':launcher', ':unityLibrary'
**INCLUDES**
+def channelUnityProjectPath = $/**DIR_UNITYPROJECT**/$.replace("\\", "/")
+include ':channel_manifest_lib'
+project(':channel_manifest_lib').projectDir = new File(channelUnityProjectPath, 'Assets/Plugins/Android/channel_manifest_lib')
+
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
diff --git a/sdk-intergration/Assets/Editor/ChannelBuildTool.cs b/sdk-intergration/Assets/Editor/ChannelBuildTool.cs
index c0e090d..27beb8f 100644
--- a/sdk-intergration/Assets/Editor/ChannelBuildTool.cs
+++ b/sdk-intergration/Assets/Editor/ChannelBuildTool.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Xml.Linq;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEngine;
@@ -16,6 +17,10 @@ public class ChannelBuildTool
private const string AndroidAddressablesContentState = "Assets/AddressableAssetsData/Android/addressables_content_state.bin";
private const string DefaultProductName = "Fishing Travel";
private const string EnjoyPayProductName = "Fishing Travel: Hook & Explore";
+ private const string ChannelManifestLib = "channel_manifest_lib";
+ private const string EmptyManifest = "\n\n";
+ private static readonly XNamespace AndroidNamespace = "http://schemas.android.com/apk/res/android";
+ private static readonly XNamespace ToolsNamespace = "http://schemas.android.com/tools";
// ==================== Channel Switching ====================
@@ -29,9 +34,10 @@ public class ChannelBuildTool
}
Debug.Log($"[ChannelSwitch] Switching to {channel}...");
+ CleanChannelManifestLibBuildArtifacts();
// 1. Sync root Android config files
- SyncRootAndroidConfigFiles(cfgDir);
+ SyncRootAndroidConfigFiles(channel, cfgDir);
// 2. Sync channel SDK adapter Java files to tysdk package
SyncChannelAdapterFiles(cfgDir);
@@ -110,6 +116,7 @@ public class ChannelBuildTool
{
try
{
+ CleanChannelManifestLibBuildArtifacts();
SwitchChannel(channel);
var fileName = debug ? $"tysdkTest_{channel}_debug.apk" : $"tysdkTest_{channel}.apk";
@@ -190,11 +197,12 @@ public class ChannelBuildTool
}
}
- private static void SyncRootAndroidConfigFiles(string cfgDir)
+ private static void SyncRootAndroidConfigFiles(string channel, string cfgDir)
{
CopyRootConfigFiles(cfgDir, "*.gradle");
CopyRootConfigFiles(cfgDir, "*.properties");
- CopyRootConfigFile(cfgDir, "AndroidManifest.xml");
+ SetMainManifestChannel(channel);
+ SyncChannelManifestLib(channel, cfgDir);
}
private static void SyncChannelAdapterFiles(string cfgDir)
@@ -215,18 +223,134 @@ public class ChannelBuildTool
}
}
- private static void CopyRootConfigFiles(string cfgDir, string searchPattern)
+ private static void SyncChannelManifestLib(string channel, string cfgDir)
{
- foreach (var src in Directory.GetFiles(cfgDir, searchPattern, SearchOption.TopDirectoryOnly))
+ var dest = Path.Combine(AssetsPlugins, ChannelManifestLib, "src");
+ if (channel == "GooglePlay")
{
- CopyRootConfigFile(src);
+ WriteEmptyChannelManifestLib(dest);
+ Debug.Log($"[ChannelSwitch] Manifest lib reset to empty default. Channel={channel}");
+ return;
+ }
+
+ var srcManifest = Path.Combine(cfgDir, "AndroidManifest.xml");
+ if (!File.Exists(srcManifest))
+ {
+ throw new FileNotFoundException($"[ChannelSwitch] Channel manifest not found: {srcManifest}");
+ }
+
+ WriteChannelManifestLib(srcManifest, Path.Combine(cfgDir, "res"), dest);
+ Debug.Log($"[ChannelSwitch] Manifest: {srcManifest} -> {Path.Combine(dest, "main", "AndroidManifest.xml")}");
+ }
+
+ private static void SetMainManifestChannel(string channel)
+ {
+ var manifestPath = Path.Combine(AssetsPlugins, "AndroidManifest.xml");
+ if (!File.Exists(manifestPath))
+ {
+ throw new FileNotFoundException($"[ChannelSwitch] Main AndroidManifest not found: {manifestPath}");
+ }
+
+ var doc = XDocument.Load(manifestPath);
+ var root = doc.Root;
+ var application = root?.Elements().FirstOrDefault(x => x.Name.LocalName == "application");
+ if (application == null)
+ {
+ throw new InvalidDataException($"[ChannelSwitch] Main AndroidManifest application node not found: {manifestPath}");
+ }
+
+ var channelMeta = application.Elements()
+ .FirstOrDefault(x => x.Name.LocalName == "meta-data" &&
+ (string)x.Attribute(AndroidNamespace + "name") == "com.arkgame.ft.channel");
+ if (channelMeta == null)
+ {
+ channelMeta = new XElement("meta-data",
+ new XAttribute(AndroidNamespace + "name", "com.arkgame.ft.channel"));
+ application.Add(channelMeta);
+ }
+
+ channelMeta.SetAttributeValue(AndroidNamespace + "value", channel);
+ SetMainManifestBackupRules(application, channel);
+ doc.Save(manifestPath);
+ AssetDatabase.ImportAsset(manifestPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
+ Debug.Log($"[ChannelSwitch] Main manifest channel -> {channel}");
+ }
+
+ private static void SetMainManifestBackupRules(XElement application, string channel)
+ {
+ const string fullBackupContent = "android:fullBackupContent";
+ var replaceAttr = application.Attribute(ToolsNamespace + "replace");
+ var replaceItems = replaceAttr?.Value
+ .Split(',')
+ .Select(x => x.Trim())
+ .Where(x => !string.IsNullOrEmpty(x))
+ .ToList() ?? new List();
+
+ if (channel == "Flexion")
+ {
+ application.SetAttributeValue(AndroidNamespace + "fullBackupContent", "@xml/flexion_backup_rules");
+ if (!replaceItems.Contains(fullBackupContent))
+ {
+ replaceItems.Add(fullBackupContent);
+ }
+ }
+ else
+ {
+ application.SetAttributeValue(AndroidNamespace + "fullBackupContent", null);
+ replaceItems.RemoveAll(x => x == fullBackupContent);
+ }
+
+ application.SetAttributeValue(ToolsNamespace + "replace",
+ replaceItems.Count > 0 ? string.Join(",", replaceItems) : null);
+ }
+
+ private static void WriteEmptyChannelManifestLib(string dest)
+ {
+ if (Directory.Exists(dest))
+ {
+ Directory.Delete(dest, true);
+ }
+
+ var manifestDir = Path.Combine(dest, "main");
+ Directory.CreateDirectory(manifestDir);
+ File.WriteAllText(Path.Combine(manifestDir, "AndroidManifest.xml"), EmptyManifest);
+ }
+
+ private static void CleanChannelManifestLibBuildArtifacts()
+ {
+ var buildDir = Path.Combine(AssetsPlugins, ChannelManifestLib, "build");
+ if (Directory.Exists(buildDir))
+ {
+ Directory.Delete(buildDir, true);
+ }
+
+ var buildMeta = buildDir + ".meta";
+ if (File.Exists(buildMeta))
+ {
+ File.Delete(buildMeta);
}
}
- private static void CopyRootConfigFile(string cfgDir, string fileName)
+ private static void WriteChannelManifestLib(string srcManifest, string srcResDir, string dest)
{
- var src = Path.Combine(cfgDir, fileName);
- if (File.Exists(src))
+ if (Directory.Exists(dest))
+ {
+ Directory.Delete(dest, true);
+ }
+
+ var manifestDir = Path.Combine(dest, "main");
+ Directory.CreateDirectory(manifestDir);
+ File.Copy(srcManifest, Path.Combine(manifestDir, "AndroidManifest.xml"), true);
+
+ if (Directory.Exists(srcResDir))
+ {
+ CopyDirectoryClean(srcResDir, Path.Combine(manifestDir, "res"));
+ }
+ }
+
+ private static void CopyRootConfigFiles(string cfgDir, string searchPattern)
+ {
+ foreach (var src in Directory.GetFiles(cfgDir, searchPattern, SearchOption.TopDirectoryOnly))
{
CopyRootConfigFile(src);
}
@@ -240,6 +364,27 @@ public class ChannelBuildTool
Debug.Log($"[ChannelSwitch] Config: {src} -> {dest}");
}
+ private static void CopyDirectoryClean(string src, string dest)
+ {
+ if (Directory.Exists(dest))
+ {
+ Directory.Delete(dest, true);
+ }
+
+ Directory.CreateDirectory(dest);
+ foreach (var srcFile in Directory.GetFiles(src, "*", SearchOption.AllDirectories))
+ {
+ if (srcFile.EndsWith(".meta")) continue;
+
+ var relativePath = srcFile.Substring(src.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
+ var destFile = Path.Combine(dest, relativePath);
+ var destDir = Path.GetDirectoryName(destFile);
+ if (!Directory.Exists(destDir)) Directory.CreateDirectory(destDir);
+
+ File.Copy(srcFile, destFile, true);
+ }
+ }
+
private static void SetAddressablesProfile(string channel)
{
var settings = AddressableAssetSettingsDefaultObject.Settings;
diff --git a/sdk-intergration/Assets/Plugins/Android/AndroidManifest.xml b/sdk-intergration/Assets/Plugins/Android/AndroidManifest.xml
index a1fa4fc..d2b229a 100644
--- a/sdk-intergration/Assets/Plugins/Android/AndroidManifest.xml
+++ b/sdk-intergration/Assets/Plugins/Android/AndroidManifest.xml
@@ -1,48 +1,41 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib.meta b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib.meta
new file mode 100644
index 0000000..4c7681c
--- /dev/null
+++ b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ad9923efa7716e24a9eacfdeaba25735
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/build.gradle b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/build.gradle
new file mode 100644
index 0000000..26bff43
--- /dev/null
+++ b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/build.gradle
@@ -0,0 +1,14 @@
+apply plugin: 'com.android.library'
+
+evaluationDependsOn(':unityLibrary')
+def unityAndroid = project(':unityLibrary').extensions.getByName('android')
+
+android {
+ namespace 'com.arkgame.ft.channelmanifest'
+ compileSdkVersion unityAndroid.compileSdkVersion
+ buildToolsVersion unityAndroid.buildToolsVersion
+
+ defaultConfig {
+ minSdkVersion unityAndroid.defaultConfig.minSdkVersion.apiLevel
+ }
+}
diff --git a/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/build.gradle.meta b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/build.gradle.meta
new file mode 100644
index 0000000..41603a7
--- /dev/null
+++ b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/build.gradle.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 6b1864b7c14c2874290c96b313f016da
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src.meta b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src.meta
new file mode 100644
index 0000000..c42f21c
--- /dev/null
+++ b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0c6d5688cdd2a434fae148ccc076e1ee
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main.meta b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main.meta
new file mode 100644
index 0000000..4070fb6
--- /dev/null
+++ b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4835437bf5f97d548abb765917c4873c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main/AndroidManifest.xml b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b2d3ea1
--- /dev/null
+++ b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main/AndroidManifest.xml.meta b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main/AndroidManifest.xml.meta
new file mode 100644
index 0000000..7a6b1d5
--- /dev/null
+++ b/sdk-intergration/Assets/Plugins/Android/channel_manifest_lib/src/main/AndroidManifest.xml.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: f8101f5c11c019f45843819fd0a0aec8
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle b/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle
index 28d7325..666e2c6 100644
--- a/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle
+++ b/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle
@@ -18,6 +18,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':channel_manifest_lib')
api "com.android.support:support-v4:28.0.0"
api "com.android.support:appcompat-v7:28.0.0"
diff --git a/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle b/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle
index fa73a11..a28dd34 100644
--- a/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle
+++ b/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle
@@ -10,6 +10,10 @@ pluginManagement {
include ':launcher', ':unityLibrary'
**INCLUDES**
+def channelUnityProjectPath = $/**DIR_UNITYPROJECT**/$.replace("\\", "/")
+include ':channel_manifest_lib'
+project(':channel_manifest_lib').projectDir = new File(channelUnityProjectPath, 'Assets/Plugins/Android/channel_manifest_lib')
+
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {