As the general consensus is so far, its impossible to prevent anyone hell-bent upon "cracking" your APK from doing so. Obfuscation techniques will only increase the complexity required to "crack" the APK once. After it gets uploaded to the myriad of the sites that offer to host APKs for free, its just a google search away from even the "noob-est" of Android noobs.
Also security through obscurity will NOT get you far.
Regarding protecting your APK from being hacked, i would recommend the following article that discusses the current state of license validation of APKs on Android. The techniques described in it should give you an idea of the common attack-vectors that you need to safeguard against.
Proguard is a good place to start obfuscating your APK.
After you manage to obtain an obfuscated APK, DO run it through the following tools and observe the de-compiled source. All these are free and open-source tools that are very popular and will surely be the first thing that any decent "cracker" will try :
1. baksmali
2. apktool
3. Dex2Jar + JD-Gui
Keep adding layers of obfuscation to your code until you are satisfied that the output of the above tools is fairly complicated to make sense. (Again do NOT under-estimate what a college-grad armed with coke, pizza and the knowledge of DVM opcodes can accomplish over a weekend).
Regarding the techniques discussed in the link you shared, i fail to see how they can be implemented to protect the .dex
on Android. And if you end up implementing the verification logic in a separate .so
then all the "cracker" would need to do is patch the call in your java code to the verify() function inside the .so
.
UPDATE:
Additional obfuscation steps to secure the .so
.
1. Do NOT follow a more or less linear path.
Adding additional jumps all over the place works by flooding the "cracker" with so many potential targets which need to be individually modified and patched and verified if the protection has been bypassed.
2. Add timing checks
This is mainly to throw off the "cracker" by making the code follow different paths during debug and actual run-time. If the time spent between two points is a lot more than usual then its a clear indication that your program is being debugged. i.e time to jump into that part of junk code that calculates the number of pianos in the world.
3. Write self modifying code
Again this thwarts static analysis. For example if your jump into the verification function does not exist in the binary but is patched everywhere as part of some init() function in the .so
.
All the above techniques(and more) are described with examples in the following article on anti-debugging techniques.
A more comprehensive guide is Ultimate Anti Debugging Reference by Peter Ferrie.