Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store in-app items data on device

I want to add in-app purchase functionality to my application, and I would like to know what is the recommended way to store the available count of a product (for example 100 coins).

A user with root access can:

  • access/manipulate unencrypted data that the application store (so he can change the number of coins).
  • save the encryped (or obfuscated) data, and then later replace it to get back the state when he had much more coins

So even with encryption, it is relatively easy to cheat. My questios are:

  • should I go any further than encrytion? (does it worth the effort?)
  • is it common that users abuse this?
  • is there a better way to store item counts?
  • what is the practise?
like image 776
kupsef Avatar asked Mar 22 '26 13:03

kupsef


1 Answers

Store your game-world currency locally and let transactions occur locally without network connection, but when the user reconnects to the internet, reconcile the local coins with what the server shows as purchased.

Basically, when you have a network connection, download any purchased in-app products from Google. Check your inventory, then consume whatever products should be reduced based on what the user did while offline. After doing this, if there's a discrepancy between the local total and what the server shows (after consuming), then flag it as a potential hack. Otherwise, you're good (everything balances).

When using consumable in-app products like this (which it sounds like you're trying to do), there's really no completely offline way to do it. You're relying on Google's in-app billing services, so you have to check their servers from time-to-time to reconcile/refresh the purchased inventory. From Google's in-app billing documentation:

To record a purchase consumption, send the consumePurchase method to the In-app Billing service and pass in the purchaseToken String value that identifies the purchase to be removed. The purchaseToken is part of the data returned in the INAPP_PURCHASE_DATA String by the Google Play service following a successful purchase request. In this example, you are recording the consumption of a product that is identified with the purchaseToken in the token variable.

int response = mService.consumePurchase(3, getPackageName(), token);

Warning: Do not call the consumePurchase method on the main thread. Calling this method triggers a network request which could block your main thread. Instead, create a separate thread and call the consumePurchase method from inside that thread.

It's your responsibility to control and track how the in-app product is provisioned to the user. For example, if the user purchased in-game currency, you should update the player's inventory with the amount of currency purchased.

As for how to store and manage inventory while offline, the ways you've mentioned sound fine. Encrypting doesn't hurt, but likely unnecessary as long as you reconcile with Google at reasonable intervals. Only a very small percentage of people actually try to exploit apps. Most users don't root, and for those that do, most actually have no clue how to pull off these exploits. If you're still worried about it, yes, go ahead and encrypt. That should be sufficient enough of a deterrence to keep the vast majority of your users honest.

like image 179
hungryghost Avatar answered Mar 25 '26 01:03

hungryghost



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!