FileUtilsAndroid::getWritablePath() crash on android

Hi, I have a crash the second time this function is called.

The first is at the very beginning inside AppDelegate::applicationDidFinishLaunching() and the path is correct.

The second time is during the game when trying to capture an image inside RenderTexture::saveToFile the app crashes.

This second time the call was originated from a callback. Could it be a thread-safe problem?

It was working ok before migrating to androidx and setting PROP_COMPILE_SDK_VERSION=28. Or at least I haven’t noticed a crash before. :slight_smile:

The crash is on a physical device (tablet-android)

Any suggestion?
Thanks in advance :slight_smile:

Screen Shot 2021-06-23 at 8.10.31 PM

Yes, it could be the thread issue. You can apple callback to rendertexture or perform in cocos-thread.
And BTW you can directly call this
FileUtils::getInstance()->getWritablePath()
You dont need to call JNI method for that.

@Marce Yes it’s most likely a thread-related issue, so try out Scheduler::performFunctionInCocosThread(...) to handle it, as @smitpatel88 mentioned, or you could also try Node::scheduleOnce(...) to run the screenshot on the next update loop.

@smitpatel88 getWritablePath() is overriden in the Android implementation of FileUtils, so calling FileUtils::getInstance()->getWritablePath() is actually calling FileUtilsAndroid::getWritablePath(), which internally calls the JNI method.

Yes, i know that. But it will be cross-platform so better to use that.

I’m not quite sure that I understand what you mean, because the code @Marce pasted is Cocos2d engine code, not user code, and the screenshot doesn’t show any user code calling FileUtilsAndroid::getWritablePath() directly:

string FileUtilsAndroid::getWritablePath() const
{
    // Fix for Nexus 10 (Android 4.2 multi-user environment)
    // the path is retrieved through Java Context.getCacheDir() method
    string dir("");
    string tmp = JniHelper::callStaticStringMethod("org.cocos2dx.lib.Cocos2dxHelper", "getCocos2dxWritablePath");

    if (tmp.length() > 0)
    {
        dir.append(tmp).append("/");

        return dir;
    }
    else
    {
        return "";
    }
}

I’m assuming the getWritablePath() call in the callstack is coming from here, since Marce mentioned the use of RenderTexture::saveToFile:

bool RenderTexture::saveToFile(const std::string& fileName, Image::Format format, bool isRGBA, std::function<void (RenderTexture*, const std::string&)> callback)
{
    ...
    std::string fullpath = FileUtils::getInstance()->getWritablePath() + fileName;
    ...
}

Hi all, I’ve found the problem. It was a non-initialised pointer in a java class while trying to log the event into Firebase.
It was not a thread safe problem or any other problem inside RenderTexture.
I wonder why RenderTexture was affected though.
Sorry for the noise and thank you for the suggestions :slight_smile: