You may use ProGuard.
Or you can save purchased status in secure way using some Encrypted text either in shared preference or in database. So it gets harder to manipulate it.
Encryption example:
Encrypt:
MCrypt mcrypt = new MCrypt();
String encrypted = MCrypt.bytesToHex(mcrypt.encrypt("Text to Encrypt"));
Decrypt:
MCrypt mcrypt = new MCrypt();
String decrypted = new String(mcrypt.decrypt(encrypted));
Mcrypt.java
public class MCrypt {
private String iv = "fedcba9876543210";
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
private String SecretKey = "0123456789abcdef";
public MCrypt() {
ivspec = new IvParameterSpec(iv.getBytes());
keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception {
if (text == null || text.length() == 0) throw new Exception("Empty string");
byte[] encrypted = null;
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
try {
encrypted = android.util.Base64.encode(encrypted, android.util.Base64.NO_PADDING);
} catch (NoClassDefFoundError e) {
}
return encrypted;
}
public byte[] decrypt(String code) throws Exception {
if (code == null || code.length() == 0) throw new Exception("Empty string");
byte[] decrypted = null;
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
try {
decrypted = cipher.doFinal(android.util.Base64.decode(code, android.util.Base64.NO_PADDING));
} catch (NoClassDefFoundError e) {
}
return decrypted;
}
private static String padString(String source) {
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++) {
source += paddingChar;
}
return source;
}
}
Reference:
128 bit encryption