[UE4] Get 13-bit timestamp

UE4 itself provides a FDateTime::ToUnixTimestamp function that can convert the system time into a timestamp, but FDateTime::ToUnixTimestamp can only provide a 10-digit time error. FDateTime does not provide a 13-digit timestamp, and check FDateTime: : The source code of ToUnixTimestamp is indeed only accurate to the second.

FString UBPFunctionLibrary::GetTimestamp()
{
	FString Timestamp;
    FDateTime Time = FDateTime::UtcNow();
    int64 unixTimestamp = Time.ToUnixTimestamp();
    Timestamp = FString::Printf(TEXT("%lld"), unixTimestamp);
    UE_LOG(LogTemp, Log, TEXT("Timestamp:%s"), *Timestamp);
    return Timestamp
}

output:

LogTemp: Timestamp:1651734043

When we need to use a 13-bit timestamp, UE does not seem to be able to provide it, so it can only be obtained by means of C++.

#include <windows.h>
//...
FString UBPFunctionLibrary::GetTimestamp()
{
	string nowTimeUnix;
	string cs_uninxtime;
	string cs_milliseconds;
	SYSTEMTIME sysTime;
	GetLocalTime(&sysTime);
	time_t unixTime;
	time(&unixTime);
	char buf[30], bufms[30];
	sprintf_s(buf, sizeof(buf), "%I64d", (INT64)unixTime);
	sprintf_s(bufms, sizeof(bufms), "%03I64d", (INT64)sysTime.wMilliseconds);
	nowTimeUnix = string(buf) + string(bufms);
    FString Timestamp = FString(nowTimeUnix.c_str());
    UE_LOG(LogTemp, Log, TEXT("Timestamp:%s"), *Timestamp);
	return Timestamp;
}

output:

LogTemp: Timestamp:1751734043331

The above method can only be used on Windows, if you need to use it on Andriod, you can directly encapsulate java library functions. Then use the JNI framework of UE4 to call the java function to achieve the effect of obtaining a 13-bit timestamp on Android.

UE4 calls java functions through an intermediate XML file. We encapsulate the functions that need to be called with java functions in XML, and then call this encapsulated function in UE4 to realize indirect calls.

First create an XML file, named here: JavaTest.xml:

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:android="http://schemas.android.com/apk/res/android">
    <gameActivityClassAdditions>
        <insert>
            <![CDATA[
            public String getSystemTimestamp()
            {
                long now = System.currentTimeMillis();
                return String.valueOf(now);
            }
   		]]>
        </insert>
    </gameActivityClassAdditions>
</root>

Write our wrapper function in the gameActivityClassAdditions tag, here directly call the Android library function to get the current timestamp.

Then we need to indicate this XML file in the .Build.cs file:

using UnrealBuildTool;
using System.IO;

public class JavaTest423 : ModuleRules
{
	public JavaTest423(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

        if (Target.Platform == UnrealTargetPlatform.Android)
        {
            PrivateDependencyModuleNames.Add("Launch");
            AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(ModuleDirectory, "JavaTest.xml"));
        }
    }
}

Since it only needs to run on Android, a platform judgment is made here.

Then create an Actor—JavaTest, and call this java function in the Actor:

#include "JavaTest.h"
#include "Kismet/KismetSystemLibrary.h"

#if PLATFORM_ANDROID
#include "Android/AndroidApplication.h"
#include "Android/AndroidJavaEnv.h"
#include "../Source/Runtime/Launch/Public/Android/AndroidJNI.h"
#endif
AJavaTest::AJavaTest()
{
	PrimaryActorTick.bCanEverTick = true;
}
void AJavaTest::BeginPlay()
{
	Super::BeginPlay();
    Timestamp();
}
void AJavaTest::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}
FString AJavaTest::Timestamp()
{
    FString Timestamp;
#if PLATFORM_ANDROID
    jstring JavaString = NULL;
    if (JNIEnv* Env = FAndroidApplication::GetJavaEnv(true))
    {
        //寻找方法的地址
        static jmethodID MethonId = FJavaWrapper::FindMethod(Env, FJavaWrapper::GameActivityClassID, "getSystemTimestamp", "()Ljava/lang/String;", false);
        //通过地址调用方法
        JavaString = (jstring)FJavaWrapper::CallObjectMethod(Env, FJavaWrapper::GameActivityThis, MethonId);
        if (JavaString != NULL)
        {
            const char* JavaChars = Env->GetStringUTFChars(JavaString, JNI_FALSE);
            Timestamp = FString(UTF8_TO_TCHAR(JavaChars));
            Env->ReleaseStringUTFChars(JavaString, JavaChars);
            Env->DeleteLocalRef(JavaString);
        }
    }
#endif
    UE_LOG(LogTemp, Log, TEXT("Timestamp:%s"), *Timestamp);
    return Timestamp;
}

Then make an Android package, install it on the phone and run it, and check the printed log:

830: 05-06 20:38:28.134  5103  5159 D UE4     : [2022.05.06-20.38.28:134][  0]LogTemp: Timestamp:1651840708134

Guess you like

Origin blog.csdn.net/qq_39108291/article/details/124618338