Athana SDK

For Games

Cocos 集成

安装与配置

下载并安装插件

下载方式:

  1. 导入至 Cocos Create 项目:

     打开 Extension Manger (Extension -> Extension Manager)
     - 目录导入: `Import Extension Folder`
     - ZIP包导入:`Import Extension File`
    
  2. 进入项目插件目录:

     {PROJECT_ROOT}/extension/athana-cocos
    
  3. 编译插件

1
2
3
# 执行命令
npm install
npm run build

设置插件

打开配置面板:Project -> Build -> New Build Task -> 创建 Android 构建配置 -> Build

填选相应的项:

构建配置

Android Studio 项目配置

编辑 Gradle 构建脚本

修改 {COCOS_PROJECT}/build/{ANDROID_STUDIO_PROJECT}/proj/build.gradle

1
2
3
4
5
6
7
8
9
10
11
buildscript {

...
dependencies {
classpath 'com.android.tools.build:gradle:<AGP_VERSION>' // <AGP_VERSION> 替换为 8.11.0 或更高版本

...
}
}

...

修改 {COCOS_PROJECT}/build/{ANDROID_STUDIO_PROJECT}/proj/gradle/wrapper/gradle-wrapper.properties

1
2
3
4
...
# <GRADLE_VERSION> 替换为 8.14 或更高版本
distributionUrl=https\://services.gradle.org/distributions/gradle-<GRADLE_VERSION>-bin.zip
...
配置 Kotlin 运行环境

修改 {COCOS_PROJECT}/build/{ANDROID_STUDIO_PROJECT}/proj/build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
buildscript {

...
dependencies {
classpath 'com.android.tools.build:gradle:<AGP_VERSION>'
// add kotlin-android plugin
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21"

...
}
}

...
修改构建工具版本

修改{COCOS_PROJECT}/build/{ANDROID_STUDIO_PROJECT}/proj/gradle.properties

1
2
3
4
5
6
...
# 最低设置为 23
PROP_MIN_SDK_VERSION=23
# 构建工具根据 PROP_TARGET_SDK_VERSION 选择对应的,假如为 36,则构建工具版本设置为 36.0.0
PROP_BUILD_TOOLS_VERSION=36.0.0
...
Firebase 集成配置

如果需要集成 Firebase,将 google-srvices.json 文件放置在以下目录:

1
{COCOS_PROJECT}/native/engine/android/app

修改 {COCOS_PROJECT}/build/{ANDROID_STUDIO_PROJECT}/proj/build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
buildscript {

...
dependencies {
classpath 'com.android.tools.build:gradle:<AGP_VERSION>'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21"
// add google-service plugin
classpath 'com.google.gms:google-services:4.4.1'
classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.6'

...
}
}

...
AppActivity 插入 SDK 初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.cocos.game;

import android.os.Bundle;
import android.content.Intent;
import android.content.res.Configuration;

import com.cocos.service.SDKWrapper;
import com.cocos.lib.CocosActivity;
// 在此处插入引用
import com.inonesdk.athana.cocos.AthanaCocosPlugin;

public class AppActivity extends CocosActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // DO OTHER INITIALIZATION BELOW
        SDKWrapper.shared().init(this);
// 在此处插入初始化
AthanaCocosPlugin.initBridge();
    }
   
...
}
AndroidManifest.xml 冲突解决
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
xmlns:tools="http://schemas.android.com/tools"> <!-- 增加 tools 命名空间 -->
...
<application ...>
<!-- 插入冲突解决规则 -->
<meta-data tools:replace="android:value" android:name="com.google.android.gms.games.APP_ID" android:value="${GMS_GAMES_ID}"/>
...
  </application>
</manifest>

使用

初始化

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { _decorator, Component } from 'cc';
import {
    Athana,
    AthanaConfig,
    AccountServiceConfig,
    AdServiceConfigs,
    MaxAdServiceConfig,
    ConversionServiceConfigs,
    AppsFlyerServiceConfig
} from 'db://athana-cocos/athana';

const { ccclass } = _decorator;

