将 Android Target SDK 从 33 更新到 34 后,配置不再有效(即
platform_configuration_->Valid() == false
)。
我从 Google Play 游戏服务 C++ 收到以下错误消息
1 GamesNativeSDK V Using classes from /data/user/0/com.mycompany.myapp/app_.gpg.classloader/4105d0375b9d69fe6ee3a07b7893a4f1_games.jar.
2 GamesNativeSDK I Using existing jar.
3 GamesNativeSDK I Writing 1881 bytes to jar file
a.myapp E Attempt to load writable dex file: /data/user/0/com.mycompany.myapp/app_.gpg.classloader/4105d0375b9d69fe6ee3a07b7893a4f1_games.jar
4 Compatibil...geReporter D Compat change id reported: 218865702; UID 10402; state: ENABLED
5 GamesNativeSDK E Exception in dalvik/system/DexClassLoader.<init>: java.lang.SecurityException: Writable dex file '/data/user/0/com.mycompany.myapp/app_.gpg.classloader/4105d0375b9d69fe6ee3a07b7893a4f1_games.jar' is not allowed..
6 GamesNativeSDK E Could not create class loader from file.
7 GamesNativeSDK E Could not load additional classes from embedded jar.
似乎与这个问题有关:使用Android 14开发应用程序时遇到的问题
正如上面问题中所建议的,当我添加时
File(Context.getDataDir() + "/app_.gpg.classloader/4105d0375b9d69fe6ee3a07b7893a4f1_games.jar").setReadOnly();
对于我的活动
onCreate
方法,日志消息2、3、4和5不再显示。尽管如此,其他日志消息仍然显示,并且游戏服务的初始化失败。
有谁知道这个问题有什么解决办法吗?
我今天遇到了同样的问题,并决定更新到 v2 版本或切换到该库的 java 版本不是一个选择。
所以我尝试做像你一样的事情,但没有成功。我意识到的原因是,jar 是在单个函数调用之后编写并加载的(
Valid()
),因此您不能简单地在编写后修复 jar。
我发现的解决方案虽然非常hacky,但最终还是起作用了:启动一个具有非常紧密的无限循环的线程,等待jar完全写入(通过查询其大小来确定),然后将文件翻转为只读。如果运气好的话(看来运气站在我们这一边),这种翻转可能会在操作系统代码检查只读条件之前发生。
实际上有两个不同的 jar 文件需要修复。
这是完整的代码。这是在 C++ 方面,同样的想法也可能在 Java 中起作用,我不确定。 请注意,这很可能仅适用于arm64版本的库 - 我在其他版本中没有找到相同的校验和字符串,因此可能需要更多的手动工作。
static void fixup_jar(const std::string& name, unsigned expected_size, const bool& done) {
// Work around an issue with API level 34 and the old google play games lib we're using.
// The SDK writes to a jar file and tries to load it. The system refuses to load non-read-only files.
// So we do our best to make it read-only just in time...
const std::string path = ANDROID_DEFAULT_FILES_DIR + std::string("/../app_.gpg.classloader/") + name + ".jar";
unlink(path.c_str());
bool thread_started = false;
auto t = std::thread([=, &thread_started, &done]() {
thread_started = true;
while (!done) {
struct stat st;
stat(path.c_str(), &st);
if (st.st_size == expected_size) {
chmod(path.c_str(), S_IRUSR);
break;
}
}
});
t.detach();
while (!thread_started);
}
void android_leaderboard_init(jobject mainActivity) {
platform_configuration.SetActivity(mainActivity);
if (!platform_configuration.Valid()) {
for (unsigned int i = 0; i < 10; ++i) {
bool jars_done = false;
fixup_jar("4105d0375b9d69fe6ee3a07b7893a4f1_games", 1881, jars_done);
fixup_jar("6e3966b0d5618671dcdc0ea28384da37_nearby", 1066, jars_done);
if (platform_configuration.Valid()) {
jars_done = true;
break;
}
jars_done = true;
}
}
if (!platform_configuration.Valid()) {
abort("invalid platform config");
}
}