Regardless of OAuth2 PKCE flow or any other flow, the question boils down to "can the server check the application integrity?". The answer to this question is simply NO.
The application resides in user land, meaning that an attacker has full control over the application. The attacker can install it on his device, patch it, dynamically change its behaviour (hooking) or change values in-memory etc...
The only thing you can do is to make it hard for an attacker to mess with your application. A few counter measures are:
- Root/jailbreak detection.
- Code obfuscation: includes obfuscating method/variable names, control flow obfuscation etc...
- Something called Runtime Application Self Protection (RASP): this usually includes hook detection & debugging detection.
- Encryption: for example in Android it's possible to dynamically load a DEX file, some apps load an encrypted DEX file in memory and decrypt it.
- Device finger printing: check for example if device is run inside emulator.
The above counter measures can be implemented in different ways. There are products out there that can do this for you. In the end, it is possible to bypass all such measures but it requires some effort. The question usually boils down to threat modeling: What are you trying to protect? How much do you want to spend on such solutions? What can an attacker achieve if these solutions are bypassed? How easy/hard is it?
Also don't forget about communication hardening. You can implement all above measures but an attacker can for example also use a mitm proxy like Burp to intercept and change data in transit. So using TLS everywhere might be a given, but don't forget about hardening measures such as TLS-pinning. To be honest, this is easy to bypass if you ask me. I've seen some people get creative and do stuff such as: encrypting and signing the payloads sent to the server, using binary protocols instead of HTTP and much more.
Remember, at the end of the day, a motivated attacker can overcome all these hurdles.