@ccclass('SdkDemoComponent')
export class SdkDemoComponent extends Component {

onLoad() {
// Athana SDK应用配置信息
        const appId = "****************";
        const appKey = "****************";
        const appSecret = "****************";

// 三方SDK配置信息
        const afDevKey = "****************";
        const maxDevKey = "****************";
        const googleWebClientId = "****************";
       
// 是否开启 Athana SDK 调试模式
        const debug = true;

// 初始化
        Athana.init(
new AthanaConfig(
appId, appKey, appSecret,
                // 三方登录服务配置,如无对接三方登录需求,则设置 null
                new AccountServiceConfig(googleWebClientId),
                // 广告服务配置,如无广告模块,则设置 null
                new AdServiceConfigs(
                // AppLovin MAX 配置
                    new MaxAdServiceConfig(
                    maxDevKey,
                    // 隐私协议链接
                    null,
                    // 用户协议链接
                    null,
                    // 预加载配置,可按需添加
                        new Map<AdType, string>([
                            [AdType.AppOpen, "****************"],
                            [AdType.Interstitial, "****************"],
                            [AdType.Rewarded, "****************"],
                        ]),
                        // MAX调试日志开关
                        debug)
                ),
// 归因服务配置
                new ConversionServiceConfigs(
                    new AppsFlyerServiceConfig(afDevKey)
                ),
// 内购服务测试模式,默认false|null,仅当使用测试环境的SDK下生效
                null,
// SDK调试模式
                debug)
        );
    }
   
start() {
var privacyGrant = false; // 玩家对隐私协议是否接受
// 启动 SDK
        Athana.start(privacyGrant);

// 检查平台用户
// 如有使用三方账号登录,则不需要主动调用 registerUser() 函数
Athana.currentUser({
onSuccess: (data) => {
if (data != null) {
// 已登入
} else {
// 未登入或凭证失效
registerUser();
}
},
onError: (error) => {
// 调用异常
this.showToast("Faied to get Current User: " + error.message);
        });
    }

    update(deltaTime: number) {

    }

/**
* 注册平台用户
*/
    private registerUser() {
Athana.registerUser(new RegisterUserParam(SignInType.ANONYMOUS), {
onSuccess: (data) => {
// 注册成功
},

onError: (error) => {
// 注册异常
console.log(`Athana Cocos - Register User Error: type=${error.type}, code=${error.code}, msg=${error.message}`);
}
});
    }
}

账号服务

登入

指定三方账号登入:

1
2
3
4
5
6
7
8
9
10
11
12
// 指定三方账号类型
const signInType = SignInType.FACEBOOK;
// 其它方式详见:SignInType
// 登入
Athana.signIn(new SignInParam(signInType), {
onSuccess: (data) => {
// 登入成功
},
onError: (error) => {
// 调用异常
}
});

使用内置登录界面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 启用的登入方式,空数组或 null 表示启用所有支持的登入方式
const enableSignTypes = [SignInType.GOOGLE, SignInType.FACEBOOK];
// 自定义用户ID - 游戏内用户ID
var customUserId: number = null;
// 隐私政策链接,设置 null 则不显示隐私政策跳转链接
const privacyPolicyUrl: string = null;
// 服务条款链接,设置 null 则不显示服务条款跳转链接
const termsOfServiceUrl: string = null;

// 跳转到内置页面
Athana.signInWithUI(new SignInWithUIParam(
enableSignTypes,
customUserId,
privacyPolicyUrl,
termsOfServiceUrl
), {
onSuccess: (data) => {
// 登入成功
},
onError: (error) => {
// 调用异常
}
});

登出

1
2
3
4
5
6
7
8
9
// 退出账号
Athana.signOut({
onSuccess: (data) => {
// 登出成功
},
onError: (error) => {
// 调用异常
}
});

查询绑定

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
Athana.queryAllAccountBind({
onSuccess: (data) => {
// 查询成功
if (data.Facebook != null) {
// 已绑定 Facebook

// OpenID
data.Facebook?.open_id;
}
if (data.Apple != null) {
// 已绑定 Apple
}
if (data.Google != null) {
// 已绑定 Google
}
if (data.GoogleGameV2 != null) {
// 已绑定 Google Play Games
}
if (data.Firebase != null) {
// 已绑定 Firebase Auth
}
},
onError: (error) => {
// 调用异常
}
});

绑定

1
2
3
4
5
6
7
8
9
10
11
// 绑定方式
const signInType = SignInType.FACEBOOK;
// 发起绑定
Athana.accountBinding(new AccountBindingParam(signInType), {
onSuccess: (data) => {
// 绑定成功
},
onError: (error) => {
// 调用异常
}
});

解绑

1
2
3
4
5
6
7
8
9
10
11
12
// 绑定方式
const signInType = SignInType.FACEBOOK;
// OpenID
const openId = "********";
Athana.accountUnbind(new AccountBindingParam(signInType, openId), {
onSuccess: (data) => {
// 解绑成功
},
onError: (error) => {
// 调用异常
}
});

广告服务

应用启动广告

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
private _onLoadedListener?: (ad: ProxyAd) => void = null;
private _onLoadFailedListener?: (event: AdEventResult) => void = null;
private _adType = AdType.AppOpen;

// 设置监听
private setListener() {
// 注册加载成功监听
this._onLoadedListener = (ad: ProxyAd) => {
this.show();
}
Athana.adService.registerOnLoaded(this._adType, this._onLoadedListener);

// 注册加载失败监听
this._onLoadFailedListener = (event: AdEventResult) => {
// 加载失败
}
Athana.adService.registerOnLoadFailed(this._adType, this._onLoadFailedListener);
}

// 展示广告
private show() {
// 广告位ID
const adUnitId = "************";
// 判断广告是否已加载完毕
Athana.adService.isReadyAppOpenAd(adUnitId).then((isReady) => {
if (isReady) {
// 展示广告
Athana.adService.showAppOpenAd(adUnitId);
} else {
// 游戏内显示加载提示

// 请求广告
Athana.adService.loadAppOpenAd(adUnitId);
}
}).catch((error) => {
// 调用异常
});
}

// 注销监听
private destroy() {
if (this._onLoadedListener != null) {
Athana.adService.unregisterOnLoaded(this._adType, this._onLoadedListener);
this._onLoadedListener = null;
}
if (this._onLoadFailedListener != null) {
Athana.adService.unregisterOnLoadFailed(this._adType, this._onLoadFailedListener);
this._onLoadFailedListener = null;
}

}

激励广告

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
private _onLoadedListener?: (ad: ProxyAd) => void = null;
private _onLoadFailedListener?: (event: AdEventResult) => void = null;
private _onRewardedListener?: (ad: ProxyAd) => void = null;
private _adType = AdType.Rewarded;

// 设置监听
private setListener() {
// 注册加载成功监听
this._onLoadedListener = (ad: ProxyAd) => {
this.show();
}
Athana.adService.registerOnLoaded(this._adType, this._onLoadedListener);

// 注册加载失败监听
this._onLoadFailedListener = (event: AdEventResult) => {
// 加载失败
}
Athana.adService.registerOnLoadFailed(this._adType, this._onLoadFailedListener);

// 注册发放激励监听
this._onRewardedListener = (ad: ProxyAd) => {
// 获得奖励
}
Athana.adService.registerOnRewarded(this._adType, this._onRewardedListener);
}

// 展示广告
private show() {
// 广告位ID
const adUnitId = "************";
// 判断广告是否已加载完毕
Athana.adService.isReadyRewardedAd(adUnitId).then((isReady) => {
if (isReady) {
// 展示广告
Athana.adService.showRewardedAd(adUnitId);
} else {
// 游戏内显示加载提示

// 请求广告
Athana.adService.loadRewardedAd(adUnitId);
}
}).catch((error) => {
// 调用异常
});
}

// 注销监听
private destroy() {
if (this._onLoadedListener != null) {
Athana.adService.unregisterOnLoaded(this._adType, this._onLoadedListener);
this._onLoadedListener = null;
}
if (this._onLoadFailedListener != null) {
Athana.adService.unregisterOnLoadFailed(this._adType, this._onLoadFailedListener);
this._onLoadFailedListener = null;
}
if (this._onRewardedListener != null) {
Athana.adService.unregisterOnRewarded(this._adType, this._onRewardedListener);
this._onRewardedListener = null;
}
}

插屏广告

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
private _onLoadedListener?: (ad: ProxyAd) => void = null;
private _onLoadFailedListener?: (event: AdEventResult) => void = null;
private _adType = AdType.Interstitial;

// 设置监听
private setListener() {
// 注册加载成功监听
this._onLoadedListener = (ad: ProxyAd) => {
this.show();
}
Athana.adService.registerOnLoaded(this._adType, this._onLoadedListener);

// 注册加载失败监听
this._onLoadFailedListener = (event: AdEventResult) => {
// 加载失败
}
Athana.adService.registerOnLoadFailed(this._adType, this._onLoadFailedListener);
}

// 展示广告
private show() {
// 广告位ID
const adUnitId = "************";
// 判断广告是否已加载完毕
Athana.adService.isReadyInterstitialAd(adUnitId).then((isReady) => {
if (isReady) {
// 展示广告
Athana.adService.showInterstitialAd(adUnitId);
} else {
// 游戏内显示加载提示

// 请求广告
Athana.adService.loadInterstitialAd(adUnitId);
}
}).catch((error) => {
// 调用异常
});
}

// 注销监听
private destroy() {
if (this._onLoadedListener != null) {
Athana.adService.unregisterOnLoaded(this._adType, this._onLoadedListener);
this._onLoadedListener = null;
}
if (this._onLoadFailedListener != null) {
Athana.adService.unregisterOnLoadFailed(this._adType, this._onLoadFailedListener);
this._onLoadFailedListener = null;
}

}

横幅广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 广告位ID
const adUnitId = "***************";
// 横幅尺寸
const adSize = AdSize.fullWidth(60); // 占满屏幕宽度,高度60dp
// 创建横幅
Athana.adService.createBannerAd(new CreateBannerParam(adUnitId, adSize))
.then((banner) => {
this._banner = banner;

// 隐藏横幅
this._banner?.hide();
// 显示横幅,创建横幅成功会自动调用 show,所以创建后不用手动调用 show
this._banner?.show();

}).catch((error: AthanaError) => {
// 创建失败
});

支付服务

查询商店服务是否可用

1
2
3
4
5
6
7
8
9
10
11
12
Athana.isIapAvailable({
onSuccess: (data) => {
if (data) {
// 可用
} else {
// 不可用
}
},
onError: (error) => {
// 调用异常
}
});

查询商品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 需要查询商品信息的key数组,需要去重
const keys = ["key1", "key2", ...];
// 发起查询
Athana.queryProducts(keys, {
onSuccess: (data) => {
if (data.length == 0) {
// 查询不到对应结果
} else if (data.length != keys.length) {
// 存在无效的 key
} else {
// 查到对应结果
data.forEach(item => {
// 商品价格
item.price;

// 详细参数说明见:IapProduct
});
}
},
onError: (error) => {
// 调用异常
}
});

购买

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 需购买的商品key
const productId = "****";
// 订阅类商品的序号,从 IapProduct.subsInex 获取。订阅类商品必传
const subsInex = null;
// 自定义订单ID - 游戏订单ID,如无服务器,则不需要传入
const clientOrderId = null;
// 是否消耗型商品,默认为true,如果一个用户只能购买一次,则设置为false,例如:购买永久去广告
const consumable = true;

// 发起购买
Athana.purchase(
new PurchaseParam(
productId,
subsInex,
clientOrderId,
consumable
), {
onSuccess: (data) => {
// 购买成功
},
onError: (error) => {
// 调用异常
}
});

查询历史订单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Athana.queryPurchaseHistory({
onSuccess: (data) => {
// 查询成功
// 结果只包含:未确认订单、有效期内的订阅、非一次性消耗类商品
data.forEach(item => {
// 商店流水号
item.purchaseId;

// 订单是否已确认,如果为 false,则表示为用户已付款,但是客户端未确认订单,常见于调单场景,如不补单,订单将在3天后自动退款
item.isAcknowledged

// 详细参数说明见:IapPurchaseDetail
});
},
onError: (error) => {
// 调用异常
}
});

验证订单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 需补单的商店订单流水号
const purchaseId = "******";
// 是否消耗型商品,默认为true,如果一个用户只能购买一次,则设置为false,例如:购买永久去广告
const consumable = true;
// 发起验证
Athana.verifyOrder(
new VerifyOrderParam(
productId,
subsInex,
clientOrderId,
consumable
), {
onSuccess: (data) => {
// 验证成功
},
onError: (error) => {
// 调用异常
}
});

事件服务

内置事件

1
2
3
4
5
6
7
// 创建事件
const event = AthanaEventFactory.logGamesTask(...);

// 更多内置事件见:AthanaEventFactory

// 发送事件
Athana.sendEvent(event);

内置事件可参阅:事件服务

发送自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
// 创建自定义事件

// 事件命名
const key = "";
// 事件参数
const params = new Map<string, any>();
// 添加参数,参数值只支持基础类型:number、boolean、string
params.set("param1", "value1");
const event = AthanaEvent(key, params);

// 发送事件
Athana.sendEvent(event);

应用内评分

1
2
3
4
5
6
7
8
Athana.requestReview({
onSuccess: () => {
// 拉起成功
},
onError: (error) => {
// 调用异常
}
});
0%