Athana SDK

For Games

Unity 集成

安装插件

  • 方式一:本地 UnityPackage 安装
  • 方式二:通过 Git URL 安装
    • 打开 Package Manager (Window -> Package Manger)
    • 点击左上角 + 图标,选择:Install Package form git URL
    • 输入:https://github.com/AthanaSDK/athana_unity_plugin.git

集成配置

  1. 确认 Edit -> Project Settings -> Player -> Settings for Android -> Publishing Settings -> Build 中,勾选:

    • Custom Launcher Gradle Template
    • Custom Base Gradle Template
  2. 编辑 ${UNITY_PROJEECT}\Assets\Plugins\Android\baseProjectTemplate.gradle

1
2
3
4
5
6
7
8
9
10
11
12
plugins {
...

// 插入插件声明↓
id "org.jetbrains.kotlin.android" version "2.0.21" apply false
id "com.google.gms.google-services" version "4.4.2" apply false
id "com.google.firebase.crashlytics" version "3.0.4" apply false

**BUILD_SCRIPT_DEPS**
}

...
  1. 编辑 ${UNITY_PROJEECT}\Assets\Plugins\Android\launcherTemplate.gradle
1
2
3
4
5
6
apply plugin: 'com.android.application'
// 插入插件应用 ↓
apply plugin: 'org.jetbrains.kotlin.android'
apply from: 'athana_options.gradle'

...
  1. 进入配置面板(Unity Editor -> Assets -> Athana -> Sdk Configuration),填选数据

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

public class MainSceneController : MonoBehaviour
{
void Start()
{
...
InitAthanaSdk()
...
// 在合适的时机(隐私政策确认后、用户注册账户时),启动 Athana
AthanaSdk.Start(false);
}

private void InitAthanaSdk()
{
long appId = 00000000000;
string appKey = "******************";
string appSecret = "*****************************";

// 三方SDK配置
string appsFlyerDevKey = "******************";
string maxDevKey = "******************";
string googleWebClintId = "******************";

// 如果需要开启调试或内购测试模式,请开启对应参数
bool testMode = false; // 内购测试模式
bool debug = false; // 调试模式

// 如果需要进行预加载,则添加相应配置
var preloadAds = new Dictionary<AdType, string>() {
{ AdType.AppOpen, "******************" },
{ AdType.Rewarded, "******************" },
{ AdType.Interstitial, "******************" },
};

AthanaSdk.Initialize(appId, appKey, appSecret, testMode: testMode, debug: debug, serviceConfig: new()
{
// 按需选择服务配置:
// 三方登录配置(可选)
AccountConfig = new()
{
googleWebClientId = googleWebClintId,
},
// 广告配置(可选)
AdServiceConfigs = new()
{
// AppLovin MAX 配置
max = new()
{
sdkKey = maxDevKey,
debug = debug, // 是否开启 MAX 的调试日志
preloadAds = AthanaUtils.preloadAds2String(preloadAds)
}
},
// 归因配置(可选)
ConversionServiceConfigs = new()
{
// AppsFlyer 配置
appsflyer = new()
{
sdkKey = appsFlyerDevKey,
}
}
});

}
}

功能调用

  • 对于没有后端、账户体系的游戏,在 SDK 初始化后,需要走 注册平台账户 流程;
  • 对于有账户体系的游戏,在 SDK 初始化后,可参照以下流程:
    • 通过Athana.CurrentUser()查询当前是否有登录账户
    • 如果没有则可:注册游客账户 或 跳转至登录方式选择页面
    • 在通过新手教程后,引导用户绑定三方账号
    • 查询当前账户的三方登录绑定状态:``

注册平台账户

适用于无账户体系的游戏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<SdkCallback<AccountInfo?>>? onCurrentUserResult;
private Action<SdkCallback<AccountInfo>>? onRegistryUserResult;

