Page 1 of 1

Android Development

Posted: Thu Aug 17, 2017 3:31 pm
by christian
There's more to an Android application than what you see in the Unreal logs. Make sure you know how to see the actual device logs too.

You can get them by using adb.

Code: Select all

adb logcat > mylog.txt

Re: Android Development

Posted: Thu Aug 17, 2017 3:44 pm
by christian
Want to know how to hook into native Android events? Yeah, you could just hack up the engine's GameActivity.java file at Engine\Build\Android\Java\src\com\epicgames\ue4, but that isn't the best way to do it.

Instead, use an UPL file!

Documentation here: https://github.com/EpicGames/UnrealEngi ... anguage.cs

Make sure you've got it configured properly in your Build.cs file:

Code: Select all

if (Target.Platform == UnrealTargetPlatform.Android)
{
        AdditionalPropertiesForReceipt.Add(new ReceiptProperty("AndroidPlugin", Path.Combine(ModuleDirectory, "My_APL.xml")));
}

Re: Android Development

Posted: Thu Aug 17, 2017 4:28 pm
by christian
If you're using a third-party API, having it read files can be tricky.

Here's a good explanation - https://forums.unrealengine.com/showthr ... -quot-work
Chris Babcock wrote: The files are packaged so you cannot use low-level fopen to access them. You need to use the file system.
https://forums.unrealengine.com/showthr ... iles-along
Chris Babcock wrote: The OBB is embedded in the APK in the assets directory as "main.obb.png".

just use extern FString GExternalFilePath and protect any code using it with #if PLATFORM_ANDROID / #endif.

Something like this should copy all the files in the provided directory (assuming it was in Contents) to GExternalFilePath:

Code: Select all

void CopyAllAssetsToExternal(FString inDirectory)
{
#if PLATFORM_ANDROID
	// only do this on Android
	extern FString GExternalFilePath;
	FString DirectoryPath = FPaths::GameContentDir() / inDirectory;
	IFileManager* FileManager = &IFileManager::Get();

	// iterate over all the files in provided directory
	TArray<FString> directoriesToIgnoreAndNotRecurse;
	FLocalTimestampDirectoryVisitor Visitor(FPlatformFileManager::Get().GetPlatformFile(), directoriesToIgnoreAndNotRecurse, directoriesToIgnoreAndNotRecurse, false);
	FileManager->IterateDirectory(*DirectoryPath, Visitor);

	for (TMap<FString, FDateTime>::TIterator TimestampIt(Visitor.FileTimes); TimestampIt; ++TimestampIt)
	{
		// read the file contents and write it if successful to external path
		TArray<uint8> MemFile;
		const FString SourceFilename = TimestampIt.Key();
		if (FFileHelper::LoadFileToArray(MemFile, *SourceFilename, 0))
		{
			FString DestFilename = GExternalFilePath / FPaths::GetCleanFilename(*SourceFilename);
			FFileHelper::SaveArrayToFile(MemFile, *DestFilename);
		}
	}
#endif
}
Then you can give the filename to your third-party library prefixed with GExternalFilePath.