diff --git a/ExtraPluginCfgs/Android/flexion/ConfigManager.java b/ExtraPluginCfgs/Android/flexion/ConfigManager.java index 4d30160..1727c92 100644 --- a/ExtraPluginCfgs/Android/flexion/ConfigManager.java +++ b/ExtraPluginCfgs/Android/flexion/ConfigManager.java @@ -6,7 +6,7 @@ public class ConfigManager { public static String SDK_GAMEID = "20587"; public static String SDK_PROJECTID = "20587"; public static String SDK_CLOUDID = "128"; - public static String SDK_CLIENTID = "Android_5.00_tyGuest,facebook.googleplay.0-hall20587.googleplay.FishingMaster"; + public static String SDK_CLIENTID = "Android_5.00_tyGuest,facebook.googleplay.0-hall20587.flexion.FishingMaster"; public static String SDK_LOGIN_SERVER_URL = "https://128-hwsfsdk-sdk-online01.qijihdhk.com"; diff --git a/ExtraPluginCfgs/Android/flexion/FlexionSDKHelper.java b/ExtraPluginCfgs/Android/flexion/FlexionSDKHelper.java index bc60ef3..1da70de 100644 --- a/ExtraPluginCfgs/Android/flexion/FlexionSDKHelper.java +++ b/ExtraPluginCfgs/Android/flexion/FlexionSDKHelper.java @@ -46,6 +46,7 @@ public class FlexionSDKHelper implements SDKManager.ISDKHelper { public void init(Activity activity) { activity.runOnUiThread(() -> { SDKAPI.getIns().lightModeEnable(); + boolean sdkInitOk = false; try { SDKAPI.getIns().init(new InitParam.Builder() .withActivity(activity) @@ -55,23 +56,27 @@ public class FlexionSDKHelper implements SDKManager.ISDKHelper { .build()); SDKAPI.getIns().onActivityStart(activity); SDKAPI.getIns().onActivityResume(activity); + sdkInitOk = true; } catch (Exception e) { - Log.e(TAG, "TuYoo SDK init Exception: " + e); + Log.e(TAG, "TuYoo SDK init failed, skip FLX init: " + e); + TYUnityActivity.setSdkInited(); } - FLX.init(activity, (initCode, initMsg) -> { - Log.i(TAG, "FLX.init result=" + initCode); - if (initCode == 0) { - FLX.showFlexionScreens(activity, (screenCode, screenMsg) -> { - Log.i(TAG, "FLX.showFlexionScreens result=" + screenCode); - initBillingService(activity); + if (sdkInitOk) { + FLX.init(activity, (initCode, initMsg) -> { + Log.i(TAG, "FLX.init result=" + initCode); + if (initCode == 0) { + FLX.showFlexionScreens(activity, (screenCode, screenMsg) -> { + Log.i(TAG, "FLX.showFlexionScreens result=" + screenCode); + initBillingService(activity); + TYUnityActivity.setSdkInited(); + }); + } else { + Log.e(TAG, "FLX.init failed: " + initCode); TYUnityActivity.setSdkInited(); - }); - } else { - Log.e(TAG, "FLX.init failed: " + initCode); - TYUnityActivity.setSdkInited(); - } - }); + } + }); + } }); } diff --git a/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle b/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle index 814c5c6..0505686 100644 --- a/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle +++ b/sdk-intergration/Assets/Plugins/Android/mainTemplate.gradle @@ -13,7 +13,14 @@ android { } // Android Resolver Exclusions End android { - namespace "com.unity3d.player" + namespace "com.unity3d.player" +} + +// Flexion 渠道专用:排除不需要的 AppsFlyer 模块 +// - purchase-connector: 基于 Google Play Billing,Flexion 不走 GP 计费,没用还增大包 +// 即使 Unity Android Resolver 下次又把 implementation 行写回来,这里的 exclude 也兜底排除 +configurations.all { + exclude group: 'com.appsflyer', module: 'purchase-connector' } dependencies { @@ -31,13 +38,17 @@ dependencies { api "io.reactivex:rxandroid:1.2.1" api "io.reactivex:rxjava:1.1.9" - // Google Play In-App Review + // Google Play In-App Review implementation 'com.google.android.play:review:2.0.1' + // Google Play Billing — tuyoosdk AAR references BillingManager during init + implementation 'com.android.billingclient:billing:6.0.1' implementation 'net.aihelp:android-aihelp-aar:5.3.+' implementation 'com.google.android.gms:play-services-auth:20.2.0' - implementation('com.android.billingclient:billing:7.0.0') - + + // Flexion SDK (includes wrapped billing) + implementation("com.flexionmobile:sdk:4.0.1") + implementation 'com.google.android.gms:play-services-basement:18.2.0' implementation 'androidx.fragment:fragment:1.3.6' implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.41" @@ -48,7 +59,7 @@ dependencies { implementation 'com.miui.referrer:homereferrer:1.0.0.6' - implementation platform('com.google.firebase:firebase-bom:34.6.0') + implementation platform('com.google.firebase:firebase-bom:32.7.4') implementation 'com.google.firebase:firebase-analytics' implementation('com.facebook.android:facebook-android-sdk:16.2.0') @@ -59,6 +70,8 @@ dependencies { implementation "androidx.credentials:credentials-play-services-auth:1.3.0" implementation "com.google.android.libraries.identity.googleid:googleid:1.1.1" + coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.1.2" + // Android Resolver Dependencies Start implementation 'com.android.installreferrer:installreferrer:2.1' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:7 implementation 'com.applovin.mediation:facebook-adapter:[6.18.0.1]' // Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml:8 @@ -69,20 +82,35 @@ dependencies { implementation 'com.applovin.mediation:vungle-adapter:7.4.2.2' // Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml:4 implementation 'com.applovin:applovin-sdk:13.5.1' // Assets/MaxSdk/AppLovin/Editor/Dependencies.xml:4 implementation 'com.appsflyer:af-android-sdk:6.17.3' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:5 - implementation 'com.appsflyer:purchase-connector:2.2.0' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:8 + // Flexion: purchase-connector removed — Flexion does not use Google Play Billing. + // Also covered by top-level `configurations.all { exclude ... }` as a safety net. + // implementation 'com.appsflyer:purchase-connector:2.2.0' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:8 implementation 'com.appsflyer:unity-wrapper:6.17.7' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:6 implementation 'com.google.android.ump:user-messaging-platform:2.1.0' // Assets/MaxSdk/AppLovin/Editor/Dependencies.xml:5 // Android Resolver Dependencies End **DEPS**} +// Android Resolver Exclusions Start +android { + packagingOptions { + exclude ('/lib/armeabi/*' + '*') + exclude ('/lib/mips/*' + '*') + exclude ('/lib/mips64/*' + '*') + exclude ('/lib/x86/*' + '*') + exclude ('/lib/x86_64/*' + '*') + } +} +// Android Resolver Exclusions End android { ndkPath "**NDKPATH**" compileSdkVersion **APIVERSION** buildToolsVersion '**BUILDTOOLS**' + compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 + coreLibraryDesugaringEnabled true } defaultConfig { @@ -91,6 +119,7 @@ android { ndk { abiFilters **ABIFILTERS** } + versionCode **VERSIONCODE** versionName '**VERSIONNAME**' consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD** diff --git a/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle b/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle index 73133c1..169416f 100644 --- a/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle +++ b/sdk-intergration/Assets/Plugins/Android/settingsTemplate.gradle @@ -16,6 +16,17 @@ dependencyResolutionManagement { **ARTIFACTORYREPOSITORY** google() mavenCentral() + + // Flexion SDK Maven Repository + maven { + url = uri("https://maven.pkg.github.com/FlexionSDK/JavaSDK") + credentials { + username = "FlexionSDK" + // Replace with your actual Flexion PAT from DropPoint + password = "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" + } + } + // Android Resolver Repos Start def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/") maven { diff --git a/sdk-intergration/Packages/tysdk/Files/google-services.json b/sdk-intergration/Packages/tysdk/Files/google-services.json index 8ae069a..c390912 100644 --- a/sdk-intergration/Packages/tysdk/Files/google-services.json +++ b/sdk-intergration/Packages/tysdk/Files/google-services.json @@ -2,7 +2,7 @@ "project_info": { "project_number": "481260393117", "project_id": "fishing-travel", - "storage_bucket": "fishing-travel.appspot.com" + "storage_bucket": "fishing-travel.firebasestorage.app" }, "client": [ { @@ -21,6 +21,14 @@ "certificate_hash": "c9cf2f5eaba383cbdd5b968d0342c49afabc32a2" } }, + { + "client_id": "481260393117-vfn1jueugjqjach8kgc0kfi54g085q6l.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.arkgame.ft", + "certificate_hash": "53fd6ff623712411792a4665163e4cbf4a7a22ec" + } + }, { "client_id": "481260393117-0ah0ekk7lu5r44ko2uqlfoebgak8dmhj.apps.googleusercontent.com", "client_type": 3 @@ -37,6 +45,51 @@ { "client_id": "481260393117-0ah0ekk7lu5r44ko2uqlfoebgak8dmhj.apps.googleusercontent.com", "client_type": 3 + }, + { + "client_id": "481260393117-88n0v3ht8ashhk0r5ri47hced7o5qj62.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.arkgame.ft", + "app_store_id": "6505145935" + } + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:481260393117:android:eafec4a060b0224907fa74", + "android_client_info": { + "package_name": "com.arkgame.ft.flexion" + } + }, + "oauth_client": [ + { + "client_id": "481260393117-0ah0ekk7lu5r44ko2uqlfoebgak8dmhj.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyBU6gAwu0O28jg7-TRd_Vx2YMCH_Baa8Bw" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "481260393117-0ah0ekk7lu5r44ko2uqlfoebgak8dmhj.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "481260393117-88n0v3ht8ashhk0r5ri47hced7o5qj62.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.arkgame.ft", + "app_store_id": "6505145935" + } } ] } diff --git a/sdk-intergration/Packages/tysdk/Plugins/Android/ChannelHelpers.java b/sdk-intergration/Packages/tysdk/Plugins/Android/ChannelHelpers.java index b62fba6..000d512 100644 --- a/sdk-intergration/Packages/tysdk/Plugins/Android/ChannelHelpers.java +++ b/sdk-intergration/Packages/tysdk/Plugins/Android/ChannelHelpers.java @@ -1,12 +1,16 @@ package com.unity3d.player; public class ChannelHelpers { - public static final String CHANNEL = "GooglePlay"; + + public static final String CHANNEL = "Flexion"; static void register() { - // GooglePlay uses default behavior, no additional SDKHelper + SDKManager.registerHelper(CHANNEL, new FlexionSDKHelper()); } + + // Flexion provides price in micros and currency code, so no normalization needed + // 支付的变化,可能会修改这里 public static String normalizeSkuList(String msg) { return msg; } diff --git a/sdk-intergration/Packages/tysdk/Plugins/Android/ConfigManager.java b/sdk-intergration/Packages/tysdk/Plugins/Android/ConfigManager.java index 4d30160..1727c92 100644 --- a/sdk-intergration/Packages/tysdk/Plugins/Android/ConfigManager.java +++ b/sdk-intergration/Packages/tysdk/Plugins/Android/ConfigManager.java @@ -6,7 +6,7 @@ public class ConfigManager { public static String SDK_GAMEID = "20587"; public static String SDK_PROJECTID = "20587"; public static String SDK_CLOUDID = "128"; - public static String SDK_CLIENTID = "Android_5.00_tyGuest,facebook.googleplay.0-hall20587.googleplay.FishingMaster"; + public static String SDK_CLIENTID = "Android_5.00_tyGuest,facebook.googleplay.0-hall20587.flexion.FishingMaster"; public static String SDK_LOGIN_SERVER_URL = "https://128-hwsfsdk-sdk-online01.qijihdhk.com"; diff --git a/sdk-intergration/Packages/tysdk/Plugins/Android/FlexionSDKHelper.java b/sdk-intergration/Packages/tysdk/Plugins/Android/FlexionSDKHelper.java new file mode 100644 index 0000000..1da70de --- /dev/null +++ b/sdk-intergration/Packages/tysdk/Plugins/Android/FlexionSDKHelper.java @@ -0,0 +1,237 @@ +package com.unity3d.player; + +import android.app.Activity; +import android.util.Log; + +import com.flexionmobile.ddpx.listener.ConnectionStateListener; +import com.flexionmobile.ddpx.listener.PurchasesUpdateListener; +import com.flexionmobile.ddpx.model.BillingResult; +import com.flexionmobile.ddpx.model.BillingResults; +import com.flexionmobile.ddpx.model.Purchase; +import com.flexionmobile.ddpx.model.ProductDetails; +import com.flexionmobile.ddpx.model.params.BillingFlowParams; +import com.flexionmobile.ddpx.model.params.ConsumeParams; +import com.flexionmobile.ddpx.model.params.QueryPurchasesParams; +import com.flexionmobile.ddpx.model.params.ProductDetailsParams; +import com.flexionmobile.ddpx.service.BillingService; +import com.flexionmobile.fdk.FLX; + +import com.tuyoo.gamesdk.api.SDKAPI; +import com.tuyoo.gamesdk.api.SDKCallBack; +import com.tuyoo.gamesdk.model.InitParam; +import com.tuyoo.gamesdk.util.SDKLog; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.List; + +public class FlexionSDKHelper implements SDKManager.ISDKHelper { + private static final String TAG = "FlexionSDKHelper"; + private static BillingService billingService; + private static boolean billingConnected = false; + + private static final PurchasesUpdateListener purchasesListener = (billingResult, purchase) -> { + if (billingResult.getResponseCode() == BillingResults.ResultCode.PURCHASE_SUCCESS_CODE) { + if (purchase != null) handlePurchase(purchase); + } else if (billingResult.getResponseCode() == BillingResults.ResultCode.PURCHASE_USER_CANCELLED_CODE) { + sendPayCallback(1, "user_cancelled", null, null); + } else { + sendPayCallback(1, "purchase_failed_" + billingResult.getResponseCode(), null, null); + } + }; + + @Override + public void init(Activity activity) { + activity.runOnUiThread(() -> { + SDKAPI.getIns().lightModeEnable(); + boolean sdkInitOk = false; + try { + SDKAPI.getIns().init(new InitParam.Builder() + .withActivity(activity) + .withAppId(ConfigManager.SDK_APPID) + .withClientId(ConfigManager.SDK_CLIENTID) + .withServerUrl(ConfigManager.SDK_LOGIN_SERVER_URL) + .build()); + SDKAPI.getIns().onActivityStart(activity); + SDKAPI.getIns().onActivityResume(activity); + sdkInitOk = true; + } catch (Exception e) { + Log.e(TAG, "TuYoo SDK init failed, skip FLX init: " + e); + TYUnityActivity.setSdkInited(); + } + + if (sdkInitOk) { + FLX.init(activity, (initCode, initMsg) -> { + Log.i(TAG, "FLX.init result=" + initCode); + if (initCode == 0) { + FLX.showFlexionScreens(activity, (screenCode, screenMsg) -> { + Log.i(TAG, "FLX.showFlexionScreens result=" + screenCode); + initBillingService(activity); + TYUnityActivity.setSdkInited(); + }); + } else { + Log.e(TAG, "FLX.init failed: " + initCode); + TYUnityActivity.setSdkInited(); + } + }); + } + }); + } + + @Override + public void pay(Activity activity, String productId, String productName, + String productCount, String prodorderId, String appInfo) { + Log.i(TAG, "pay: " + productId); + if (billingService == null || !billingConnected) { + sendPayCallback(1, "billing_not_ready", null, null); + return; + } + activity.runOnUiThread(() -> + billingService.launchBillingFlow(activity, + new BillingFlowParams(productId, "inapp", ""))); + } + + @Override + public void queryProducts() { + if (billingService == null || !billingConnected) { + sendExtensionError("billing_not_ready"); + return; + } + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("action", "ACTION_GET_SKU_DETAILS_LIST"); + } catch (JSONException e) { + throw new RuntimeException(e); + } + SDKAPI.getIns().thirdExtend(jsonObject.toString(), new SDKCallBack.Extend() { + @Override + public void callback(int code, String msg) { + if (code == SDKCallBack.Extend.EXTEND_CODE_SUCCESS && msg != null) { + try { + JSONArray products = new JSONArray(msg); + List productIds = new java.util.ArrayList<>(); + for (int i = 0; i < products.length(); i++) { + JSONObject p = products.getJSONObject(i); + String pid = p.optString("productId", ""); + if (!pid.isEmpty()) productIds.add(pid); + } + queryProductDetails(productIds); + } catch (JSONException e) { + sendExtensionError("parse_error: " + e.getMessage()); + } + } else { + sendExtensionError("tuyoo_query_failed: " + msg); + } + } + }); + } + + // ---- Billing Infrastructure ---- + + private static void initBillingService(Activity activity) { + billingService = FLX.createBillingService(activity, purchasesListener); + billingService.startConnection(activity, new ConnectionStateListener() { + @Override + public void onBillingSetupFinished(BillingResult result) { + if (result.getResponseCode() == BillingResults.ResultCode.CONNECTION_SUCCESS_CODE) { + billingConnected = true; + queryPendingPurchases(); + } + } + @Override + public void onBillingServiceDisconnected() { + billingConnected = false; + } + }); + } + + private static void handlePurchase(Purchase purchase) { + if (purchase.getPurchaseState() == 0) { + sendPayCallback(0, "success", purchase.getPurchaseJson(), purchase.getSignature()); + billingService.consumeAsync( + new ConsumeParams(purchase.getToken()), + r -> Log.i(TAG, "Consume " + + (r.getResponseCode() == BillingResults.ResultCode.CONSUME_SUCCESS_CODE ? "ok" : "fail"))); + } else if (purchase.getPurchaseState() == 2) { + sendPayCallback(2, "pending", null, null); + } + } + + private static void queryPendingPurchases() { + if (billingService == null || !billingConnected) return; + billingService.queryPurchasesAsync( + new QueryPurchasesParams("inapp"), + (result, purchases) -> { + if (purchases != null) for (Purchase p : purchases) handlePurchase(p); + }); + } + + private static void queryProductDetails(List productIds) { + billingService.queryProductDetailsAsync( + new ProductDetailsParams("inapp", productIds), + (billingResult, productDetails) -> { + try { + JSONObject result = new JSONObject(); + if (billingResult.getResponseCode() == BillingResults.ResultCode.QUERY_PRODUCT_DETAILS_SUCCESS_CODE + && productDetails != null) { + JSONArray arr = new JSONArray(); + for (ProductDetails detail : productDetails) { + JSONObject item = new JSONObject(); + item.put("productId", detail.getId()); + item.put("ourProductId", detail.getId()); + item.put("title", detail.getTitle()); + item.put("description", detail.getDescription()); + item.put("price", detail.getPrice()); + item.put("price_amount_micros", detail.getPriceAmountMicros()); + item.put("price_currency_code", detail.getPriceCurrencyCode()); + item.put("type", detail.getType()); + arr.put(item); + } + result.put("code", 0); + result.put("respObj", arr.toString()); + } else { + result.put("code", 1); + result.put("thirdExtend_errStr", + "flexion_query_failed: " + billingResult.getDebugMessage()); + } + UnityPlayer.UnitySendMessage(ConfigManager.UNITY_FACADE_NAME, + ConfigManager.PAY_TYPE_CALLBACK_FUNCTION_NAME, result.toString()); + } catch (JSONException e) { + UnityPlayer.UnitySendMessage(ConfigManager.UNITY_FACADE_NAME, + ConfigManager.PAY_TYPE_CALLBACK_FUNCTION_NAME, "{\"code\":1}"); + } + }); + } + + // ---- Callbacks to Unity ---- + + private static void sendPayCallback(int code, String errStr, String purchaseJson, String signature) { + try { + JSONObject result = new JSONObject(); + result.put("code", code); + result.put("errStr", errStr != null ? errStr : ""); + if (purchaseJson != null) result.put("purchaseJson", purchaseJson); + if (signature != null) result.put("signature", signature); + UnityPlayer.UnitySendMessage(ConfigManager.UNITY_FACADE_NAME, + ConfigManager.PAY_CALLBACK_FUNCTION_NAME, result.toString()); + } catch (JSONException e) { + UnityPlayer.UnitySendMessage(ConfigManager.UNITY_FACADE_NAME, + ConfigManager.PAY_CALLBACK_FUNCTION_NAME, "{\"code\":1,\"errStr\":\"json_error\"}"); + } + } + + private static void sendExtensionError(String errStr) { + try { + JSONObject result = new JSONObject(); + result.put("code", 1); + result.put("thirdExtend_errStr", errStr); + UnityPlayer.UnitySendMessage(ConfigManager.UNITY_FACADE_NAME, + ConfigManager.PAY_TYPE_CALLBACK_FUNCTION_NAME, result.toString()); + } catch (JSONException e) { + UnityPlayer.UnitySendMessage(ConfigManager.UNITY_FACADE_NAME, + ConfigManager.PAY_TYPE_CALLBACK_FUNCTION_NAME, "{\"code\":1}"); + } + } +} diff --git a/sdk-intergration/Packages/tysdk/Plugins/Android/FlexionSDKHelper.java.meta b/sdk-intergration/Packages/tysdk/Plugins/Android/FlexionSDKHelper.java.meta new file mode 100644 index 0000000..147e335 --- /dev/null +++ b/sdk-intergration/Packages/tysdk/Plugins/Android/FlexionSDKHelper.java.meta @@ -0,0 +1,32 @@ +fileFormatVersion: 2 +guid: 4932bae8b9e69a447b0e2d7d3bcd0917 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Android: Android + second: + enabled: 1 + settings: {} + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdk-intergration/Packages/tysdk/Plugins/Android/tuyoosdk_1.0.0.aar b/sdk-intergration/Packages/tysdk/Plugins/Android/tuyoosdk_1.0.0.aar index 6576bb4..b16d93c 100644 Binary files a/sdk-intergration/Packages/tysdk/Plugins/Android/tuyoosdk_1.0.0.aar and b/sdk-intergration/Packages/tysdk/Plugins/Android/tuyoosdk_1.0.0.aar differ