将 Target SDK 从 33 更新到 34 后,Google Play 游戏服务 (C++) 无法初始化

问题描述 投票:0回答:1

Android Target SDK33 更新到 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不再显示。尽管如此,其他日志消息仍然显示,并且游戏服务的初始化失败。

有谁知道这个问题有什么解决办法吗?

android google-play-services google-play-games dex targetsdkversion
1个回答
0
投票

我今天遇到了同样的问题,并决定更新到 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");
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.