feat:1、添加项目

This commit is contained in:
2026-06-02 10:26:44 +08:00
commit dfead2c461
7518 changed files with 748693 additions and 0 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e911636ac126b4819bb8ee84eecfac04
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,47 @@
using System;
using UnityEditor;
using UnityEngine;
using AnyThink.Scripts.IntegrationManager.Editor;
[InitializeOnLoad]
public class ATAssetPostprocessor : AssetPostprocessor
{
private static readonly string TAG = "ATAssetPostprocessor";
static ATAssetPostprocessor()
{
log("ATAssetPostprocessor is now initialized!");
}
void OnPostprocessAsset(string path)
{
log("OnPostprocessAsset() >>> path: " + path + " assetPath: " + assetPath);
}
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (string str in importedAssets)
{
log("imported Asset: " + str);
}
foreach (string str in deletedAssets)
{
log("Deleted Asset: " + str);
}
for (int i = 0; i < movedAssets.Length; i++)
{
log("Moved Asset: " + movedAssets[i] + " from: " + movedFromAssetPaths[i]);
}
}
void OnPreprocessAsset()
{
log("OnPreprocessAsset() >>> called assetPath: " + assetPath);
}
private static void log(string msg)
{
ATLog.log(TAG, msg);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f9137cd99292b497cbba1a142f7e73ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,426 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
// using AnyThink.Scripts.Assets;
using System.Text.RegularExpressions;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class ATConfig
{
public static string PLUGIN_VERSION = "2.1.5";
public static bool isDebug = false;
public static int PLUGIN_TYPE = 2;
public static int OS_ANDROID = 1;
public static int OS_IOS = 2;
public static int CHINA_COUNTRY = 1;
public static int NONCHINA_COUNTRY = 2;
public static string ANYTHINK_SDK_FILES_PATH = "Assets/ThinkupTpnPlugin/AnyThinkAds";
//国内Android core包的相关目录
public static string[] CHINA_ANDROID_CORE_FILES_ARRAY = {Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/China/Editor"),
Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/China/thinkup_base"),
Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/China/mediation_plugin")};
//海外Android core包的相关目录
public static string[] NON_CHINA_ANDROID_CORE_FILES_ARRAY = {Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/NonChina/thinkup_base"),
Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/NonChina/Editor")};
//国内core aar包的父目录
public static string CHINA_ANDROID_CORE_FILES_PATH = Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/China/thinkup_base/");
public static string NONCHINA_ANDROID_CORE_FILES_PATH = Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/NonChina/thinkup_base/");
//国内Android network aar包的父目录
public static string CHINA_ANDROID_NETWORK_FILES_PARENT_PATH = Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/China/mediation/");
//海外Android network 依赖文件的目录
public static string NONCHINA_ANDROID_NETWORK_FILES_PARENT_PATH = Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/Android/NonChina/mediation/");
//iOS network依赖文件的目录,不区分国家
public static string IOS_NETWORK_FILES_PARENT_PATH = Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/iOS/China/");
public static string NONCHINA_IOS_NETWORK_FILES_PARENT_PATH = Path.Combine(ANYTHINK_SDK_FILES_PATH, "Plugins/iOS/NonChina/");
//network json文件名
public static string network_data_file_name = "network_data.json";
//插件设置的数据
public static string plugin_setting_data_path = "Assets/ThinkupTpnPlugin/Resources/json/" + PLUGIN_VERSION;
private static string plugin_setting_data_file_name = "plugin_setting_data.json";
//保存插件设置的数据,保存时机:安装core包、选择国家、切换SDK、androidX设置发生变化时
public static void savePluginSettingData(PluginSettingData settingData)
{
var directoryPath = plugin_setting_data_path;
// 确保目标文件夹存在
if (!Directory.Exists(directoryPath))
{
// 如果目录不存在,则创建它
Directory.CreateDirectory(directoryPath);
}
string fullPath = Path.Combine(directoryPath, plugin_setting_data_file_name);
string settingDataStr = JsonUtility.ToJson(settingData);
ATLog.log("savePluginSettingData() >>> fullPath: " + fullPath + " settingDataStr: " + settingDataStr);
File.WriteAllText(fullPath, settingDataStr);
}
//获取插件设置的数据
public static PluginSettingData getPluginSettingData()
{
string fullPath = Path.Combine(plugin_setting_data_path, plugin_setting_data_file_name);
if (!File.Exists(fullPath)) {
return null;
}
string json = File.ReadAllText(fullPath);
if(json == "") {
return null;
}
return JsonUtility.FromJson<PluginSettingData>(json);
}
public static bool removeSdk(int country, int os) {
string path = ANYTHINK_SDK_FILES_PATH + "/Plugins";
if (os == OS_ANDROID) {
path = path + "/Android";
} else {
path = path + "/iOS";
}
if (country == CHINA_COUNTRY) {
path = path + "/China";
} else {
path = path + "/NonChina";
}
if (Directory.Exists(path)) {
FileUtil.DeleteFileOrDirectory(path);
}
if (File.Exists(path + ".meta")) {
FileUtil.DeleteFileOrDirectory(path + ".meta");
}
return true;
}
//移除本地的network
public static bool removeInstalledNetwork(Network network, int os)
{
//修改sdk的配置
if (isCoreNetwork(network.Name) && os == OS_ANDROID) {
var paths = CHINA_ANDROID_CORE_FILES_ARRAY;
if (network.Country == NONCHINA_COUNTRY) {
paths = NON_CHINA_ANDROID_CORE_FILES_ARRAY;
}
foreach(string p in paths) {
if (Directory.Exists(p)) {
FileUtil.DeleteFileOrDirectory(p);
}
if (File.Exists(p + ".meta")) {
FileUtil.DeleteFileOrDirectory(p + ".meta");
}
}
return true;
}
var path = getAndroidNetworkPath(network);
if (os == OS_IOS) {
path = getIosNetworkPath(network);
}
if (Directory.Exists(path)) {
FileUtil.DeleteFileOrDirectory(path);
if (File.Exists(path + ".meta")) {
FileUtil.DeleteFileOrDirectory(path + ".meta");
}
}
//针对mintegral改名字为gtm后,旧版升级到新版,旧版的mintegral目录需要删除
var displayName = network.DisplayName;
var name = network.Name;
ATLog.log("removeInstalledNetwork() >>> displayName: " + displayName + " name: " + name);
if (Equals(displayName, "Mintegral") && Equals(name, "Gtm"))
{
displayName = "mintegral";
var mtgPath = getNetworkInstallPath(displayName, os, network.Country);
if (Directory.Exists(mtgPath))
{
FileUtil.DeleteFileOrDirectory(mtgPath);
if (File.Exists(mtgPath + ".meta"))
{
FileUtil.DeleteFileOrDirectory(mtgPath + ".meta");
}
}
}
return true;
}
// 保存已安装的network到本地
public static void saveInstalledNetworkVersion(Network network, int os)
{
if (isCoreNetwork(network.Name)) {
return;
}
var networkDataFileName = network_data_file_name;
var networkName = network.Name.ToLower();
int country = network.Country;
var installedVersions = network.CurrentVersions;
if (installedVersions != null) {
if (os == OS_ANDROID) {
var android_version = installedVersions.Android;
//Android
if (!string.IsNullOrEmpty(android_version)) {
var networkPath = getAndroidNetworkPath(network);
Directory.CreateDirectory(networkPath);
ATLog.log("saveInstalledNetworkVersion() >>> android networkPath: " + networkPath + " exist: " + Directory.Exists(networkPath));
if (Directory.Exists(networkPath)) {
string fullPath = Path.Combine(networkPath, networkDataFileName);
var networkData = new NetworkLocalData();
networkData.name = networkName;
networkData.country = country;
networkData.version = android_version;
networkData.path = networkPath;
File.WriteAllText(fullPath, JsonUtility.ToJson(networkData));
}
}
} else {
//iOS
var ios_version = installedVersions.Ios;
if (!string.IsNullOrEmpty(ios_version)) {
var networkPath = getIosNetworkPath(network);
Directory.CreateDirectory(networkPath);
ATLog.log("saveInstalledNetworkVersion() >>> ios networkPath: " + networkPath);
if (Directory.Exists(networkPath)) {
string fullPath = Path.Combine(networkPath, networkDataFileName);
var networkData = new NetworkLocalData();
networkData.name = networkName;
networkData.country = country;
networkData.version = ios_version;
networkData.path = networkPath;
File.WriteAllText(fullPath, JsonUtility.ToJson(networkData));
}
}
}
}
}
//Core 是否已安装
public static bool isCoreNetworkInstalled(PluginSettingData pluginSettingData, int os) {
var countrySettingData = pluginSettingData.getCountrySettingData();
if (os == OS_ANDROID) {
return !string.IsNullOrEmpty(countrySettingData.android_version);
} else {
return !string.IsNullOrEmpty(countrySettingData.ios_version);
}
}
//Network是否已安装
public static bool isNetworkInstalled(Network network, int os)
{
if (isCoreNetwork(network.Name)) {
var pluginSettingData = getPluginSettingData();
return isCoreNetworkInstalled(pluginSettingData, os);
}
var path = getIosNetworkPath(network);
if (os == OS_ANDROID) {
path = getAndroidNetworkPath(network);
}
return File.Exists(Path.Combine(path, network_data_file_name));
}
//Network是否已安装,根据name
public static bool isNetworkInstalledByName(string name, int os)
{
var pluginSettingData = getPluginSettingData();
if (pluginSettingData != null) {
var country = pluginSettingData.curCountry;
var network = new Network();
network.Name = name;
network.Country = country;
return isNetworkInstalled(network, os);
}
return false;
}
private static string getAndroidNetworkPath(Network network)
{
var networkName = network.Name.ToLower();
var country = network.Country;
if (isCoreNetwork(networkName))
{
return country == CHINA_COUNTRY ? CHINA_ANDROID_CORE_FILES_PATH : NONCHINA_ANDROID_CORE_FILES_PATH;
}
else
{
return country == CHINA_COUNTRY ? CHINA_ANDROID_NETWORK_FILES_PARENT_PATH + networkName.ToLower() : NONCHINA_ANDROID_NETWORK_FILES_PARENT_PATH + networkName.ToLower();
}
}
private static string getIosNetworkPath(Network network)
{
var networkName = network.Name.ToLower();
var country = network.Country;
// if (isCoreNetwork(networkName))
// {
// return IOS_NETWORK_FILES_PARENT_PATH;
// } else {
// }
return country == CHINA_COUNTRY ? IOS_NETWORK_FILES_PARENT_PATH + networkName : NONCHINA_IOS_NETWORK_FILES_PARENT_PATH + networkName;
}
//根据network名字去获取安装路径
private static string getNetworkInstallPath(string networkName, int os, int country)
{
if (os == OS_ANDROID) {
return country == CHINA_COUNTRY ? CHINA_ANDROID_NETWORK_FILES_PARENT_PATH + networkName.ToLower() : NONCHINA_ANDROID_NETWORK_FILES_PARENT_PATH + networkName.ToLower();
} else {
return country == CHINA_COUNTRY ? IOS_NETWORK_FILES_PARENT_PATH + networkName : NONCHINA_IOS_NETWORK_FILES_PARENT_PATH + networkName;
}
}
public static int getSelectedCountry()
{
var pluginSettingData = getPluginSettingData();
if (pluginSettingData != null)
{
return pluginSettingData.curCountry;
}
return CHINA_COUNTRY;
}
public static bool isCoreNetwork(string networkName) {
return Equals(networkName.ToLower(), ATIntegrationManager.AnyThinkNetworkName.ToLower());
}
//查找本地是否有已安装network,并进行版本赋值
public static void initNetworkLocalData(Network network) {
var networkDataFileName = network_data_file_name;
var androidPath = getAndroidNetworkPath(network);
var iosPath = getIosNetworkPath(network);
var androidDataFile = Path.Combine(androidPath, networkDataFileName);
var iosDataFile = Path.Combine(iosPath, networkDataFileName);
var curVersions = network.CurrentVersions;
if (curVersions == null) {
curVersions = new Versions();
}
if (File.Exists(androidDataFile)) {
string a_json = File.ReadAllText(androidDataFile);
var a_data = JsonUtility.FromJson<NetworkLocalData>(a_json);
curVersions.Android = a_data.version;
}
if (File.Exists(iosDataFile)) {
string i_json = File.ReadAllText(iosDataFile);
var i_data = JsonUtility.FromJson<NetworkLocalData>(i_json);
curVersions.Ios = i_data.version;
}
network.CurrentVersions = curVersions;
}
//当前是否选择国内地区
public static bool isSelectedChina() {
var pluginSettingData = getPluginSettingData();
if (pluginSettingData != null) {
return pluginSettingData.curCountry == CHINA_COUNTRY;
}
return true;
}
//获取admob app id
public static string getAdmobAppIdByOs(int os) {
var pluginSettingData = getPluginSettingData();
if (pluginSettingData == null) {
return "";
}
var settingData = pluginSettingData.getCountrySettingData();
return settingData.getAdmobAppId(os);
}
public static bool enableAndroidX() {
var pluginSettingData = getPluginSettingData();
if (pluginSettingData == null) {
return false;
}
return pluginSettingData.getCountrySettingData().androidXSetting == 1;
}
public static bool isDefaultAndroidX() {
var pluginSettingData = getPluginSettingData();
if (pluginSettingData == null) {
return false;
}
return pluginSettingData.getCountrySettingData().androidXSetting == 0;
}
//获取默认选中的地区
public static int getDefCountry() {
// string version = PLUGIN_VERSION;
// int lastIndex = version.LastIndexOf('.');
// if (lastIndex != -1)
// {
// //2.1.0:是区分国内海外的插件,2.1.01:后缀多了1,是只有海外的插件
// string lastPart = version.Substring(lastIndex + 1);
// if (lastPart.Length == 2) {
// return NONCHINA_COUNTRY;
// }
// }
if(PLUGIN_TYPE == 2) {
return NONCHINA_COUNTRY;
}
return CHINA_COUNTRY;
}
public static string[] getCountryArray() {
// new string[] { "ChinaMainland", "Overseas" }
// string version = PLUGIN_VERSION;
// int lastIndex = version.LastIndexOf('.');
// if (lastIndex != -1)
// {
// //2.1.0:是区分国内海外的插件,2.1.01:后缀多了1,是只有海外的插件
// string lastPart = version.Substring(lastIndex + 1);
// if (lastPart.Length == 2) {
// return new string[] { "Overseas" };
// }
// }
if(PLUGIN_TYPE == 2) {
return new string[] { "Overseas" };
}
return new string[] { "ChinaMainland", "Overseas" };
}
public static string getRegionIntegrateTip()
{
//Tips: If ChinaMainland and Oversea are integrated at the same time, there will be compilation conflicts, whether it is Android or iOS platform.
//Currently, the Android platform integrates ChinaMainland and Oversea at the same time, which may cause compilation errors or other errors.
var pluginSettingData = getPluginSettingData();
if (pluginSettingData == null) {
return "";
}
var sb = new StringBuilder();
sb.Append("Tips: Currently, ");
var android_tip = false;
if (pluginSettingData.isBothInstallAndroid()) {
sb.Append("the Android platform ");
android_tip = true;
}
var ios_tip = false;
if (pluginSettingData.isBothInstallIOS()) {
if (android_tip) {
sb.Append("and ");
}
sb.Append("iOS platform ");
ios_tip = true;
}
if (android_tip || ios_tip) {
sb.Append("integrates ChinaMainland and Oversea at the same time, which may cause compilation error or other errors.");
return sb.ToString();
} else {
return "";
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2b2352e251db34ef68de45cc12f61ccf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,355 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class ATDataUtil
{
public static Network coreNetwork;
public static Network[] parseNetworksJson(PluginData pluginData, string netowrksJson)
{
try
{
int country = pluginData.country;
bool isChinaCountry = isChina(country);
ServerNetworks serverNetworks = JsonUtility.FromJson<ServerNetworks>(netowrksJson);
Network network = pluginData.anyThink;
if (network == null) {
return null;
}
var android_version = pluginData.requestParams.androidVersion;
var ios_version = pluginData.requestParams.iosVersion;
var androidSdkVersionList = serverNetworks.android_sdk;
var iosSdkVersionList = serverNetworks.ios_sdk;
ServerNetworkSdk androidNeworkSdk = null;
if (!string.IsNullOrEmpty(android_version)) {
foreach(ServerNetworkSdk sdk in androidSdkVersionList) {
if (Equals(sdk.version, android_version)) {
androidNeworkSdk = sdk;
}
}
}
ServerNetworkSdk iosNeworkSdk = null;
if (!string.IsNullOrEmpty(ios_version)) {
foreach(ServerNetworkSdk sdk in iosSdkVersionList) {
if (Equals(sdk.version, ios_version)) {
iosNeworkSdk = sdk;
}
}
}
ATLog.log("parseNetworksJson() >>> androidNeworkSdk: " + androidNeworkSdk + " iosNeworkSdk: " + iosNeworkSdk);
ServerNetworkInfo[] serverNetworkInfoList;
Network[] networks = mergeAndroidIosNetworks(getServerNetworkInfo(isChinaCountry, androidNeworkSdk, ATConfig.OS_ANDROID), getServerNetworkInfo(isChinaCountry, iosNeworkSdk, ATConfig.OS_IOS));
Array.Sort(networks);
ATLog.log("parseNetworksJson() >>> networks.Length: " + networks.Length);
//处理本地已安装过的Core和Network数据
var countrySettingData = pluginData.pluginSettingData.getCountrySettingData();
List<Network> networkList = new List<Network>();
foreach(var item in networks) {
if (Equals(item.Name, ATIntegrationManager.AnyThinkNetworkName)) {
network.Name = item.Name;
network.DisplayName = item.DisplayName;
network.AndroidDownloadUrl = item.AndroidDownloadUrl;
network.iOSDownloadloadUrl = item.iOSDownloadloadUrl;
network.PluginFileName = item.PluginFileName;
//本地是否有安装core
var version = network.CurrentVersions;
if (version == null) {
version = new Versions();
}
version.Android = countrySettingData.android_version;
version.Ios = countrySettingData.ios_version;
network.CurrentVersions = version;
network.LatestVersions = item.LatestVersions;
} else {
// ATLog.log("parseNetworksJson() >>> lastAndroidVersion: " + item.LatestVersions.Android + " lastIosVerion: " + item.LatestVersions.Ios);
//本地是否有安装network
ATConfig.initNetworkLocalData(item);
networkList.Add(item);
}
}
return networkList.ToArray();
}
catch (Exception e)
{
// 错误处理代码
ATLog.log("parseNetworksJson() >>> failed: " + e);
}
return null;
}
public static PluginData parsePluginDataJson(string serverPluginVersionJson)
{
ATLog.log("parsePluginDataJson plugin version data: " + serverPluginVersionJson);
try
{
var pluginData = new PluginData();
ServerPluginVersion serverPluginVersion = JsonUtility.FromJson<ServerPluginVersion>(serverPluginVersionJson);
pluginData.androidVersions = serverPluginVersion.android_versions;
pluginData.iosVersions = serverPluginVersion.ios_versions;
pluginData.pluginVersion = serverPluginVersion.pluginVersion;
// 初始化本地的core包数据
var settingData = ATConfig.getPluginSettingData();
if (settingData == null) {
settingData = new PluginSettingData();
ATConfig.savePluginSettingData(settingData);
}
pluginData.country = settingData.curCountry;
pluginData.pluginSettingData = settingData;
pluginData.anyThink = initCoreNetworkWithLocalData(settingData);
return pluginData;
}
catch (Exception e)
{
// 错误处理代码
ATLog.log("parse version data failed: " + e);
}
return null;
}
public static Network initCoreNetworkWithLocalData(PluginSettingData settingData) {
var network = new Network();
var versions = new Versions();
var countryData = settingData.getCountrySettingData();
if (countryData != null) {
versions.Android = countryData.android_version;
versions.Ios = countryData.ios_version;
}
network.CurrentVersions = versions;
network.Country = settingData.curCountry;
return network;
}
public static ServerNetworkInfo[] getServerNetworkInfo(bool isChina, ServerNetworkSdk serverNetworks, int os) {
if (serverNetworks == null) {
return null;
}
if (isChina) {
return serverNetworks.network_list.china;
} else {
return serverNetworks.network_list.nonchina;
}
}
private static IEnumerable<ServerNetworkInfo> GetUniqueNetworkInfo(ServerNetworkInfo[] androidNetworks, ServerNetworkInfo[] iosNetworks)
{
// Android独有的
var uniqueToAndroid = androidNetworks.Where(a => !iosNetworks.Any(i => i.displayName == a.displayName));
// iOS独有的
var uniqueToIos = iosNetworks.Where(i => !androidNetworks.Any(a => a.displayName == i.displayName));
// 合并结果
return uniqueToAndroid.Concat(uniqueToIos);
}
//合并Android和iOS的network数据
public static Network[] mergeAndroidIosNetworks(ServerNetworkInfo[] androidNetworks, ServerNetworkInfo[] iosNetworks)
{
int a_length = 0;
int i_length = 0;
if (androidNetworks != null) {
a_length = androidNetworks.Length;
}
if (iosNetworks != null) {
i_length = iosNetworks.Length;
}
ATLog.log("mergeAndroidIosNetworks() >>> a_length: " + a_length + " i_length: " + i_length);
int max_length = Math.Max(a_length, i_length);
int min_length = Math.Min(a_length, i_length);
var externalNetworks = androidNetworks;
var internalNetworks = iosNetworks;
if (a_length < i_length) {
externalNetworks = iosNetworks;
internalNetworks = androidNetworks;
}
List<Network> networkList = new List<Network>();
ATLog.log("mergeAndroidIosNetworks() >>> max_length: " + max_length + " min_length: " + min_length);
for (int i = 0; i < max_length; i++) {
var network = new Network();
var iNetwork = externalNetworks[i];
if (min_length == 0) {
//只有集成一个平台
network = flatServerNetwork(iNetwork, network);
networkList.Add(network);
} else {
//合并相同的network
for (int j = 0; j < min_length; j++) {
var jNetwork = internalNetworks[j];
if (Equals(iNetwork.displayName, jNetwork.displayName)) {
network = flatServerNetwork(iNetwork, network);
network = flatServerNetwork(jNetwork, network);
networkList.Add(network);
}
}
}
}
//过滤平台的唯一network
if (i_length > 0 && a_length > 0) {
var serverNetworkInfos = GetUniqueNetworkInfo(androidNetworks, iosNetworks);
foreach (var serverNetworkInfo in serverNetworkInfos)
{
var network = new Network();
networkList.Add(flatServerNetwork(serverNetworkInfo, network));
}
}
return networkList.ToArray();
}
//后台下载数据转换成本地数据
public static Network flatServerNetwork(ServerNetworkInfo serverInfo, Network network)
{
network.Name = serverInfo.name;
network.DisplayName = serverInfo.displayName;
network.Country = serverInfo.country;
network.PluginFileName = serverInfo.pluginFileName;
var versions = network.LatestVersions;
if (versions == null) {
versions = new Versions();
}
if (serverInfo.os == ATConfig.OS_ANDROID) { //Android
network.AndroidDownloadUrl = serverInfo.downloadUrl;
versions.Android = serverInfo.version;
} else { //iOS
network.iOSDownloadloadUrl = serverInfo.downloadUrl;
versions.Ios = serverInfo.version;
}
ATLog.log("flatServerNetwork() >>> name: " + network.Name + " androidVersion: " + versions.Android + " iosVersion: " + versions.Ios);
network.LatestVersions = versions;
return network;
}
public static bool isChina(int country)
{
return country == ATConfig.CHINA_COUNTRY;
}
//只比较Android、iOS
public static VersionComparisonResult CompareVersions(string versionA, string versionB)
{
if (string.IsNullOrEmpty(versionA) || string.IsNullOrEmpty(versionB) || versionA.Equals(versionB))
{
return VersionComparisonResult.Equal;
}
try
{
var aVersionArrays = versionA.Split('.');
var bVersionArrays = versionB.Split('.');
var arrayLength = Mathf.Min(aVersionArrays.Length, bVersionArrays.Length);
for (var i = 0; i < arrayLength; i++)
{
var aVersionStr = aVersionArrays[i];
var bVersionStr = bVersionArrays[i];
var aVersionInt = int.Parse(aVersionStr);
var bVersionInt = int.Parse(bVersionStr);
if (i == arrayLength - 1) //末尾最后一个
{
if (aVersionStr.Length > bVersionStr.Length)
{
int gapLength = aVersionStr.Length - bVersionStr.Length;
bVersionInt = bVersionInt * (gapLength * 10);
}
else if (aVersionStr.Length < bVersionStr.Length)
{
int gapLength = bVersionStr.Length - aVersionStr.Length;
aVersionInt = aVersionInt * (gapLength * 10);
}
}
if (aVersionInt < bVersionInt) return VersionComparisonResult.Lesser;
if (aVersionInt > bVersionInt) return VersionComparisonResult.Greater;
}
}
catch (Exception e)
{
ATLog.logError("CompareVersions failed: " + e.Message);
}
return VersionComparisonResult.Equal;
}
}
//下发的插件数据:{"pluginVersion": "2.1.0", "platformName": "AnyThink", "ios_versions": ["6.2.88"], "android_versions": ["6.2.93"]}
[Serializable]
public class ServerPluginVersion
{
public string platformName;
// public string networkUrlVersion;
public string pluginVersion;
public string[] android_versions;
public string[] ios_versions;
}
[Serializable]
public class ServerNetworks
{
public string plugin_version;
public ServerNetworkSdk[] ios_sdk;
public ServerNetworkSdk[] android_sdk;
}
[Serializable]
public class ServerNetworkSdk
{
public string version;
public ServerNetworkListObj network_list;
}
[Serializable]
public class ServerNetworkListObj
{
public ServerNetworkInfo[] china;
public ServerNetworkInfo[] nonchina;
}
[Serializable]
public class ServerNetworkInfo
{
public string name;
public string displayName;
public string downloadUrl;
public string pluginFileName;
public string version;
public int os;
public int country;
// public ServerNetworkVersion versions;
}
[Serializable]
public class ServerNetworkVersion
{
public string android;
public string ios;
public string unity;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a409a636a62d04b26ade7ade224489a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,66 @@
#if !UNITY_2017_2_OR_NEWER
using System;
using System.IO;
using UnityEngine.Networking;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class ATDownloadHandler : DownloadHandlerScript
{
// Required by DownloadHandler base class. Called when you address the 'bytes' property.
protected override byte[] GetData()
{
return null;
}
private FileStream fileStream;
public ATDownloadHandler(string path) : base(new byte[2048])
{
var downloadDirectory = Path.GetDirectoryName(path);
if (!Directory.Exists(downloadDirectory))
{
Directory.CreateDirectory(downloadDirectory);
}
try
{
//Open the current file to write to
fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
}
catch (Exception exception)
{
// MaxSdkLogger.UserError(string.Format("Failed to create file at {0}\n{1}", path, exception.Message));
ATLog.logError(string.Format("Failed to create file at {0}\n{1}", path, exception.Message));
}
}
protected override bool ReceiveData(byte[] byteFromServer, int dataLength)
{
if (byteFromServer == null || byteFromServer.Length < 1 || fileStream == null)
{
return false;
}
try
{
//Write the current data to the file
fileStream.Write(byteFromServer, 0, dataLength);
}
catch (Exception exception)
{
fileStream.Close();
fileStream = null;
ATLog.logError(string.Format("Failed to download file{0}", exception.Message));
}
return true;
}
protected override void CompleteContent()
{
fileStream.Close();
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5bafb0360f71b4552859c091a9309513
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,74 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class ATEditorCoroutine
{
/// <summary>
/// Keeps track of the coroutine currently running.
/// </summary>
private IEnumerator enumerator;
/// <summary>
/// Keeps track of coroutines that have yielded to the current enumerator.
/// </summary>
private readonly List<IEnumerator> history = new List<IEnumerator>();
private ATEditorCoroutine(IEnumerator enumerator) {
this.enumerator = enumerator;
}
public static ATEditorCoroutine startCoroutine(IEnumerator enumerator) {
var coroutine = new ATEditorCoroutine(enumerator);
coroutine.Start();
return coroutine;
}
private void Start()
{
EditorApplication.update += OnEditorUpdate;
}
/// <summary>
/// Stops the coroutine.
/// </summary>
public void Stop()
{
if (EditorApplication.update == null) return;
EditorApplication.update -= OnEditorUpdate;
}
private void OnEditorUpdate()
{
if (enumerator.MoveNext())
{
// If there is a coroutine to yield for inside the coroutine, add the initial one to history and continue the second one
if (enumerator.Current is IEnumerator)
{
history.Add(enumerator);
enumerator = (IEnumerator) enumerator.Current;
}
}
else
{
// Current coroutine has ended, check if we have more coroutines in history to be run.
if (history.Count == 0)
{
// No more coroutines to run, stop updating.
Stop();
}
// Step out and finish the code in the coroutine that yielded to it
else
{
var index = history.Count - 1;
enumerator = history[index];
history.RemoveAt(index);
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3fc3656e471f54d6eafd9a258b89d23c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,447 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using System.Threading.Tasks;
using System.Threading;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class ATIntegrationManager
{
public static ATIntegrationManager Instance = new ATIntegrationManager();
// private UnityWebRequest downloadPluginRequest;
private const string AnyThinkAds = "AnyThinkAds";
//AnyThink的unity插件
public static string AnyThinkNetworkName = "Core";
private PluginData mPluginData;
private ATIntegrationManager()
{
}
public void CancelDownload()
{
// if (downloadPluginRequest == null) return;
// downloadPluginRequest.Abort();
}
public IEnumerator loadPluginData(Action<PluginData> callback)
{
var thinkupVersionRequest = UnityWebRequest.Get(ATNetInfo.getPluginConfigUrl(ATConfig.PLUGIN_VERSION));
var webRequest = thinkupVersionRequest.SendWebRequest();
while (!webRequest.isDone)
{
yield return new WaitForSeconds(0.1f);
}
#if UNITY_2020_1_OR_NEWER
if (thinkupVersionRequest.result != UnityWebRequest.Result.Success)
#elif UNITY_2017_2_OR_NEWER
if (thinkupVersionRequest.isNetworkError || thinkupVersionRequest.isHttpError)
#else
if (thinkupVersionRequest.isError)
#endif
{
Debug.Log("loadPluginData failed.");
callback(null);
}
else
{
//解析Anythink的版本数据
string thinkupVersionJson = thinkupVersionRequest.downloadHandler.text;
PluginData pluginData = ATDataUtil.parsePluginDataJson(thinkupVersionJson);
Debug.Log("loadPluginData succeed. country: " + pluginData.country + " androidVersions: "
+ pluginData.androidVersions + " iosVersions: " + pluginData.iosVersions);
mPluginData = pluginData;
callback(pluginData);
}
}
public IEnumerator loadNetworksData(PluginData pluginData, Action<PluginData> callback)
{
Network network = pluginData.anyThink;
if (pluginData == null)
{
callback(null);
}
else if (pluginData.requestParams == null) {
ATLog.log("loadNetworksData() >>> pluginData.requestParams is null");
callback(pluginData);
}
else
{
var networksRequest = UnityWebRequest.Get(ATNetInfo.getNetworkListUrl(ATConfig.PLUGIN_VERSION));
var webRequest = networksRequest.SendWebRequest();
while (!webRequest.isDone)
{
yield return new WaitForSeconds(0.1f);
}
#if UNITY_2020_1_OR_NEWER
if (networksRequest.result != UnityWebRequest.Result.Success)
#elif UNITY_2017_2_OR_NEWER
if (networksRequest.isNetworkError || networksRequest.isHttpError)
#else
if (networksRequest.isError)
#endif
{
Debug.Log("loadNetworksData failed.");
callback(pluginData);
}
else
{
//解析network列表的版本数据
string netowrksJson = networksRequest.downloadHandler.text;
ATLog.log("loadNetworksData() >>> netowrksJson: " + netowrksJson);
pluginData.mediatedNetworks = ATDataUtil.parseNetworksJson(pluginData, netowrksJson);
ATLog.log("loadNetworksData() >>> mediatedNetworks: " + pluginData.mediatedNetworks);
mPluginData = pluginData;
callback(pluginData);
}
}
}
/// <summary>
/// Downloads the plugin file for a given network.
/// </summary>
/// <param name="network">Network for which to download the current version.</param>
/// <param name="showImport">Whether or not to show the import window when downloading. Defaults to <c>true</c>.</param>
/// <returns></returns>
public void downloadPlugin(Network network, int os =1, bool showImport = false)
{
ATEditorCoroutine.startCoroutine(downloadPluginWithEnumerator(network, os, showImport));
}
public IEnumerator downloadPluginWithEnumerator(Network network, int os, bool showImport)
{
ATLog.log("downloadPluginWithEnumerator() >>> networkName: " + network.Name + " os: " + os);
// if (downloadPluginRequest != null)
// {
// downloadPluginRequest.Dispose();
// }
var path = Path.Combine(Application.temporaryCachePath, network.PluginFileName);
ATLog.log("downloadPluginWithEnumerator() >>> path: " + path);
#if UNITY_2017_2_OR_NEWER
var downloadHandler = new DownloadHandlerFile(path);
#else
var downloadHandler = new ATDownloadHandler(path);
#endif
var downloadUrl = network.AndroidDownloadUrl;
if (os == ATConfig.OS_IOS)
{
downloadUrl = network.iOSDownloadloadUrl;
}
UnityWebRequest downloadPluginRequest = new UnityWebRequest(downloadUrl)
{ method = UnityWebRequest.kHttpVerbGET,
downloadHandler = downloadHandler
};
#if UNITY_2017_2_OR_NEWER
var operation = downloadPluginRequest.SendWebRequest();
#else
var operation = downloadPluginRequest.Send();
#endif
while (!operation.isDone)
{
yield return new WaitForSeconds(0.1f); // Just wait till downloadPluginRequest is completed. Our coroutine is pretty rudimentary.
if (operation.progress != 1 && operation.isDone)
{
// CallDownloadPluginProgressCallback(network.DisplayName, operation.progress, operation.isDone, os);
UpdateCurrentVersions(network, os);
}
}
#if UNITY_2020_1_OR_NEWER
if (downloadPluginRequest.result != UnityWebRequest.Result.Success)
#elif UNITY_2017_2_OR_NEWER
if (downloadPluginRequest.isNetworkError || downloadPluginRequest.isHttpError)
#else
if (downloadPluginRequest.isError)
#endif
{
ATLog.logError(downloadPluginRequest.error);
}
else
{
AssetDatabase.ImportPackage(path, showImport);
UpdateCurrentVersions(network, os);
AssetDatabase.Refresh();
}
downloadPluginRequest.Dispose();
downloadPluginRequest = null;
}
//默认下载core包,在下载完network的数据时。
public void downloadCorePlugin(PluginData pluginData)
{
mPluginData = pluginData;
var requestParams = pluginData.requestParams;
var pluginSettingData = pluginData.pluginSettingData;
bool isIosInstalled = ATConfig.isCoreNetworkInstalled(pluginSettingData, ATConfig.OS_IOS);
bool isAndroidInstalled = ATConfig.isCoreNetworkInstalled(pluginSettingData, ATConfig.OS_ANDROID);
ATLog.log("downloadCorePlugin() >>> isIosInstalled: " + isIosInstalled + " isAndroidInstalled: " + isAndroidInstalled);
Network network = pluginData.anyThink;
int os = requestParams.os;
if (os == ATConfig.OS_ANDROID) {
if (!isAndroidInstalled) {
downloadPlugin(network, os);
} else {
//判断是否需要切换SDK
var latestVersions = network.LatestVersions;
var curVersion = network.CurrentVersions;
if (latestVersions.Android != curVersion.Android) {
//先删除掉core包
ATConfig.removeSdk(pluginData.country, os);
removeNetworkVersions(pluginData, os);
//赋值当前版本为空
curVersion.Android = "";
//重新下载core包
downloadPlugin(network, os);
//重新下载已安装的network
redownloadNetworksPlugin(pluginData, os);
}
}
} else if (os == ATConfig.OS_IOS){
if (!isIosInstalled) {
downloadPlugin(network, os);
} else {
//判断是否需要切换SDK
var latestVersions = network.LatestVersions;
var curVersion = network.CurrentVersions;
if (latestVersions.Ios != curVersion.Ios) {
//先删除掉core包
ATConfig.removeSdk(pluginData.country, os);
removeNetworkVersions(pluginData, os);
//赋值当前版本为空
curVersion.Ios = "";
//重新下载core包
downloadPlugin(network, os);
//重新下载已安装的network
redownloadNetworksPlugin(pluginData, os);
}
}
}
}
//当切换SDK版本时,需要重新下载已安装的network
private void redownloadNetworksPlugin(PluginData pluginData, int os) {
var mediatedNetworks = pluginData.mediatedNetworks;
var needInstallNetworkList = new List<Network>();
foreach(Network network in mediatedNetworks) {
var currentVersion = network.CurrentVersions;
if (currentVersion != null) {
if (os == ATConfig.OS_ANDROID) {
if (!string.IsNullOrEmpty(currentVersion.Android)) {
needInstallNetworkList.Add(network);
}
} else {
if (!string.IsNullOrEmpty(currentVersion.Ios)) {
needInstallNetworkList.Add(network);
}
}
}
}
if (needInstallNetworkList.Count() == 0) {
return;
}
Thread.Sleep(500);
ATEditorCoroutine.startCoroutine(UpgradeAllNetworks(needInstallNetworkList, os));
}
private IEnumerator UpgradeAllNetworks(List<Network> networks, int os) {
EditorApplication.LockReloadAssemblies();
foreach (var network in networks)
{
yield return downloadPluginWithEnumerator(network, os, false);
}
EditorApplication.UnlockReloadAssemblies();
}
public void networkInstallOrUpdate(PluginData pluginData, Network network, int os)
{
downloadPlugin(network, os);
}
//更新network已安装的版本
private void UpdateCurrentVersions(Network network, int os)
{
var latestVersions = network.LatestVersions;
var versions = network.CurrentVersions;
if (versions == null) {
versions = new Versions();
}
if (os == ATConfig.OS_ANDROID) {
versions.Android = latestVersions.Android;
} else {
versions.Ios = latestVersions.Ios;
}
network.CurrentVersions = versions;
// await Task.Delay(1000);
// Thread.Sleep(1000);
//下面的逻辑会延迟一秒后执行,确保unitypackage先解压到本地
ATConfig.saveInstalledNetworkVersion(network, os);
ATLog.log("UpdateCurrentVersions() >>> AndroidVersion: " + versions.Android);
//保存Core Networkde
if (ATConfig.isCoreNetwork(network.Name)) {
var countrySettingData = mPluginData.pluginSettingData.getCountrySettingData();
if (os == ATConfig.OS_ANDROID) {
countrySettingData.android_version = latestVersions.Android;
} else {
countrySettingData.ios_version = latestVersions.Ios;
}
ATConfig.savePluginSettingData(mPluginData.pluginSettingData);
}
// ATLog.log("UpdateCurrentVersions() >>> Name: " + network.Name + " latest Unity Version: " + network.LatestVersions.Unity);
}
//点击了界面的network删除按钮
public void uninstallNetwork(Network network, int os)
{
var result = ATConfig.removeInstalledNetwork(network, os);
if (result) {
if (os == ATConfig.OS_ANDROID){
network.CurrentVersions.Android = "";
} else {
network.CurrentVersions.Ios = "";
}
}
}
//切换国家
public void switchCountry(PluginData pluginData, int country) {
pluginData.country = country;
var pluginSettingData = pluginData.pluginSettingData;
pluginSettingData.curCountry = country;
ATConfig.savePluginSettingData(pluginSettingData);
}
//获取AndroidX开关状态
public int getAndroidXSetting(PluginData pluginData) {
if (pluginData == null) {
return 0;
}
var pluginSettingData = pluginData.pluginSettingData;
if (pluginSettingData == null) {
return 0;
}
CountrySettingData countrySettingData = pluginSettingData.getCountrySettingData();
return countrySettingData.androidXSetting;
}
//设置并保存AndroidX开关状态
public void saveAndroidXSetting(PluginData pluginData, int androidXSetting) {
ATLog.log("saveAndroidXSetting() >>> androidXSetting: " + androidXSetting);
var pluginSettingData = pluginData.pluginSettingData;
CountrySettingData countrySettingData = pluginSettingData.getCountrySettingData();
countrySettingData.androidXSetting = androidXSetting;
ATConfig.savePluginSettingData(pluginSettingData);
}
//根据系统判断Admob是否有安装
public bool isAdmobInstalled(int os) {
return ATConfig.isNetworkInstalledByName("Admob", os);
}
public string getAdmobAppIdByOs(PluginData pluginData, int os) {
if (pluginData == null) {
return "";
}
//android_admob_app_id
var countrySettingData = pluginData.pluginSettingData.getCountrySettingData();
return countrySettingData.getAdmobAppId(os);
}
//设置保存Admob app id
public void setAdmobAppidByOs(PluginData pluginData, int os, string appId) {
if (pluginData == null || pluginData.pluginSettingData == null) {
return;
}
var countrySettingData = pluginData.pluginSettingData.getCountrySettingData();
countrySettingData.setAdmobAppId(appId, os);
ATConfig.savePluginSettingData(pluginData.pluginSettingData);
}
//删除某个版本的SDK
public void deleteSdk(PluginData pluginData, string sdkVersion, int os) {
ATLog.log("deleteSdk() >>> sdkVersion: " + sdkVersion + " os: " + os);
//删除本地文件
ATConfig.removeSdk(pluginData.country, os);
//修改UI显示
removeNetworkVersions(pluginData, os, true);
var curVersions = pluginData.anyThink.CurrentVersions;
//修改sdk本地配置文件
var pluginSettingData = pluginData.pluginSettingData;
CountrySettingData countrySettingData = pluginSettingData.getCountrySettingData();
if (os == ATConfig.OS_ANDROID) {
curVersions.Android = "";
countrySettingData.android_version = "";
} else {
curVersions.Ios = "";
countrySettingData.ios_version = "";
}
ATConfig.savePluginSettingData(pluginSettingData);
}
private void removeNetworkVersions(PluginData pluginData, int os, bool isDeleteSdk = false) {
if (isDeleteSdk) {
var mediatedNetworks = pluginData.mediatedNetworks;
if (mediatedNetworks != null && mediatedNetworks.Length > 0) {
foreach(Network network in mediatedNetworks) {
var currentVersion = network.CurrentVersions;
if (currentVersion != null) {
if (os == ATConfig.OS_ANDROID) {
currentVersion.Android = "";
} else {
currentVersion.Ios = "";
}
}
var latestVersions = network.LatestVersions;
if (latestVersions != null) {
if (os == ATConfig.OS_ANDROID) {
latestVersions.Android = "";
} else {
latestVersions.Ios = "";
}
}
}
}
NetworkRequestParams requestParams = pluginData.requestParams;
if (requestParams == null) {
return;
}
if (os == ATConfig.OS_ANDROID) { //Android
requestParams.androidVersion = "";
} else {
requestParams.iosVersion = "";
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf2178e4a7ba941cba8ae0367e521ea9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,860 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Text;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class ATIntegrationManagerWindow : EditorWindow
{
private const string windowTitle = "ThinkupTpn Integration Manager";
private const string uninstallIconExportPath = "ThinkupTpnPlugin/Resources/Images/uninstall_icon.png";
private const string alertIconExportPath = "ThinkupTpnPlugin/Resources/Images/alert_icon.png";
private const string warningIconExportPath = "ThinkupTpnPlugin/Resources/Images/warning_icon.png";
private static readonly Color darkModeTextColor = new Color(0.29f, 0.6f, 0.8f);
private GUIStyle titleLabelStyle;
private GUIStyle headerLabelStyle;
private GUIStyle environmentValueStyle;
private GUIStyle wrapTextLabelStyle;
private GUIStyle linkLabelStyle;
private GUIStyle iconStyle;
private GUIStyle tipTextStyle;
private Texture2D uninstallIcon;
private Texture2D alertIcon;
private Texture2D warningIcon;
private Vector2 scrollPosition;
private static readonly Vector2 windowMinSize = new Vector2(850, 750);
private const float actionFieldWidth = 80f;
private const float upgradeAllButtonWidth = 80f;
private const float networkFieldMinWidth = 200f;
private const float versionFieldMinWidth = 200f;
private const float privacySettingLabelWidth = 200f;
private const float networkFieldWidthPercentage = 0.22f;
private const float versionFieldWidthPercentage = 0.36f; // There are two version fields. Each take 40% of the width, network field takes the remaining 20%.
private static float previousWindowWidth = windowMinSize.x;
private static GUILayoutOption networkWidthOption = GUILayout.Width(networkFieldMinWidth);
private static GUILayoutOption versionWidthOption = GUILayout.Width(versionFieldMinWidth);
private static GUILayoutOption sdkKeyTextFieldWidthOption = GUILayout.Width(520);
private static GUILayoutOption privacySettingFieldWidthOption = GUILayout.Width(400);
private static readonly GUILayoutOption fieldWidth = GUILayout.Width(actionFieldWidth);
private static readonly GUILayoutOption upgradeAllButtonFieldWidth = GUILayout.Width(upgradeAllButtonWidth);
private ATEditorCoroutine loadDataCoroutine;
private PluginData pluginData;
private bool pluginDataLoadFailed;
private bool networkButtonsEnabled = true;
private bool shouldShowGoogleWarning;
private int curSelectCountryInt;
// private int dropdownIndex = 0;
private int androidVersionPopupIndex;
private int iosVersionPopupIndex;
public static void ShowManager()
{
var manager = GetWindow<ATIntegrationManagerWindow>(utility: true, title: windowTitle, focus: true);
manager.minSize = windowMinSize;
// manager.maxSize = windowMinSize;
}
//定义UI的Style
private void Awake()
{
titleLabelStyle = new GUIStyle(EditorStyles.label)
{
fontSize = 14,
fontStyle = FontStyle.Bold,
fixedHeight = 20
};
headerLabelStyle = new GUIStyle(EditorStyles.label)
{
fontSize = 12,
fontStyle = FontStyle.Bold,
fixedHeight = 18
};
environmentValueStyle = new GUIStyle(EditorStyles.label)
{
alignment = TextAnchor.MiddleRight
};
linkLabelStyle = new GUIStyle(EditorStyles.label)
{
wordWrap = true,
normal = { textColor = EditorGUIUtility.isProSkin ? darkModeTextColor : Color.blue }
};
wrapTextLabelStyle = new GUIStyle(EditorStyles.label)
{
wordWrap = true
};
iconStyle = new GUIStyle(EditorStyles.miniButton)
{
fixedWidth = 18,
fixedHeight = 18,
padding = new RectOffset(1, 1, 1, 1)
};
tipTextStyle = new GUIStyle(EditorStyles.label)
{
normal = { textColor = Color.yellow }
};
// Load uninstall icon texture.
var uninstallIconData = File.ReadAllBytes(ATSdkUtil.GetAssetPathForExportPath(uninstallIconExportPath));
uninstallIcon = new Texture2D(100, 100, TextureFormat.RGBA32, false); // 1. Initial size doesn't matter here, will be automatically resized once the image asset is loaded. 2. Set mipChain to false, else the texture has a weird blurry effect.
uninstallIcon.LoadImage(uninstallIconData);
// Load alert icon texture.
var alertIconData = File.ReadAllBytes(ATSdkUtil.GetAssetPathForExportPath(alertIconExportPath));
alertIcon = new Texture2D(100, 100, TextureFormat.RGBA32, false);
alertIcon.LoadImage(alertIconData);
// Load warning icon texture.
var warningIconData = File.ReadAllBytes(ATSdkUtil.GetAssetPathForExportPath(warningIconExportPath));
warningIcon = new Texture2D(100, 100, TextureFormat.RGBA32, false);
warningIcon.LoadImage(warningIconData);
loadPluginData();
//热更新
ATIntegrationHotFix.Instance.loadHotFixData();
}
//这个方法在插件启动时会调用,然后脚本重新加载时也会重新调用,所以加载数据放在Awake中
private void OnEnable()
{
}
private void OnDisable()
{
if (loadDataCoroutine != null)
{
loadDataCoroutine.Stop();
loadDataCoroutine = null;
}
ATIntegrationManager.Instance.CancelDownload();
EditorUtility.ClearProgressBar();
// Saves the AppLovinSettings object if it has been changed.
AssetDatabase.SaveAssets();
}
private void OnDestroy() {
ATLog.log("OnDestroy() >>> called");
}
private void OnGUI()
{
// OnGUI is called on each frame draw, so we don't want to do any unnecessary calculation if we can avoid it. So only calculate it when the width actually changed.
if (Math.Abs(previousWindowWidth - position.width) > 1)
{
previousWindowWidth = position.width;
CalculateFieldWidth();
}
using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPosition, false, false))
{
scrollPosition = scrollView.scrollPosition;
GUILayout.Space(5);
// EditorGUILayout.LabelField("Region (Only for Android, iOS is not affected by region)", titleLabelStyle);
EditorGUILayout.LabelField("Region", titleLabelStyle);
DrawCountryUI();
DrawCountrySwitchTip();
DrawAndroidXUI();
DrawAdombAppId();
EditorGUILayout.LabelField("ThinkupTpn Plugin Details", titleLabelStyle);
//显示插件版本号
DrawPluginDetails();
//绘制SDK版本下架提示
DrawSdkVersionOffTip();
//绘制Networks
DrawMediatedNetworks();
}
if (GUI.changed)
{
AssetDatabase.SaveAssets();
}
}
/// <summary>
/// Callback method that will be called with progress updates when the plugin is being downloaded.
/// </summary>
public static void OnDownloadPluginProgress(string pluginName, float progress, bool done)
{
ATLog.logFormat("OnDownloadPluginProgress() >>> pluginName: {0}, progress: {1}, done: {2}", new object[] { pluginName, progress, done });
// Download is complete. Clear progress bar.
if (done || progress == 1)
{
EditorUtility.ClearProgressBar();
AssetDatabase.Refresh();
}
// Download is in progress, update progress bar.
else
{
if (EditorUtility.DisplayCancelableProgressBar(windowTitle, string.Format("Downloading {0} plugin...", pluginName), progress))
{
ATLog.log("OnDownloadPluginProgress() >>> click cancel download");
ATIntegrationManager.Instance.CancelDownload();
EditorUtility.ClearProgressBar();
AssetDatabase.Refresh();
}
}
}
public void DeleteSdkVersion(PluginData pluginData, int index, int os) {
var sdkVersion = pluginData.androidVersions[index];
if (os == ATConfig.OS_IOS) {
sdkVersion = pluginData.iosVersions[index];
}
ATIntegrationManager.Instance.deleteSdk(pluginData, sdkVersion, os);
}
public void ExChangeSDKVersion(PluginData pluginData, int index, int os) {
NetworkRequestParams requestParams = pluginData.requestParams;
if (requestParams == null) {
requestParams = new NetworkRequestParams();
}
requestParams.os = os;
if (os == ATConfig.OS_ANDROID) { //Android
requestParams.androidVersion = pluginData.androidVersions[index];
} else {
requestParams.iosVersion = pluginData.iosVersions[index];
}
pluginData.requestParams = requestParams;
// ATLog.log("ExChangeSDKVersion() >>> versions.Android: " + versions.Android + " versions.Ios: " + versions.Ios);
loadNetworksData(pluginData);
}
//获取插件和SDK的版本数据
private void loadPluginData()
{
if (loadDataCoroutine != null)
{
loadDataCoroutine.Stop();
}
loadDataCoroutine = ATEditorCoroutine.startCoroutine(ATIntegrationManager.Instance.loadPluginData(data =>
{
if (data == null)
{
pluginDataLoadFailed = true;
}
else
{
ATLog.log("loadNetworksData() >>> pluginData: " + data);
pluginData = data;
pluginDataLoadFailed = false;
var versions = pluginData.anyThink.CurrentVersions;
if (versions != null) {
var requestParams = new NetworkRequestParams();
requestParams.androidVersion = versions.Android;
requestParams.iosVersion = versions.Ios;
pluginData.requestParams = requestParams;
}
loadNetworksData(pluginData);
}
CalculateFieldWidth();
Repaint();
}));
}
//获取networks
private void loadNetworksData(PluginData pluginData)
{
ATEditorCoroutine.startCoroutine(ATIntegrationManager.Instance.loadNetworksData(pluginData, data =>
{
pluginData = data;
Network network = pluginData.anyThink;
if (!string.IsNullOrEmpty(network.AndroidDownloadUrl) || !string.IsNullOrEmpty(network.iOSDownloadloadUrl)) {
ATIntegrationManager.Instance.downloadCorePlugin(data);
}
Repaint();
}));
}
//切换国家,重新加载数据
private void switchCountry(int country)
{
ATIntegrationManager.Instance.switchCountry(pluginData, country);
//重新开始走network
loadPluginData();
}
private void CalculateFieldWidth()
{
var currentWidth = position.width;
var availableWidth = currentWidth - actionFieldWidth - 80; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements.
var networkLabelWidth = Math.Max(networkFieldMinWidth, availableWidth * networkFieldWidthPercentage);
networkWidthOption = GUILayout.Width(networkLabelWidth);
var versionLabelWidth = Math.Max(versionFieldMinWidth, availableWidth * versionFieldWidthPercentage);
versionWidthOption = GUILayout.Width(versionLabelWidth);
const int textFieldOtherUiElementsWidth = 45; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements.
var availableTextFieldWidth = currentWidth - networkLabelWidth - textFieldOtherUiElementsWidth;
sdkKeyTextFieldWidthOption = GUILayout.Width(availableTextFieldWidth);
var availableUserDescriptionTextFieldWidth = currentWidth - privacySettingLabelWidth - textFieldOtherUiElementsWidth;
privacySettingFieldWidthOption = GUILayout.Width(availableUserDescriptionTextFieldWidth);
}
private void DrawCountryUI()
{
// GUILayout.BeginHorizontal();
GUILayout.Space(4);
using (new EditorGUILayout.HorizontalScope("box"))
{
GUILayout.Space(5);
int countryInt = ATConfig.getDefCountry(); //默认是中国
if (pluginData != null)
{
countryInt = pluginData.country;
}
string[] options = ATConfig.getCountryArray();
// 创建Dropdown组件
int curDropdownIndex = ATDataUtil.isChina(countryInt) ? 0 : 1;
if (options.Length == 1) {
curDropdownIndex = 0;
}
int dropdownIndex = EditorGUILayout.Popup("Select Region:", curDropdownIndex, options);
if (options.Length > 1) {
curSelectCountryInt = dropdownIndex == 0 ? ATConfig.CHINA_COUNTRY : ATConfig.NONCHINA_COUNTRY;
//变化才设置
if (pluginData != null && curSelectCountryInt != countryInt)
{
ATLog.log("DrawCountryUI() >>> curSelectCountryInt: " + curSelectCountryInt + " countryInt: " + countryInt);
//Unity需要更换Network
switchCountry(curSelectCountryInt);
}
}
GUILayout.Space(5);
}
GUILayout.Space(4);
// GUILayout.EndHorizontal();
}
private void DrawCountrySwitchTip()
{
var integratedTip = ATConfig.getRegionIntegrateTip();
if (string.IsNullOrEmpty(integratedTip)) {
return;
}
GUILayout.Space(4);
// textStyle.fontStyle = FontStyle.Bold;
EditorGUILayout.LabelField(integratedTip, tipTextStyle);
GUILayout.Space(4);
}
private void DrawAndroidXUI()
{
bool isChina = ATConfig.isSelectedChina();
// if (!ATConfig.isSelectedChina()) {
// return;
// }
EditorGUILayout.LabelField("AndroidX (Only for Android)", titleLabelStyle);
GUILayout.Space(4);
using (new EditorGUILayout.HorizontalScope("box"))
{
GUILayout.Space(5);
int androidXSetting = ATIntegrationManager.Instance.getAndroidXSetting(pluginData);
string[] options = new string[] { "Default", "Enable", "Disable" };
if (!isChina) {
options = new string[] { "Default", "Enable" };
}
// 创建Dropdown组件
int lastDropdownIndex = androidXSetting;
int curDropdownIndex = EditorGUILayout.Popup("Enable AndroidX:", lastDropdownIndex, options);
//变化才设置
if (curDropdownIndex != lastDropdownIndex)
{
ATLog.log("DrawAndroidXUI() >>> curDropdownIndex: " + curDropdownIndex + " lastDropdownIndex: " + lastDropdownIndex);
ATIntegrationManager.Instance.saveAndroidXSetting(pluginData, curDropdownIndex);
}
GUILayout.Space(5);
}
GUILayout.Space(4);
}
private void DrawPluginDetails()
{
// GUILayout.BeginHorizontal();
GUILayout.Space(10);
using (new EditorGUILayout.VerticalScope("box"))
{
// Draw plugin version details
DrawHeaders("Platform", true);
DrawPluginDetailRow("Unity Plugin", ATConfig.PLUGIN_VERSION, "", "");
if (pluginData == null)
{
DrawEmptyPluginData("loading sdk data ...");
return;
}
var thinkup = pluginData.anyThink;
var android_version = "";
var ios_version = "";
if (thinkup != null) {
android_version = thinkup.CurrentVersions.Android;
ios_version = thinkup.CurrentVersions.Ios;
}
//绘制Android
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(5);
EditorGUILayout.LabelField(new GUIContent("Android"), networkWidthOption);
EditorGUILayout.LabelField(new GUIContent(android_version), versionWidthOption);
GUILayout.Space(3);
string[] androidVersions = pluginData.androidVersions;
if (androidVersions != null && androidVersions.Length > 0) {
List<int> androidVersionsInt = new List<int>();
int androidLength = androidVersions.Length;
for (int i = 0; i < androidLength; i = i + 1)
{
androidVersionsInt.Add(i);
}
// 创建Dropdown组件
androidVersionPopupIndex = EditorGUILayout.IntPopup(androidVersionPopupIndex, androidVersions, androidVersionsInt.ToArray(), versionWidthOption);
GUILayout.FlexibleSpace();
string selectedAndroidVersion = androidVersions[androidVersionPopupIndex];
string action = "Exchange";
if (!string.IsNullOrEmpty(android_version) && Equals(android_version, selectedAndroidVersion)) {
action = "Delete";
}
GUI.enabled = (!Equals(android_version, selectedAndroidVersion)) || action == "Delete";
if (GUILayout.Button(new GUIContent(action), fieldWidth))
{
//切换AndroidSDK版本
if (action == "Delete") {
DeleteSdkVersion(pluginData, androidVersionPopupIndex, ATConfig.OS_ANDROID);
} else {
ExChangeSDKVersion(pluginData, androidVersionPopupIndex, ATConfig.OS_ANDROID);
}
}
GUI.enabled = true;
GUILayout.Space(5);
} else {
EditorGUILayout.LabelField(new GUIContent("loading..."), versionWidthOption);
}
GUILayout.Space(3);
}
//绘制iOS
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(5);
EditorGUILayout.LabelField(new GUIContent("iOS"), networkWidthOption);
EditorGUILayout.LabelField(new GUIContent(ios_version), versionWidthOption);
GUILayout.Space(3);
string[] iosVersions = pluginData.iosVersions;
if (iosVersions != null && iosVersions.Length > 0) {
List<int> iosVersionsInt = new List<int>();
int androidLength = iosVersions.Length;
for (int i = 0; i < androidLength; i = i + 1)
{
iosVersionsInt.Add(i);
}
// 创建Dropdown组件
iosVersionPopupIndex = EditorGUILayout.IntPopup(iosVersionPopupIndex, iosVersions, iosVersionsInt.ToArray(), versionWidthOption);
GUILayout.FlexibleSpace();
string selectedIosVersion = iosVersions[iosVersionPopupIndex];
string action = "Exchange";
if (!string.IsNullOrEmpty(ios_version) && Equals(ios_version, selectedIosVersion)) {
action = "Delete";
}
GUI.enabled = !Equals(ios_version, selectedIosVersion) || action == "Delete";
if (GUILayout.Button(new GUIContent(action), fieldWidth))
{
if (action == "Delete") {
DeleteSdkVersion(pluginData, iosVersionPopupIndex, ATConfig.OS_IOS);
} else {
ExChangeSDKVersion(pluginData, iosVersionPopupIndex, ATConfig.OS_IOS);
}
}
GUI.enabled = true;
GUILayout.Space(5);
} else {
EditorGUILayout.LabelField(new GUIContent("loading..."), versionWidthOption);
}
GUILayout.Space(3);
}
GUILayout.Space(4);
#if !UNITY_2018_2_OR_NEWER
EditorGUILayout.HelpBox("AnyThink Unity plugin will soon require Unity 2018.2 or newer to function. Please upgrade to a newer Unity version.", MessageType.Warning);
#endif
}
GUILayout.Space(5);
// GUILayout.EndHorizontal();
}
private void DrawSdkVersionOffTip()
{
if (pluginData == null) {
return;
}
var thinkup = pluginData.anyThink;
if (thinkup == null) {
return;
}
var android_version = "";
var ios_version = "";
if (thinkup != null) {
android_version = thinkup.CurrentVersions.Android;
ios_version = thinkup.CurrentVersions.Ios;
//判断android版本是否版本列表中
string[] androidVersions = pluginData.androidVersions;
string[] iosVersions = pluginData.iosVersions;
//The currently installed Android version and io version have been offline
StringBuilder sb = new StringBuilder();
sb.Append("Tips: The currently installed ");
var android_version_off = false;
if (!string.IsNullOrEmpty(android_version) && androidVersions != null && androidVersions.Length > 0) {
if (!IsCharInStringArray(android_version, androidVersions)) {
sb.Append("Android version(");
sb.Append(android_version);
sb.Append(") ");
android_version_off = true;
}
}
var ios_version_off = false;
if (!string.IsNullOrEmpty(ios_version) && iosVersions != null && iosVersions.Length > 0) {
if (!IsCharInStringArray(ios_version, iosVersions)) {
if (android_version_off) {
sb.Append("and ");
}
sb.Append("iOS version(");
sb.Append(ios_version);
sb.Append(") ");
ios_version_off = true;
}
}
if (android_version_off || ios_version_off) {
sb.Append("have been offline, please install the latest version.");
GUILayout.Space(4);
EditorGUILayout.LabelField(sb.ToString(), tipTextStyle);
GUILayout.Space(4);
} else {
sb.Clear();
}
}
}
private bool IsCharInStringArray(string character, string[] array)
{
// 遍历数组中的每个字符串
foreach (string str in array)
{
// 如果当前字符串包含指定的字符,则返回true
if (str == character)
{
return true;
}
}
// 如果没有找到字符,则返回false
return false;
}
private void DrawHeaders(string firstColumnTitle, bool drawAction)
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(5);
EditorGUILayout.LabelField(firstColumnTitle, headerLabelStyle, networkWidthOption);
EditorGUILayout.LabelField("Current Version", headerLabelStyle, versionWidthOption);
GUILayout.Space(3);
EditorGUILayout.LabelField("SDK Versions", headerLabelStyle, versionWidthOption);
GUILayout.Space(3);
if (drawAction)
{
GUILayout.FlexibleSpace();
GUILayout.Button("Actions", headerLabelStyle, fieldWidth);
GUILayout.Space(5);
}
}
GUILayout.Space(4);
}
private void DrawPluginDetailRow(string platform, string currentVersion, string sdkversions, string actions)
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(5);
EditorGUILayout.LabelField(new GUIContent(platform), networkWidthOption);
EditorGUILayout.LabelField(new GUIContent(currentVersion), versionWidthOption);
GUILayout.Space(3);
EditorGUILayout.LabelField(new GUIContent(sdkversions), versionWidthOption);
GUILayout.Space(3);
// EditorGUILayout.LabelField(new GUIContent(actions), versionWidthOption);
// GUILayout.Space(3);
}
GUILayout.Space(4);
}
private void DrawEmptyPluginData(string tip)
{
GUILayout.Space(5);
// Plugin data failed to load. Show error and retry button.
if (pluginDataLoadFailed)
{
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Space(5);
EditorGUILayout.LabelField("Failed to load plugin data. Please click retry or restart the integration manager.", titleLabelStyle);
if (GUILayout.Button("Retry", fieldWidth))
{
pluginDataLoadFailed = false;
loadPluginData();
}
GUILayout.Space(5);
GUILayout.EndHorizontal();
GUILayout.Space(10);
}
// Still loading, show loading label.
else
{
GUILayout.Space(10);
GUILayout.BeginHorizontal();
// GUILayout.FlexibleSpace();
EditorGUILayout.LabelField(tip, titleLabelStyle);
// GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Space(10);
}
GUILayout.Space(5);
}
//绘制Admob Id
private void DrawAdombAppId() {
var integrationManager = ATIntegrationManager.Instance;
bool isAdmobInstalledForAndroid = integrationManager.isAdmobInstalled(ATConfig.OS_ANDROID);
bool isAdmobInstalledForIos = integrationManager.isAdmobInstalled(ATConfig.OS_IOS);
if (isAdmobInstalledForAndroid || isAdmobInstalledForIos) {
EditorGUILayout.LabelField("Admob AppId", titleLabelStyle);
GUILayout.Space(5);
using (new EditorGUILayout.VerticalScope("box"))
{
GUILayout.Space(10);
if (isAdmobInstalledForAndroid) {
var androidAdmobAppId = DrawTextField("App ID (Android)", integrationManager.getAdmobAppIdByOs(pluginData, ATConfig.OS_ANDROID), networkWidthOption);
integrationManager.setAdmobAppidByOs(pluginData, ATConfig.OS_ANDROID, androidAdmobAppId);
}
if (isAdmobInstalledForIos) {
if (isAdmobInstalledForAndroid) {
GUILayout.Space(10);
}
var iosAdmobAppId = DrawTextField("App ID (iOS)", integrationManager.getAdmobAppIdByOs(pluginData, ATConfig.OS_IOS), networkWidthOption);
integrationManager.setAdmobAppidByOs(pluginData, ATConfig.OS_IOS, iosAdmobAppId);
}
}
}
}
private string DrawTextField(string fieldTitle, string text, GUILayoutOption labelWidth, GUILayoutOption textFieldWidthOption = null)
{
GUILayout.BeginHorizontal();
GUILayout.Space(4);
EditorGUILayout.LabelField(new GUIContent(fieldTitle), labelWidth);
GUILayout.Space(4);
text = (textFieldWidthOption == null) ? GUILayout.TextField(text) : GUILayout.TextField(text, textFieldWidthOption);
GUILayout.Space(4);
GUILayout.EndHorizontal();
GUILayout.Space(4);
return text;
}
private void DrawMediatedNetworks()
{
GUILayout.Space(5);
EditorGUILayout.LabelField("Ad Networks", titleLabelStyle);
GUILayout.Space(5);
GUILayout.BeginHorizontal();
using (new EditorGUILayout.VerticalScope("box"))
{
DrawHeaders("Network", true);
string clickTip = "You need to select an sdk version and click the Exchange button.";
// Immediately after downloading and importing a plugin the entire IDE reloads and current versions can be null in that case. Will just show loading text in that case.
if (pluginData == null)
{
ATLog.log("DrawMediatedNetworks failed.");
DrawEmptyPluginData("loading sdk data ...");
} else if(pluginData.mediatedNetworks == null) {
DrawEmptyPluginData(clickTip);
} else {
var networks = pluginData.mediatedNetworks;
var length = networks.Length;
ATLog.log("DrawMediatedNetworks() >>> networks length: " + length);
if (length == 0) {
DrawEmptyPluginData(clickTip);
return;
}
int versionEmptyLength = 0;
foreach (var network in networks)
{
if (network.isVersionEmpty()) {
// ATLog.log("DrawMediatedNetworks() >>> isVersionEmpty name: " + network.Name);
versionEmptyLength = versionEmptyLength + 1;
} else {
DrawNetworkDetailRow2(network);
}
}
ATLog.log("DrawMediatedNetworks() >>> versionEmptyLength: " + versionEmptyLength);
if (versionEmptyLength == length) {
DrawEmptyPluginData(clickTip);
}
GUILayout.Space(10);
}
}
GUILayout.Space(5);
GUILayout.EndHorizontal();
}
//绘制network的每一行
private void DrawNetworkDetailRow2(Network network) {
using (new EditorGUILayout.VerticalScope("box"))
{
GUILayout.Space(4);
string a_action = "";
string i_action = "";
string cur_a_version = "";
string cur_i_version = "";
string last_a_version = "";
string last_i_version = "";
if (network.CurrentVersions != null)
{
cur_a_version = network.CurrentVersions.Android;
cur_i_version = network.CurrentVersions.Ios;
}
if (network.LatestVersions != null)
{
last_a_version = network.LatestVersions.Android;
last_i_version = network.LatestVersions.Ios;
}
//Android Action按钮状态
ATLog.log("DrawNetworkDetailRow2() >>> cur_a_version: " + cur_a_version + " last_i_version: " + last_i_version +
" name: " + network.DisplayName + " last_a_version: " + last_a_version);
if (string.IsNullOrEmpty(cur_a_version)) {
a_action = "Install";
} else if (ATDataUtil.CompareVersions(cur_a_version, last_a_version) == VersionComparisonResult.Lesser) {
a_action = "Upgrade";
} else if(ATDataUtil.CompareVersions(cur_a_version, last_a_version) == VersionComparisonResult.Equal) {
a_action = "Installed";
}
bool hasAndroid = false;
if (!string.IsNullOrEmpty(last_a_version)) {
hasAndroid = true;
DrawRowNetwork(network, ATConfig.OS_ANDROID, cur_a_version, last_a_version, a_action, true);
}
//iOS Action按钮状态
// var i_compare_result = ATDataUtil.CompareVersions(cur_i_version, last_i_version);
if (string.IsNullOrEmpty(cur_i_version)) {
i_action = "Install";
} else if (ATDataUtil.CompareVersions(cur_i_version, last_i_version) == VersionComparisonResult.Lesser) {
i_action = "Upgrade";
} else if(ATDataUtil.CompareVersions(cur_i_version, last_i_version) == VersionComparisonResult.Equal) {
i_action = "Installed";
}
if (!string.IsNullOrEmpty(last_i_version)) {
DrawRowNetwork(network, ATConfig.OS_IOS, cur_i_version, last_i_version, i_action, !hasAndroid);
}
GUILayout.Space(4);
}
}
private void DrawRowNetwork(Network network, int os, string curVersion, string lastVersion, string action, bool isShowNetworkName)
{
GUILayout.Space(5);
if (os == ATConfig.OS_ANDROID) {
if (!string.IsNullOrEmpty(curVersion)) {
curVersion = "Android-" + curVersion;
} else {
curVersion = "Not Installed";
}
lastVersion = "Android-" + lastVersion;
} else {
if (!string.IsNullOrEmpty(curVersion)) {
curVersion = "iOS-" + curVersion;
} else {
curVersion = "Not Installed";
}
lastVersion = "iOS-" + lastVersion;
}
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandHeight(false)))
{
GUILayout.Space(5);
if (isShowNetworkName) {
EditorGUILayout.LabelField(new GUIContent(network.DisplayName), networkWidthOption);
} else {
EditorGUILayout.LabelField(new GUIContent(""), networkWidthOption);
}
EditorGUILayout.LabelField(new GUIContent(curVersion), versionWidthOption);
GUILayout.Space(3);
EditorGUILayout.LabelField(new GUIContent(lastVersion), versionWidthOption);
GUILayout.Space(3);
GUILayout.FlexibleSpace();
if (network.isReqiureUpdate())
{
GUILayout.Label(new GUIContent { image = alertIcon, tooltip = "Adapter not compatible, please update to the latest version." }, iconStyle);
}
GUI.enabled = action != "Installed";
if (GUILayout.Button(new GUIContent(action), fieldWidth))
{
ATIntegrationManager.Instance.networkInstallOrUpdate(pluginData, network, os);
}
GUI.enabled = true;
GUILayout.Space(2);
GUI.enabled = action == "Installed";
if (GUILayout.Button(new GUIContent { image = uninstallIcon, tooltip = "Uninstall" }, iconStyle))
{
EditorUtility.DisplayProgressBar("Integration Manager", "Deleting " + network.Name + "...", 0.5f);
ATIntegrationManager.Instance.uninstallNetwork(network, os);
//Refresh UI
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();
}
GUI.enabled = true;
GUILayout.Space(5);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 435df1e40057948a581aaa9c703eadba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,164 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using System.Threading.Tasks;
using System.Threading;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class ATIntegrationHotFix {
public static ATIntegrationHotFix Instance = new ATIntegrationHotFix();
private ATIntegrationHotFix()
{
}
private static string plugin_hot_fix_data_file_name = "plugin_hot_fix_data.json";
public void loadHotFixData()
{
var downloadUrl = ATNetInfo.getHotfixPluginDownloadUrl(ATConfig.PLUGIN_VERSION);
ATLog.log("loadHotFixData() >>> downloadUrl: " + downloadUrl);
ATEditorCoroutine.startCoroutine(loadHotFixDataWithIEnumerator(downloadUrl));
}
private IEnumerator loadHotFixDataWithIEnumerator(string url) {
var hotFixDataRequest = UnityWebRequest.Get(url);
var webRequest = hotFixDataRequest.SendWebRequest();
while (!webRequest.isDone)
{
yield return new WaitForSeconds(0.1f);
}
#if UNITY_2020_1_OR_NEWER
if (hotFixDataRequest.result != UnityWebRequest.Result.Success)
#elif UNITY_2017_2_OR_NEWER
if (hotFixDataRequest.isNetworkError || hotFixDataRequest.isHttpError)
#else
if (hotFixDataRequest.isError)
#endif
{
// Debug.Log("loadPluginData failed.");
// callback(null);
ATLog.log("load hotfix data failed.");
}
else
{
//解析热修复的数据
try {
string hotFixData = hotFixDataRequest.downloadHandler.text;
var hotFixDataObj = JsonUtility.FromJson<HotfixPluginData>(hotFixData);
ATLog.log("loadHotFixDataWithIEnumerator() >>> hotFixData: " + hotFixData);
//判断status是否需要进行热更新
if (hotFixDataObj.status != 1) {
ATLog.log("loadHotFixDataWithIEnumerator() >>> 热更新被禁止");
} else {
var localHotFixDataObj = getHotfixPluginData();
if (localHotFixDataObj == null) {
//本地未曾下载过热更新
ATLog.log("loadHotFixDataWithIEnumerator() >>> 本地未曾下载过热更新");
ATEditorCoroutine.startCoroutine(loadHotFixPlugin(hotFixDataObj));
} else {
var compareVersionResult = ATDataUtil.CompareVersions(localHotFixDataObj.hot_fix_version, hotFixDataObj.hot_fix_version);
ATLog.log("loadHotFixDataWithIEnumerator() >>> compareVersionResult: " + compareVersionResult);
//本地版本比远端版本低,则需要更新
if (compareVersionResult == VersionComparisonResult.Lesser) {
ATEditorCoroutine.startCoroutine(loadHotFixPlugin(hotFixDataObj));
} else {
//不需要热更新
saveHotfixData(hotFixData);
}
}
}
} catch(Exception e) {
ATLog.logError("parseNetworksJson() >>> failed: " + e);
}
}
}
private IEnumerator loadHotFixPlugin(HotfixPluginData hotFixDataObj) {
var path = Path.Combine(Application.temporaryCachePath, hotFixDataObj.file_name);
ATLog.log("downloadPluginWithEnumerator() >>> path: " + path);
#if UNITY_2017_2_OR_NEWER
var downloadHandler = new DownloadHandlerFile(path);
#else
var downloadHandler = new ATDownloadHandler(path);
#endif
var downloadUrl = hotFixDataObj.download_url;
UnityWebRequest downloadPluginRequest = new UnityWebRequest(downloadUrl)
{ method = UnityWebRequest.kHttpVerbGET,
downloadHandler = downloadHandler
};
#if UNITY_2017_2_OR_NEWER
var operation = downloadPluginRequest.SendWebRequest();
#else
var operation = downloadPluginRequest.Send();
#endif
while (!operation.isDone)
{
yield return new WaitForSeconds(0.1f); // Just wait till downloadPluginRequest is completed. Our coroutine is pretty rudimentary.
if (operation.progress != 1 && operation.isDone)
{
}
}
#if UNITY_2020_1_OR_NEWER
if (downloadPluginRequest.result != UnityWebRequest.Result.Success)
#elif UNITY_2017_2_OR_NEWER
if (downloadPluginRequest.isNetworkError || downloadPluginRequest.isHttpError)
#else
if (downloadPluginRequest.isError)
#endif
{
ATLog.log(downloadPluginRequest.error);
}
else
{
AssetDatabase.ImportPackage(path, false);
AssetDatabase.Refresh();
string hotFixData = JsonUtility.ToJson(hotFixDataObj);
saveHotfixData(hotFixData);
}
downloadPluginRequest.Dispose();
downloadPluginRequest = null;
}
private void saveHotfixData(string hotfixPluginData) {
var directoryPath = ATConfig.plugin_setting_data_path;
// 确保目标文件夹存在
if (!Directory.Exists(directoryPath))
{
// 如果目录不存在,则创建它
Directory.CreateDirectory(directoryPath);
}
string fullPath = Path.Combine(directoryPath, plugin_hot_fix_data_file_name);
ATLog.log("saveHotfixData() >>> fullPath: " + fullPath + " hotfixPluginData: " + hotfixPluginData);
File.WriteAllText(fullPath, hotfixPluginData);
}
private HotfixPluginData getHotfixPluginData() {
string fullPath = Path.Combine(ATConfig.plugin_setting_data_path, plugin_hot_fix_data_file_name);
if (!File.Exists(fullPath)) {
return null;
}
string json = File.ReadAllText(fullPath);
if(json == "") {
return null;
}
return JsonUtility.FromJson<HotfixPluginData>(json);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9261d30b7b2ae4a469e3428502ab201c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,37 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class ATLog {
public static bool isDebug = false;
public static void log(string msg)
{
// string msg =
if (isDebug) {
Debug.Log(msg);
}
}
public static void log(string tag, string msg)
{
if (isDebug) {
Debug.Log(tag + ": " + msg);
}
}
public static void logFormat(string msg, object[] args)
{
if (isDebug) {
Debug.LogFormat(msg, args);
}
}
public static void logError(string msg)
{
Debug.LogError(msg);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7535cfe4fd8d145fe896ce8d4099d1db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,37 @@
//菜单栏
using UnityEditor;
using UnityEngine;
// using DownloadManager;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public class AnyThinkMenuItems : MonoBehaviour
{
/**
* The special characters at the end represent a shortcut for this action.
*
* % - ctrl on Windows, cmd on macOS
* # - shift
* & - alt
*
* So, (shift + cmd/ctrl + t) will launch the integration manager
*/
[MenuItem("ThinkupTpnPlugin/SDK Manager %#t")]
private static void IntegrationManager()
{
ATIntegrationManagerWindow.ShowManager();
}
[MenuItem("ThinkupTpnPlugin/Documentation")]
public static void Documentation()
{
// if (ATConfig.isSelectedChina()) {
// Application.OpenURL("https://help.toponad.com/cn/docs/SDK-dao-ru-shuo-ming");
// } else {
// Application.OpenURL("https://docs.toponad.com/#/en-us/unity/unity_doc/unity_access_doc_new?id=_3-integration");
// }
Application.OpenURL("https://help.toponad.com/cn/docs/SDK-dao-ru-shuo-ming");
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe6ef4ba2bbf2480187401f5626e19a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
public static class ATNetInfo {
//插件的配置文件:unity_plugin_config.json
public static string getPluginConfigUrl(String plugin_version)
{
return "https://topon-sdk-release.oss-cn-hangzhou.aliyuncs.com/Unity_Release_Thinkup_TPN/plugin/" + plugin_version + "/unity_plugin_config.json";
}
//插件版本对应的network列表文件:unity_plugin_config_network.json
public static string getNetworkListUrl(String plugin_version)
{
return "https://topon-sdk-release.oss-cn-hangzhou.aliyuncs.com/Unity_Release_Thinkup_TPN/plugin/" + plugin_version + "/unity_plugin_config_network.json";
}
//插件unitypackage名字
public static string getPluginFileName(string pluginVersion)
{
return "ThinkupTpnPlugin_" + pluginVersion + ".unitypackage";
}
//插件unitypackage的下载链接
public static string getPluginDownloadUrl(string pluginVersion)
{
return "https://topon-sdk-release.oss-cn-hangzhou.aliyuncs.com/Unity_Release_Thinkup_TPN/plugin/" + pluginVersion + "/" + getPluginFileName(pluginVersion);
}
public static string getHotfixPluginDownloadUrl(string pluginVersion)
{
return "https://topon-sdk-release.oss-cn-hangzhou.aliyuncs.com/Unity_Release_Thinkup_TPN/plugin/" + pluginVersion + "/hotfix/hotfix_config.json";
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf2e8a6c6aabc44329d491a7c9709e33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,220 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
namespace AnyThink.Scripts.IntegrationManager.Editor
{
[Serializable]
public class PluginData
{
public string pluginVersion; //插件版本
public string[] androidVersions;
public string[] iosVersions;
public int country = ATConfig.getDefCountry(); //默认是1=china
public Network anyThink;
public Network[] mediatedNetworks;
public PluginSettingData pluginSettingData;
public NetworkRequestParams requestParams;
}
//请求network参数
public class NetworkRequestParams {
public int os;
public string androidVersion;
public string iosVersion;
}
[Serializable]
public class Network : IComparable<Network>
{
//
// Sample network data:
//
// {
// "Name": "adcolony",
// "DisplayName": "AdColony",
// "DownloadUrl": "https://bintray.com/applovin/Unity-Mediation-Packages/download_file?file_path=AppLovin-AdColony-Adapters-Android-3.3.10.1-iOS-3.3.7.2.unitypackage",
// "PluginFileName": "AppLovin-AdColony-Adapters-Android-3.3.10.1-iOS-3.3.7.2.unitypackage",
// "DependenciesFilePath": "MaxSdk/Mediation/AdColony/Editor/Dependencies.xml",
// "LatestVersions" : {
// "Unity": "android_3.3.10.1_ios_3.3.7.2",
// "Android": "3.3.10.1",
// "Ios": "3.3.7.2"
// }
// }
//
public string Name;
public string DisplayName;
public string AndroidDownloadUrl;
public string iOSDownloadloadUrl;
// public string DependenciesFilePath;
public string PluginFileName;
public int Country;
public Versions LatestVersions; //最新版本
public Versions CurrentVersions; //当前版本
[NonSerialized] public VersionComparisonResult CurrentToLatestVersionComparisonResult = VersionComparisonResult.Equal;
// [NonSerialized] public bool RequiresUpdate = CurrentToLatestVersionComparisonResult == VersionComparisonResult.Lesser;
public bool isVersionEmpty() {
if (LatestVersions != null) {
ATLog.log("isVersionEmpty() >>> name: " + Name + " android: " + LatestVersions.Android + " ios: " + LatestVersions.Ios);
return string.IsNullOrEmpty(LatestVersions.Android) && string.IsNullOrEmpty(LatestVersions.Ios);
}
return false;
}
public bool isReqiureUpdate()
{
return CurrentToLatestVersionComparisonResult == VersionComparisonResult.Lesser;
}
public int CompareTo(Network other)
{
return this.DisplayName.CompareTo(other.DisplayName);
}
public string ToString() {
return DisplayName + "-" + AndroidDownloadUrl + "-" + iOSDownloadloadUrl + "-" + Country;
}
}
/// <summary>
/// A helper data class used to get current versions from Dependency.xml files.
/// </summary>
[Serializable]
public class Versions
{
public string Unity;
public string Android;
public string Ios;
public override bool Equals(object value)
{
var versions = value as Versions;
return versions != null
&& (Unity == null || Unity.Equals(versions.Unity))
&& (Android == null || Android.Equals(versions.Android))
&& (Ios == null || Ios.Equals(versions.Ios));
}
public bool HasEqualSdkVersions(Versions versions)
{
return versions != null && versions.Android == Android && versions.Ios == Ios;
}
public override int GetHashCode()
{
return new { Unity, Android, Ios }.GetHashCode();
}
public Versions clone()
{
Versions cloneObj = new Versions();
cloneObj.Android = Android;
cloneObj.Ios = Ios;
cloneObj.Unity = Unity;
return cloneObj;
}
}
public enum VersionComparisonResult
{
Lesser = -1,
Equal = 0,
Greater = 1
}
//存在本地插件设置数据并序列化为json文件
[Serializable]
public class PluginSettingData
{
public int curCountry = ATConfig.getDefCountry(); //当前选择的国家
public CountrySettingData china = new CountrySettingData(ATConfig.CHINA_COUNTRY); //国内地区
public CountrySettingData nonchina = new CountrySettingData(ATConfig.NONCHINA_COUNTRY); //海外地区
public CountrySettingData getCountrySettingData() {
if (curCountry == ATConfig.CHINA_COUNTRY) {
return china;
} else {
return nonchina;
}
}
//Android 是否同时安装了国内海外地区
public bool isBothInstallAndroid() {
return !string.IsNullOrEmpty(china.android_version) && !string.IsNullOrEmpty(nonchina.android_version);
}
//iOS 是否同时安装了国内海外地区
public bool isBothInstallIOS() {
return !string.IsNullOrEmpty(china.ios_version) && !string.IsNullOrEmpty(nonchina.ios_version);
}
}
//已安装的sdk版本
[Serializable]
public class CountrySettingData
{
public string android_version; //当前已安装Android sdk的版本号
public string ios_version; //当前已安装的iOS sdk的版本号
public int androidXSetting = 0; //当前的AndroidX设置,0=default; 1=修改为AndroidX2=修改为非AndroidX
public int country;
public string android_admob_app_id;
public string ios_admob_app_id;
public CountrySettingData(int country) {
this.country = country;
}
public string getAdmobAppId(int os) {
if (os == ATConfig.OS_ANDROID) {
return android_admob_app_id;
} else {
return ios_admob_app_id;
}
}
public void setAdmobAppId(string appId, int os) {
if (os == ATConfig.OS_ANDROID) {
android_admob_app_id = appId;
} else {
ios_admob_app_id = appId;
}
}
}
//存储在本地的Network json数据
[Serializable]
public class NetworkLocalData
{
public string name;
public string version;
public int country;
public string path;
}
[Serializable]
public class HotfixPluginData
{
public string plugin_version;
public string hot_fix_version;
public string download_url;
public int status;
public string file_name;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9a01fc414249b4d609e2db2ea9cc1876
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
// #if UNITY_EDITOR //是Unity编辑器才引入
using UnityEditor;
// #endif
public class ATSdkUtil
{
// #if UNITY_EDITOR
/// <summary>
/// Gets the path of the asset in the project for a given Anythink plugin export path.
/// </summary>
/// <param name="exportPath">The actual exported path of the asset.</param>
/// <returns>The exported path of the MAX plugin asset or the default export path if the asset is not found.</returns>
public static string GetAssetPathForExportPath(string exportPath)
{
var defaultPath = Path.Combine("Assets", exportPath);
var assetLabelToFind = "l:al_max_export_path-" + exportPath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var assetGuids = AssetDatabase.FindAssets(assetLabelToFind);
return assetGuids.Length < 1 ? defaultPath : AssetDatabase.GUIDToAssetPath(assetGuids[0]);
}
public static bool Exists(string filePath)
{
return Directory.Exists(filePath) || File.Exists(filePath);
}
// #endif
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f128e7cd9651c48e5939333cccd9e821
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,10 @@
{
"name": "ThinkupTpnPlugin.Script.IntegrationManager.Editor",
"references": [
"ThinkupTpnPlugin.Script"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": []
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d9801a1b5d6474105846c4dc70b24ef3
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: