cocosCreator2.4 googlePlay登录升级、API 35、16KB内存页面的支持
环境:我这里是cocosCreator 2.4.12 导出的android 工程
登录升级
后台收到的google 的提醒:
之前是通过implementation 'com.google.android.gms:play-services-auth:20.0.0'
来获取玩家 uid 和 邮箱,然后发送到我们的服务器获取账号。
升级文档:从旧版 Google 登录服务迁移到 Credential Manager 和 AuthorizationClient
这位网友的文档写的很好:接入谷歌最新登录SDK凭据管理器Credential Manager
具体细节不考虑的话我们这边只要能从新的登录方式中继续获取玩家的 uid 和 邮箱,后续按照之前的逻辑继续下去就行了。
build.gradle 中引入新的sdk:
//google登录
implementation "androidx.credentials:credentials:1.3.0"
implementation "androidx.credentials:credentials-play-services-auth:1.3.0"
implementation "com.google.android.libraries.identity.googleid:googleid:1.1.0"
登录主要代码:
public static AppActivity app; // 在onCreate里保存的 app = this;
static final String TAG = "MainActivity";private static CredentialManager credentialManager;
private static boolean oneTapStatus = false;public static void googleSignIn(String str) {credentialManager = CredentialManager.create(app);GetSignInWithGoogleOption signInWithGoogleOption = new GetSignInWithGoogleOption.Builder(app.getString(R.string.web_client_id)).build(); //这里是web client idGetCredentialRequest request = new GetCredentialRequest.Builder().addCredentialOption(signInWithGoogleOption).build();android.os.CancellationSignal cancellationSignal = new android.os.CancellationSignal();cancellationSignal.setOnCancelListener(() -> {if (oneTapStatus) oneTapStatus = false;showToast("Preparing credentials with Google was cancelled.");});credentialManager.getCredentialAsync(app,request,cancellationSignal,Executors.newSingleThreadExecutor(),new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {@Overridepublic void onResult(GetCredentialResponse result) {handleGoogleSignIn(result);}@Overridepublic void onError(GetCredentialException e) {Log.e(TAG, "googleSignIn Error: " + e);}});}// Handle the successfully returned credential.public static void handleGoogleSignIn(GetCredentialResponse result) {Credential credential = result.getCredential();if (credential instanceof CustomCredential) {if (GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.equals(credential.getType())) {// Use googleIdTokenCredential and extract id to validate and// authenticate on your serverGoogleIdTokenCredential googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.getData());String email = googleIdTokenCredential.getId();String idToken = googleIdTokenCredential.getIdToken();Log.d(TAG, "handleGoogleSignIn: " + email);app.nativeCallLoginWithGoogle(email, idToken);} else {// Catch any unrecognized custom credential type here.Log.e(TAG, "Unexpected type of credential");}} else {// Catch any unrecognized credential type here.Log.e(TAG, "Unexpected type of credential");}}public void nativeCallLoginWithGoogle(String email, String token){Log.d(TAG, "signIn token:" + token);Cocos2dxHelper.runOnGLThread(new Runnable() {@Overridepublic void run() {Cocos2dxJavascriptJavaBridge.evalString("cc.sdkMgr.googleSignIn(\""+email+"\",\""+token+"\")");}});}
这里的 token 是 JWT,可以直接解出来。JWT网站。
我这里把token放在JS里解析的,加了一个解析函数:
getDataFromJWT(token) {try {//分割 Token 的三个部分const parts = token.split('.');if (parts.length !== 3) {throw new Error("Invalid JWT format");}//获取 Payload (Base64Url 部分)const payloadBase64Url = parts[1];//Base64Url 转 Base64let base64 = payloadBase64Url.replace(/-/g, '+').replace(/_/g, '/');//补全 Base64 末尾的 '='switch (base64.length % 4) {case 2: base64 += '=='; break;case 3: base64 += '='; break;}//解码 Base64 → 字符串const buffer = Buffer.from(base64, 'base64');let decodedPayload = buffer.toString('utf-8');//解析为 JSON 对象return JSON.parse(decodedPayload);} catch (error) {console.error("JWT 解析失败:", error);return null;}},}
解出来是这样的数据(其中sub 就是uid,email就是邮箱):
{"iss": "https://accounts.google.com","azp": "xxxxxxxxx.apps.googleusercontent.com","aud": "xxxxxxxxxx.apps.googleusercontent.com","sub": "11111111111","email": "222222222222222222@gmail.com","email_verified": true,"name": "ZZZZZZZZZZZZZZZZ","picture": "https://lh3.googleusercontent.com/ZZZZZZZZZZZZZZZZ","given_name": "ZZZZZZZZZZZZZZZZ","family_name": "ZZZZZZZZZZZZZZZZ","iat": 1752744039,"exp": 1752747639
}
我们这边由于是托管给 googlePlay 签名的,就导致本地调试登录会因为签名问题无法进行,只能上内部轨道。后来同事将develop的签名信息上传的google后台,这样就可以在本地用androidStudio进行调试了(具体是在后台添加了多个签名,还是用develop签名新建了一个测试项目我就不清楚)。
参考:Google Play 签名维护
升级API 35
参考链接:请教各位,2025年,如何打包符合google商店要求的apk?
1.下载新一些的androidStudio,下载链接,我选的版本是:Android Studio Meerkat Feature Drop | 2024.3.2 Patch 1
。
2.打开 Tools >> SDK Manager
SDK Platforms 下载 Android 15.0
SDK Tools 下载 35.0.0
3.升级gradle,使用的版本是:
gradle sync
失败的话可以手动处理一下:Android Studio 手动下载Gradle配置的方法
4.在gradle.properties
中升级API35相关的配置:(cocosCreator 可以在导出项目的时候先选择 api-35,其它不一样的再手动改)
5.新版的AndroidStudio 需要在build.gradle 中也要配置一下ndkVerison
(注意要跟 local.properties 中的一致 )
6.如果还 编不过去的话,可以尝试升级ndk到r26,如果需要支持16KB内存页面,直接升级到r28。
16KB内存页面的支持
参考链接:cocos2.4系列,如何打包支持16KB对齐的安卓应用???
先说如何检测是否支持,官方文档里有说 :支持 16 KB 的页面大小,我使用的是mac,直接按照下面的方法:
使用 check_elf_alignment.sh 脚本(Linux 或 macOS) 请按照以下步骤使用
check_elf_alignment.sh 脚本检查 ELF 段的对齐情况:将 check_elf_alignment.sh 脚本保存到文件中。
对应用的 APK 文件运行脚本:
check_elf_alignment.sh APK_NAME.apk
该脚本会针对所有 arm64-v8a 共享库输出 ALIGNED 或 UNALIGNED。如果任何 arm64-v8a 或 x86_64 共享库是
UNALIGNED,您需要更新这些库的打包,然后重新编译应用,并按照本部分中的步骤重新测试。
其中 check_elf_alignment.sh脚本中的内容是:
#!/bin/bash
progname="${0##*/}"
progname="${progname%.sh}"# usage: check_elf_alignment.sh [path to *.so files|path to *.apk]cleanup_trap() {if [ -n "${tmp}" -a -d "${tmp}" ]; thenrm -rf ${tmp}fiexit $1
}usage() {echo "Host side script to check the ELF alignment of shared libraries."echo "Shared libraries are reported ALIGNED when their ELF regions are"echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."echoecho "Usage: ${progname} [input-path|input-APK|input-APEX]"
}if [ ${#} -ne 1 ]; thenusageexit
ficase ${1} in--help | -h | -\?)usageexit;;*)dir="${1}";;
esacif ! [ -f "${dir}" -o -d "${dir}" ]; thenecho "Invalid file: ${dir}" >&2exit 1
fiif [[ "${dir}" == *.apk ]]; thentrap 'cleanup_trap' EXITechoecho "Recursively analyzing $dir"echoif { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; thenecho "=== APK zip-alignment ==="zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'echo "========================="elseecho "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."echo " You can install the latest build-tools by running the below command"echo " and updating your \$PATH:"echoecho " sdkmanager \"build-tools;35.0.0-rc3\""fidir_filename=$(basename "${dir}")tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1dir="${tmp}"
fiif [[ "${dir}" == *.apex ]]; thentrap 'cleanup_trap' EXITechoecho "Recursively analyzing $dir"echodir_filename=$(basename "${dir}")tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }dir="${tmp}"
fiRED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"unaligned_libs=()echo
echo "=== ELF alignment ==="matches="$(find "${dir}" -type f)"
IFS=$'\n'
for match in $matches; do# We could recursively call this script or rewrite it to though.[[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"[[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"[[ $(file "${match}") == *"ELF"* ]] || continueres="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; thenecho -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"elseecho -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"unaligned_libs+=("${match}")fi
doneif [ ${#unaligned_libs[@]} -gt 0 ]; thenecho -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
elif [ -n "${dir_filename}" ]; thenecho -e "ELF Verification Successful"
fi
echo "====================="
注意执行 脚本前需要搞一下环境:export PATH=/Users/loofnn/Library/Android/sdk/build-tools/35.0.0:$PATH
。
输出是这个样子的:
=== APK zip-alignment ===
4570074 lib/arm64-v8a/libcocos2djs.so (OK - compressed)
Verification succesful
============================ ELF alignment ===
/var/folders/4v/qgw2n0k93k33q9kbl3b6n_7c0000gn/T/app-release3_out_XXXXX.gxZM5X8KG7/lib/armeabi-v7a/libcocos2djs.so: \e[31mUNALIGNED\e[0m (2**12)
/var/folders/4v/qgw2n0k93k33q9kbl3b6n_7c0000gn/T/app-release3_out_XXXXX.gxZM5X8KG7/lib/arm64-v8a/libcocos2djs.so: \e[32mALIGNED\e[0m (2**14)
需要关注的是 arm64 和 x86_64 的括号内输出。如果是(2**12)
就是要升级。(上边的输出是我升级之后的)。
升级16KB这个非常简单,按照网友说的 升级 NDK 到 r28就可以了。
如何升级ndk: 打开 Tools >> SDK Manager,SDK Tools 下载 NDK 28.1.13356709
如果帮到你的话,点个赞赞吧!