开发指南
监听用户状态变化
在执行登录接口前,需要先设置全局的用户状态变化回调,以方便游戏响应退出登录、第三方账号绑定/解绑成功等状态变更。
- Android
- iOS
- Unity
// MainActivity.java
import com.xd.sdk.account.XDGAccount;
import com.xd.sdk.common.callback.XDGUserStatusChangeCallback;
import org.jetbrains.annotations.Nullable;
// ...
private void addUserStatusChangeCallback() {
XDGAccount.addUserStatusChangeCallback(new XDGUserStatusChangeCallback() {
@Override
public void userStatusChange(int code, @Nullable String message) {
if (code == XDGUserStatusChangeCallback.UserStatus.LOGOUT) {
// 退出登录,回到登录页面,展示登录按钮
} else if (code == XDGUserStatusChangeCallback.UserStatus.BIND) {
// 绑定成功,没有更多登录方式可不处理
} else if (code == XDGUserStatusChangeCallback.UserStatus.UNBIND) {
// 解绑成功,没有更多登录方式可不处理
} else if (code == XDGUserStatusChangeCallback.UserStatus.PROTOCOL_AGREED_AFTER_LOGOUT) {
// 退出登录后同意协议,可不处理
} else if (code == XDGUserStatusChangeCallback.UserStatus.CUSTOMER_NO_UNREAD_MESSAGE) {
// 客服有未读消息,未开通服务可以不处理
} else if (code == XDGUserStatusChangeCallback.UserStatus.CUSTOMER_HAS_UNREAD_MESSAGE) {
// 客服没有未读消息,未开通服务可以不处理
} else {
// 未知 Code,不需要处理
}
}
});
}
typedef NS_ENUM(NSInteger, XDGUserStateChangeCode) {
XDGUserStateChangeCodeLogout = 0, // 用户登出
XDGUserStateChangeCodeBindSuccess = 1, // 用户绑定成功,msg = 登录类型字符串,例如:@"TAPTAP"
XDGUserStateChangeCodeUnBindSuccess = 2, // 用户解绑成功,msg = 登录类型字符串
XDGUserStateChangeCodeProtocolAgreedAfterLogout = 3, // 用户在登出后点击确认同意协议
XDGUserStateChangeCodeSupportNoUnread = 4, // 客服中心没有未读消息
XDGUserStateChangeCodeSupportHasUnread = 5, // 客服中心有未读消息
};
[XDGAccount addUserStatusChangeCallback:^(XDGUserStateChangeCode userStateChangeCode, NSString *message) {
if (userStateChangeCode == XDGUserStateChangeCodeBindSuccess) {
// 绑定新平台成功
} else if (userStateChangeCode == XDGUserStateChangeCodeUnBindSuccess) {
// 解绑平台成功
} else if (userStateChangeCode == XDGUserStateChangeCodeLogout) {
// 用户退出登录
} else if (userStateChangeCode == XDGUserStateChangeCodeProtocolAgreedAfterLogout) {
// 用户退出登录后点击同意协议
} else if (userStateChangeCode == XDGUserStateChangeCodeSupportNoUnread) {
// 客服中心没有未读消息
} else if (userStateChangeCode == XDGUserStateChangeCodeSupportHasUnread) {
// 客服中心有未读消息
}
}];
using XD.SDK.Account;
// 设置用户状态回调
XDGAccount.AddUserStatusChangeCallback((code, message) =>
{
switch (code)
{
case XDGUserStatusCodeType.BIND:
// 绑定成功,没有更多登录方式可不处理
break;
case XDGUserStatusCodeType.UNBIND:
// 解绑成功,没有更多登录方式可不处理
break;
case XDGUserStatusCodeType.LOGOUT:
// 退出登录,回到登录页面,展示登录按钮
break;
case XDGUserStatusCodeType.ProtocolAgreedAfterLogout:
// 退出登录后同意协议,可不处理
break;
case XDGUserStatusCodeType.SupportHasUnRead:
// 客服有未读消息,未开通服务可以不处理
break;
case XDGUserStatusCodeType.SupportNoUnRead:
// 客服没有未读消息,未开通服务可以不处理
break;
default:
// 未知 Code,不需要处理
break;
}
});
发起登录
需要在初始化成功后才可使用登录相关功能。
普通登录
- 调用
LoginByType(Default)进行自动登录,如果玩家之前已经登录过且还未过期,则能直接登录成功。 - 如果自动登录返回失败,则游戏需要绘制包含各类型登录按钮的登录页面,等待玩家选择登录方式。
- 玩家点击登录按钮时调用
LoginByType(targetType),需要传入对应的登录类型来触发对应的流程并等待接口回调。 - 登录成功后,游戏可获取到用户的 XD User ID 以及头像、昵称等信息,之后可引导玩家进入游戏主流程。
- 当用户状态回调退出登录时,游戏需要同步退出登录状态并引导玩家重新登录。
注意事项:
- 手动登录时,游戏可以在点击后短时间内屏蔽重复点击,但请勿长时间禁用登录按钮,SDK 无法保证所有情况下的登录一定会有回调。
- 自动登录在整个游戏生命周期内只需要调用一次,如果玩家退出登录后回到登录页面时,不需要再次调用自动登录接口。
- 登录成功后不再需要调用 TrackUser 方法,SDK 会自动处理用户行为上报。
- 国内游戏在登录成功后不再需要处理实名和防沉迷相关逻辑,SDK 会自动处理相关逻辑。
- Android
- iOS
- Unity
// LoginActivity.java
import android.util.Log;
import com.xd.sdk.account.XDGAccount;
import com.xd.sdk.common.base.XDGError;
import com.xd.sdk.common.bean.XDGUser;
import com.xd.sdk.common.callback.Callback;
import com.xd.sdk.common.entities.LoginEntryType;
import java.util.Map;
// ...
/**
* 登录
*
* LoginEntryType 枚举:
* LoginEntryType.DEFAULT - 自动登录
* LoginEntryType.TAP_TAP - TapTap 登录
* LoginEntryType.APPLE - Apple 登录
* LoginEntryType.GOOGLE - Google 登录
* LoginEntryType.FACEBOOK - Facebook 登录
* LoginEntryType.LINE - LINE 登录
* LoginEntryType.TWITTER - Twitter 登录
* LoginEntryType.STEAM - Steam 登录
* LoginEntryType.GUEST - 游客登录
* LoginEntryType.PHONE - 手机号登录
* LoginEntryType.EMAIL - 邮箱登录
*/
private void loginByType() {
XDGAccount.loginByType(LoginActivity.this, LoginEntryType.TAP_TAP, new Callback<XDGUser>() {
@Override
public void onCallback(XDGUser xdgUser, XDGError xdgError) {
if (xdgUser != null) {
// 登录成功
String userId = xdgUser.getId(); // 用户在 XD 账户系统的 XD User ID(用户唯一标识)
String avatarUrl = xdgUser.getAvatar();
String nickname = xdgUser.getNickName();
return;
}
// 登录失败
if (xdgError != null) {
int code = xdgError.getCode();
String message = xdgError.getMessage();
Log.e("LoginActivity", "XDSDK loginFailed, code=" + code + ", message: " + message);
Map<String, Object> errorDataMap = xdgError.getErrorDataMap();
if (errorDataMap != null) {
// ...
}
}
}
});
}
LoginEntryTypeDefault (自动登录)
LoginEntryTypeTapTap
LoginEntryTypeApple
LoginEntryTypeGoogle
LoginEntryTypeFacebook
LoginEntryTypeLine
LoginEntryTypeTwitter
LoginEntryTypeSteam
LoginEntryTypeGuest
LoginEntryTypePhone
LoginEntryTypeEmail
LoginEntryType type = LoginEntryTypeDefault;
[XDGAccount loginByType:type loginHandler:^(XDGUser * _Nullable result, NSError * _Nullable error) {
if (error) {
// 登录失败
// error.code (错误码,用来区分类型)
// error.localizedDescription (可以用来展示给用户的错误原因文案)
} else {
// 登陆成功
NSString *xdUserID = result.userId; // result.userId 为用户在 XD 账户系统的 XD User ID(用户唯一标识)
NSString *name = result.name;
NSString *nickName = result.nickName;
NSString *avatar = result.avatar;
}
}];
using XD.SDK.Account;
// 自动登录,在初始化成功后可以调用该方法,每次打开游戏只触发一次。失败之后只能调用其他登录方式。
XDGAccount.LoginByType(LoginType.Default,
user =>
{
// 自动登录成功,进入游戏
String userId = user.UserId;
},
error =>
{
// 自动登录失败,展示 TapTap 登录按钮
});
// 手动登录
XDGAccount.LoginByType(LoginType.TapTap,
user =>
{
// TapTap登录成功,进入游戏
String userId = user.UserId;
},
error =>
{
// TapTap 登录失败,展示 TapTap 登录按钮
});
// 登录后获取用户信息
XDGUser currentUser = XDGAccount.GetCurrentUser();
主机登录
我们可以把「Steam/PS/Nintendo」等平台上发行的游戏称之为主机游戏,对于这些游戏,用户们会更习惯用该平台账号登录游戏。对于这类游戏,推荐使用这个接口来登录。
游戏如何正确的使用该接口,可以参考这里的方案
- Unity
XDGAccount.LoginByConsole(xdgUser => {
ResultText.text = $"Steam 主机登录成功:{xdgUser.nickName} userId: {xdgUser.userId} kid: {xdgUser.token.kid}";
}, null,
error => {
ResultText.text = $"Steam 主机登录失败:{error}";
}
);
退出登录
如果需要退出当前账号,可以使用该接口。调用后 SDK 会重新弹出协议窗口并在用户状态回调中返回 LOGOUT_CODE 事件。在玩家点击同意协议后会返回 PROTOCOL_AGREED_AFTER_LOGOUT_CODE 事件。
- Android
- iOS
- Unity
// LoginActivity.java
import com.xd.sdk.account.XDGAccount;
// ...
private void logout() {
XDGAccount.logout(LoginActivity.this);
}
[XDGAccount logout];
using XD.SDK.Account;
XDGAccount.Logout();
获取当前用户信息
在用户已登录的情况下,调用此方法可获取当前已登录用户的信息:
- Android
- iOS
- Unity
// LoginActivity.java
import com.xd.sdk.account.XDGAccount;
import com.xd.sdk.common.bean.XDGUser;
// ...
private void getCurrentUser() {
XDGUser currentUser = XDGAccount.getCurrentUser();
if (currentUser != null) {
String userId = currentUser.getId(); // 用户在 XD 账户系统的 XD User ID(用户唯一标识)
String userName = currentUser.getName();
String nickname = currentUser.getNickName();
String avatar = currentUser.getAvatar();
}
}
XDGUser *user = [XDGAccount getCurrentUser];
NSString *xdUserID = user.userId; // user.userId 为用户在 XD 账户系统的 XD User ID(用户唯一标识)
NSString *name = user.name;
NSString *nickName = user.nickName;
NSString *avatar = user.avatar;
XDGUser currentUser = XDGAccount.GetCurrentUser();
打开用户中心
- 需要登录
- 用户中心会展示用户当前的登录类型,对应的账号 ID,以及当前绑定的一些第三方平台,可以操作绑定更多的渠道。
- Android
- iOS
- Unity
// LoginActivity.java
import com.xd.sdk.account.XDGAccount;
// ...
private void openUserCenter() {
XDGAccount.openUserCenter(LoginActivity.this);
}
[XDGAccount openUserCenter];
using XD.SDK.Account;
XDGAccount.OpenUserCenter(null);
打开个人信息页
- 需要登录
- 会展示游戏和 SDK 收集的和玩家个人信息相关的内容。
- Android
- iOS
- Unity
// LoginActivity.java
import com.xd.sdk.account.XDGAccount;
import com.xd.sdk.common.entities.RoleInfo;
// ...
private void openUserDashboard() {
RoleInfo roleInfo = RoleInfo.newBuilder()
.setRoleId("game_role_id") // 必填
.setRoleName("game_role_name") // 必填
.setRoleLevel(100)// 必填
.setServerId("game_server_id") // 必填
.setExtra("extra_info")
.build();
XDGAccount.openUserDashboard(LoginActivity.this, roleInfo);
}
XDGRoleInfo *roleInfo = [XDGRoleInfo new];
roleInfo.roleId = roleId; // 必填
roleInfo.roleName = roleName; // 必填
roleInfo.roleLevel = roleLevel; // 必填
roleInfo.serverId = serverId; // 必填
[XDGAccount openUserDashboard:roleInfo];
using XD.SDK.Account;
XDGRoleInfo role = new XDGRoleInfo()
{
RoleId = "role_id",
RoleLevel = 10,
RoleName = "role_name",
ServerId = "server_id"
};
XDGAccount.OpenUserDashboard(role);
打开帐户注销页面
- 需要登录
- 用户可通过此方法进行帐户的注销操作。
- 当用户成功发起注销且关闭当前页面时,会在用户状态回调中返回退出登录的事件,游戏需要同步退出登录状态。
- 此时玩家账号还未真正被删除,需要参考服务端通知对接完成对接后收到通知时在游戏侧删除相应账号的数据。
- Android
- iOS
- Unity
// LoginActivity.java
import com.xd.sdk.account.XDGAccount;
// ...
private void openAccountDeletion() {
XDGAccount.openAccountDeletion(LoginActivity.this);
}
[XDGAccount openAccountDeletion];
using XD.SDK.Account;
XDGAccount.OpenAccountDeletion();
打开客服页面
- 不需要登录
- 未登录时 SDK 会自动处理成匿名游客身份进入客服页面,登录后 SDK 会自动切换成当前登录用户身份进入客服页面。
- Android
- iOS
- Unity
// MainActivity.java
import com.xd.sdk.account.XDGAccount;
import com.xd.sdk.common.entities.RoleInfo;
import java.util.HashMap;
import java.util.Map;
// ...
private void openCustomerService() {
RoleInfo roleInfo = RoleInfo.newBuilder()
.setRoleId("game_role_id") // 必填
.setRoleName("game_role_name") // 必填
.setRoleLevel(100)// 必填
.setServerId("game_server_id") // 必填
.setExtra("extra_info")
.build();
String path = ""; // 客服内的相对路径,一般留空即可
Map<String, Object> extrasMap = new HashMap<>();
extrasMap.put("key", "value");
XDGAccount.openCustomerService(MainActivity.this, roleInfo, path, extrasMap);
}
XDGRoleInfo *role = [XDGRoleInfo new];
role.roleId = roleId; // 必填
role.roleName = roleName; // 必填
role.roleLevel = roleLevel; // 必填
role.serverId = serverId; // 必填
NSString *pathStr = @"客服内的相对路径,一般留空即可";
NSDictionary *paramsDic = @{@"自定义参数 key":@"自定义参数 value"};
[XDGAccount openCustomerService:role path:pathStr params:paramsDic];
using XD.SDK.Account;
// 角色信息
XDGRoleInfo role = new XDGRoleInfo()
{
RoleId = "role_id",
RoleLevel = 10,
RoleName = "role_name",
ServerId = "server_id"
};
// 透传参数
var paramsMap = new Dictionary<string, object>
{
{ "key1", "value1" },
{ "key2", true },
{ "key3", 1234567890 }
};
XDGAccount.OpenCustomerService(role, "", paramsMap);
绑定第三方账号
危险
绑定接口对于玩家来说如果授权了和之前授权不一样的账号的话,存在「换绑」的可能性,所以游戏需要谨慎使用该方法,使用前需要给到用户明确的提醒。参考 绑定账号接口 文档。
- Android
- iOS
- Unity
// LoginActivity.java
import com.xd.sdk.account.XDGAccount;
import com.xd.sdk.common.base.XDGError;
import com.xd.sdk.common.callback.XDGBindResultCallback;
import com.xd.sdk.common.entities.LoginEntryType;
// ...
private void bindByType() {
XDGAccount.bindByType(LoginActivity.this, LoginEntryType.GOOGLE, new XDGBindResultCallback() {
@Override
public void onBindResult(boolean success, XDGError error) {
if (success) {
// 绑定成功
} else {
// 绑定失败
if (error!= null) {
int errorCode = error.getCode();
String errorMsg = error.getMessage();
}
}
}
});
}
[XDGAccount bindByType:bindType
bindHandler:^(BOOL success, NSError *_Nullable error) {
if (success) {
// 绑定成功
} else {
// 绑定失败
}
}];
XDGAccount.BindByType(LoginType, (success, error) => {
if(success){
// 绑定成功
} else {
// 绑定失败
ResultText.text = $"绑定结果:{success}, error:{JsonUtility.ToJson(error)}";
}
});