// 判断当前注册状态
public void CurrentUser()
{
if (onCurrentUserResult == null)
{
onCurrentUserResult = (SdkCallback<AthanaInterface.AccountInfo?> result) =>
{
if (result.isSuccess())
{
var data = result.data;
if (data == null)
{
// 未登录或凭证失效
RegistryUser()
}
else
{
// 已登录
// 进入游戏
}
}
else
{
// 调用失败
Debug.Log("Failed to get current user. error: " + result.error?.message);
}
};
AthanaCallbacks.OnCurrentUserResult += onCurrentUserResult;
}

Athana.CurrentUser();
}

// 注册用户
public void RegistryUser()
{
if (onRegistryUserResult == null)
{
onRegistryUserResult = (SdkCallback<AthanaInterface.AccountInfo> result) =>
{
if (result.isSuccess())
{
var data = result.data;
// 用户注册成功
Debug.Log("User(" + data.userId + ") register is successed.");
}
else
{
// 调用失败
Debug.Log("Failed to register user. error: " + result.error?.message);
}

};
AthanaCallbacks.OnRegistryUserResult += onRegistryUserResult;
}
var extra = new Dictionary<string, object>();
Athana.RegistryUser(extra: extra);
}

三方登录

适用于有账户体系需要的游戏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<SdkCallback<AccountInfo>>? onSignInResult;
private Action<SdkCallback<AccountInfo>>? onSignInWithUIResult;

// 选择指定登录方式
public void SignIn(AthanaInterface.SignInType type)
{
if (onSignInResult == null)
{
onSignInResult = (SdkCallback<AthanaInterface.AccountInfo> result) =>
{
if (result.isSuccess())
{
var data = result.data;
Debug.Log("User(" + data.userId + ") Sign-In is successed.");
// 登录成功
}
else
{
Debug.Log("SignIn is failure. error: " + result.error?.message);
// 调用失败
}

};
AthanaCallbacks.OnSignInResult += onSignInResult;
}

Athana.SignIn(signInType: type);
}

// 使用内置登录界面
public void SignInWithUI()
{
if (onSignInWithUIResult == null)
{
onSignInWithUIResult = (SdkCallback<AthanaInterface.AccountInfo> result) =>
{
if (result.isSuccess())
{
var data = result.data;
Debug.Log("User(" + data.userId + ") Sign-In is successed.");
// 登录成功
}
else
{
Debug.Log("SignIn is failure. error: " + result.error?.message);
// 调用失败
}

};
AthanaCallbacks.OnSignInWithUIResult += onSignInWithUIResult;
}

Athana.SignInWithUI();
}

三方账号绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<SdkCallback<object?>>? onAccountBindingResult;
private Action<SdkCallback<object?>>? onAccountUnbindResult;
private Action<SdkCallback<TriAccountBindMap>>? onQueryAllAccountBindResult;

public void AccountBinding(SignInType signType)
{
if (onAccountBindingResult == null)
{
onAccountBindingResult = (SdkCallback<object?> result) =>
{
if (result.isSuccess())
{
Debug.Log("Account Binding is successed.");
}
else
{
Debug.Log("Account Binding is failure.");
Debug.Log("Account Binding is failure. error: " + result.error?.message);
}
};
AthanaCallbacks.OnAccountBindingResult += onAccountBindingResult;
}

AthanaSdk.AccountBinding(signInType: signType);
}

三方账号解绑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<SdkCallback<object?>>? onAccountUnbindResult;

public void AccountUnbind(SignInType signType, TriAccount tri)
{
if (onAccountUnbindResult == null)
{
onAccountUnbindResult = (SdkCallback<object?> result) =>
{
if (result.isSuccess())
{
Debug.Log("Account Unbind is successed.");
}
else
{
Debug.Log("Account Unbind is failure. error: " + result.error?.message);
}
};
AthanaCallbacks.OnAccountUnbindResult += onAccountUnbindResult;
}

AthanaSdk.AccountUnbind(signType, OpenId);
}

查询三方绑定状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<SdkCallback<TriAccountBindMap>>? onQueryAllAccountBindResult;

