Apk of the game has 4 sets of libraries for different ABIs: armeabi-v7a, arm64-v8a, x86, x86_64. In my case 32-bit android emulator for Windows was used causing game libraries for x86 to be used. Correspondingly, all library-specific values like offsets that will be shown or mentioned in this post are only applicable to game's library for x86.
Values of interest (coins, diamonds, max workers) are located in bss section of libnative-lib.so library. They can't be edited directly because game computes sha-256 hashes of several blocks of memory with important values and checks validity of stored hashes during every operation that includes reading or writing protected values.
So in order to be able to directly edit values of interest in process memory verification of hashes needs to be disabled first. With GG it can be done by editing instructions in code segment of the library in process memory. The function that needs to be modified in library is named "IsMatchHash". It is located at offset 0x16E480 from library start. There are at least several different modifications of function's instructions to achieve desired result of function always returning 1 (true). One of the options is to modify 2 subsequent instructions at offsets 0x16E507 and 0x16E50A (see illustration below) to MOV AL, 0x1 (B0 01), MOV BYTE PTR [EDI + 0x29] (C6 47 29 01) and NOP (90) to edit all 7 bytes of original instructions.
To find values of interest in process memory, besides using offsets to them from library start that can be discovered by analysis of library with the help of disassemblers, GG search capabilities can be used. Memory ranges with bss sections of application libraries in GG in most cases are classified as "Cb: C++ .bss". This can be used to find values of interest faster and more accurately by selecting only "Cb" type in list of memory ranges types. Having that done, there is one simple approach to find values of interest by searching for nearby value - player name string. For example, if player name is "TestPlayer123", in GG it can be searched with search string ":TestPlayer123". Colon as first character of search string means to search for specified UTF-8 encoded string. One occurrence of player name string is expected to be found. Values of interest are located within several hundred bytes from first byte of the string.
After finding values of interest, adding them to saved list and assigning corresponding names to them, saved list looks like this:
Maximal amount of workers is plain dword value that can be simply edited to desired one. Coins and diamonds are each stored as two separate dword values that give real value when they are XOR'ed (value1 XOR value2 = real_value). Either first or second value can be edited to 0 and the remaining value can then be edited to desired one. This works because value XOR 0 = value.
Finally, here is an illustration of the result of modifying values of interest: