Unfortunately I will say, regardless of the solution you want is not possible, at one point or another it can be broken, simulated or emulated.
Asymmetric or symmetric key does not change that.
All these techniques will only hinder, but never inhibit the actions of someone with knowledge and interest.
In these cases you should work with the type of security that is worth. Do not put something too complex because it needs to be maintained, or put something too sophisticated, as perhaps a simple key will never be seen. It all depends on the type of application and the interest of those who are aware.
Given just one line to guide you, see how to obscure your code. Using Java with C mix also helps.
Obscuring can also be used at the API level, but in these cases you use something like swagger to define the API, and then some other solution depending on the language to shuffle the requests.
Using SSL in the endpoint makes it difficult to break, if used together as GRPC already increases the level of complexity with performance gains but with increased infrastructure spending.
One solution is to use a key in each version of the APK. Whenever a new version exits you disable access of 1 or 2 previous versions, join this with GRPC, and maybe with the generation of 'login' per installed application, each holding a registered key, or even a login itself where you return a key to be used (asymmetric) where you can selectively cancel the ones you want.