1. If my phone has Internet connections, whenever the screen is turn on, the code is refreshed.
If the code is solely based on time, the app may sync its time tick with the server every time when it's turn on.
If the app sends its time to the server, the synced time value should also be encrypted and authenticated. The only pre-shared credential is the 6-digit pin sent by sms, which might be a little short.
If the app gets the time from the server, it might have a slight time delay before the code is computed and shown due to the network latency.
2. If my phone doesn't have Internet connections, the code is only refreshed in ~5s.
So I guess every 5s the app will generate a new code for the next 0~25s.
When the server wants to verify the received code it will check whether it matches with the codes generated in 0s, 5s, 10s, 15s and 20s.
So at least 5 different codes should work in the same time. This may be a nice way.