private TriAccountBindMap? BindResults;

public void QueryAllAccountBind()
{
if (onQueryAllAccountBindResult == null)
{
onQueryAllAccountBindResult = (SdkCallback<TriAccountBindMap> result) =>
{
if (result.isSuccess())
{
BindResults = result.data;
// TriAccountBindMap.Facebook 返回 null 表示未绑定 Facebook
// TriAccountBindMap.Apple 返回 null 表示未绑定 Apple
// TriAccountBindMap.Google 返回 null 表示未绑定 Google
// TriAccountBindMap.GoogleGameV2 返回 null 表示未绑定 Google Play Game
Debug.Log("Query Account Bind is successed.");
}
else
{
Debug.Log("Query Account Bind is failure. error: " + result.error?.message);
}
};
AthanaCallbacks.OnQueryAllAccountBindResult += onQueryAllAccountBindResult;
}

AthanaSdk.QueryAllAccountBind();
}

广告

启动广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<ProxyAd>? onAdLoadedEvent = null;
private Action<ProxyAd, AdError>? onLoadFailedEvent = null;

public void LoadAppOpenAd()
{
if (onAdLoadedEvent == null)
{
onAdLoadedEvent = (ad) =>
{
// 加载成功
Debug.Log("Load AppOpen Ad is successed.");
};
AppOpenAd.OnLoadedEvent += onAdLoadedEvent;
}
if (onLoadFailedEvent == null)
{
onLoadFailedEvent = (ad, error) =>
{
// 加载失败
Debug.Log("Load AppOpen Ad is failure.");
};
AppOpenAd.OnLoadFailedEvent += onLoadFailedEvent;
}
AthanaSdk.LoadAppOpenAd(AppOpenAdUnitId);
}

public void ShowAppOpenAd()
{
if (AthanaSdk.IsReadyAppOpenAd(AppOpenAdUnitId))
{
AthanaSdk.ShowAppOpenAd(AppOpenAdUnitId, placement: "AppOpenAd");
}
else
{
LoadAppOpenAd();
}
}

插屏广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<ProxyAd>? onAdLoadedEvent = null;
private Action<ProxyAd, AdError>? onLoadFailedEvent = null;

public void LoadRewardedAd()
{
if (onAdLoadedEvent == null)
{
onAdLoadedEvent = (ad) =>
{
// 加载成功
Debug.Log("Load Interstitial Ad is successed.");
};
AppOpenAd.OnLoadedEvent += onAdLoadedEvent;
}
if (onLoadFailedEvent == null)
{
onLoadFailedEvent = (ad, error) =>
{
// 加载失败
Debug.Log("Load Interstitial Ad is failure.");
};
AppOpenAd.OnLoadFailedEvent += onLoadFailedEvent;
}
AthanaSdk.LoadInterstitialAd(InterstitialAdUnitId);
}

public void ShowInterstitialAd()
{
if (AthanaSdk.IsReadyInterstitialAd(InterstitialAdUnitId))
{
AthanaSdk.ShowInterstitialAd(InterstitialAdUnitId, placement: "InterstitialAd");
}
else
{
LoadInterstitialAd();
}
}

激励广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

private Action<ProxyAd>? onAdLoadedEvent = null;
private Action<ProxyAd, AdError>? onLoadFailedEvent = null;
private Action<ProxyAd>? onRewardedEvent = null;

public void LoadRewardedAd()
{
if (onAdLoadedEvent == null)
{
onAdLoadedEvent = (ad) =>
{
// 加载成功
Debug.Log("Load Rewarded Ad is successed.");
};
AppOpenAd.OnLoadedEvent += onAdLoadedEvent;
}
if (onLoadFailedEvent == null)
{
onLoadFailedEvent = (ad, error) =>
{
// 加载失败
Debug.Log("Load Rewarded Ad is failure.");
};
AppOpenAd.OnLoadFailedEvent += onLoadFailedEvent;
}
if (onRewardedEvent == null)
{
onRewardedEvent = (ad) =>
{
// 收到奖励
Debug.Log("Reward received.");
};
RewardedAd.OnRewardedEvent += onRewardedEvent;
}
AthanaSdk.LoadRewardedAd(RewardedAdUnitId);
}

public void ShowRewardedAd()
{
if (AthanaSdk.IsReadyRewardedAd(RewardedAdUnitId))
{
AthanaSdk.ShowRewardedAd(RewardedAdUnitId, placement: "RewardedAd");
}
else
{
LoadRewardedAd();
}
}

横幅广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using Athana;
using Athana.Api;

private BannerAd? _BannerAd = null;

public void CreateBanner()
{
_BannerAd?.Destroy();
_BannerAd = AthanaSdk.CreateBanner(BannerAdUnitId, AdSize.fullWidth(60), "Banner", AdAlignment.TOP_CENTER);
}

public void HideBanner()
{
_BannerAd?.Hide();
}

public void ShowBanner()
{
_BannerAd?.Show();
}

支付

查询商品详情

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using Athana;
using Athana.Callbacks;
using Athana.Api;
using static Athana.Api.AthanaInterface;
using static Athana.Callbacks.AthanaCallbacks;

// 内购商品详情列表
private List<IapProduct> products = new List<IapProduct>();

public void QueryProducts()
{
if (onQueryProductsResult == null)
{
onQueryProductsResult = (SdkCallback<List<IapProduct>> result) =>
{
if (result.isSuccess())
{
var data = result.data;
if (data == null || data.Count == 0)
{
// 未查询到结果
}
else
{
// 持久化查询结果
products.AddRange(data);
foreach (var product in data)
{
// 价格回显
}
}
}
else
{
// 调用失败
Debug.Log("Failed to query products. error: " + result.error?.message);
}

};
AthanaCallbacks.OnQueryProductsResult += onQueryProductsResult;
}

var keys = new HashSet<string>();
// 添加需要查询的商品 Key
keys.Add("*********");
...
AthanaSdk.QueryProducts(keys);
}

购买

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void Purchase(IapProduct product)
{
if (onPurchaseResult == null)
{
onPurchaseResult = (SdkCallback<object?> result) =>
{
if (result.isSuccess())
{
// 购买成功
}
else
{
// 调用失败
Debug.Log("Failed to Purchase. error: " + result.error?.message);
}

};
AthanaCallbacks.OnPurchaseResult += onPurchaseResult;
}

AthanaSdk.Purchase(product);
}

查询购买历史

PS:不包含一次性消耗类商品,只能提供:在有效期内的订阅订单、非一次性消耗类商品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public void QueryPurchaseHistory()
{
if (onQueryPurchaseHistoryResult == null)
{
onQueryPurchaseHistoryResult = (SdkCallback<List<IapPurchase>> result) =>
{
if (result.isSuccess())
{
var data = result.data;
// 只包含未确认订单、非一次性消耗类商品订单以及有效期内的订阅订单
foreach (var purchase in data)
{
Debug.Log("Purchase: " + purchase.purchaseId + ", Product: " + purchase.productId + ", finished: " + purchase.isAcknowledged);
}
}
else
{
// 调用失败
Debug.Log("Failed to query PurchaseHistory. error: " + result.error?.message);
}

};
AthanaCallbacks.OnQueryPurchaseHistoryResult += onQueryPurchaseHistoryResult;
}

AthanaSdk.QueryPurchaseHistory();
}

事件

内置事件

参考:事件服务

发送自定义事件

1
2
3
4
5
6
7
8
// 自定义事件名
var eventKey = "CustomKey";
// 事件参数
var paramMap = new Dictionary<string, object>();
paramMap["key1"] = value1;
paramMap["keey2"] = value2;
// 发送事件
AthanaSdk.SendEvent(eventKey, paramMap: paramMap);

应用内评分

1
2
// 拉起评分对话框
AthanaSdk.RequestReview();
0%