Reputation: 1804
I installed a game on my rooted android phone. I want more coins. And I know that, player data is stored using playerprefs.(I have part of source code of this game.) So I edit the xml file, which locate at
/data/data/appname/shared_prefs/appname.xml
I edited corresponding number of coins. But when the game got launched, the amount of coins is not what I want. And I open the xml file again, only found the modify corrected. I tried a lot times.
What should I do?
Upvotes: 0
Views: 4787
Reputation: 5353
You should have posted or created a miniumum, complete and verifiable example, but I'll do that now myself. I created a new Unity project, and attached that script to the main camera:
using UnityEngine;
using System.Collections;
public class PlayerPrefsScript : MonoBehaviour {
private int readCoins;
void Start()
{
if (!PlayerPrefs.HasKey("coins"))
{
PlayerPrefs.SetInt("coins", 1);
PlayerPrefs.Save();
}
readCoins = PlayerPrefs.GetInt("coins");
}
void OnGUI()
{
GUI.Box(new Rect(Screen.width / 2 - 150 / 2, Screen.height / 2 - 25 / 2, 150, 25),
"Coins: " + readCoins.ToString("N0"));
}
}
The script will create the key "coins"
if the key doesn't exist (first run) and save the value 1 in it. Then, the value of that what is saved under key "coins"
will be saved in readCoins
. In OnGUI()
it draws a simple 150x25 pixels box that will display the number of read coins. Simple enough, if you compile the app for Android and let it run (I'm doing this inside the BlueStacks emulator), you see:
You can see in the file system, that the PlayerPrefs have been saved where you predicted.
C:\>adb connect 127.0.0.1:5556
connected to 127.0.0.1:5556
C:\>adb.exe -s emulator-5556 shell
root@generic:/ # cd /data/data/com.mycompany.PlayerPrefsTest/shared_prefs && ls -lh
-rw-rw---- u0_a58 u0_a58 361 2015-10-19 19:01 com.mycompany.PlayerPrefsTest.xml
root@generic:[..]/cat com.mycompany.PlayerPrefsTest.xml
That gives you the XML:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<int name="coins" value="1" />
<int name="Screenmanager Resolution Height" value="1920" />
<string name="5.2.1">293797f02df348f6b7238da14b30277d</string>
<int name="Screenmanager Is Fullscreen mode" value="0" />
<int name="Screenmanager Resolution Width" value="1080" />
</map>
So I edited it to 999999 and got
C:\>adb.exe -s emulator-5556 pull "/data/data/com.mycompany.PlayerPrefsTest/shared_prefs/com.mycompany.PlayerPrefsTest.xml" prefs.xml
64 KB/s (361 bytes in 0.005s)
*edit it*
C:\>adb.exe -s emulator-5556 push prefs.xml "/data/data/com.mycompany.PlayerPrefsTest/shared_prefs/com.mycompany.PlayerPrefsTest.xml"
4 KB/s (366 bytes in 0.085s)
Start up the game again and...
There's something going on you don't know about. If the game would just read that value, it should have worked as I demonstrated. Ergo, maybe the game saves it in another format, aswell, or has backup-values if it detects an abnormal change of score. Does even a slight increase of coins cause the value to be reset? In that case, only further reverse-engineering the application will help you with finding out what's going here. But you can rule out the simple PlayerPrefs.GetInt()
now.
If it is legal for you to do reverse-engineering on the app, go grab the latest Android MuliTool (nice all-in-one tool) from their google drive , project pageand run the decompiler on it. I'll demonstrate that on my app here.
In the unzipped tool folder, under "Decompiled apk", you will find the app's folder structure.
└───app
│ AndroidManifest.xml
│ apktool.yml
│
├───assets
│ └───bin
│ └───Data
│ │ mainData
│ │ settings.xml
│ │ sharedassets0.assets
│ │ splash.png
│ │ unity default resources
│ │
│ ├───Managed
│ │ Assembly-CSharp.dll
│ │ Mono.Security.dll
│ │ mscorlib.dll
│ │ System.Core.dll
│ │ System.dll
│ │ UnityEngine.dll
│ │ UnityEngine.dll.mdb
│ │ UnityEngine.Networking.dll
│ │ UnityEngine.UI.dll
│ │ UnityEngine.xml
│ │
│ └───Resources
│ unity_builtin_extra
...
All compiled C# scripts are in the "Assembly.CSharp.dll" file under assets\bin\Managed. Grab Telerik's decompiler "JustDecompile" (website) and run the file on it. You will be able to see that all scripts are in their respective namespaces (the default namespace in my case), and the decompiler will output that compiled MSIL code from script in nicely-readable C# syntax:
And as such, all Scripts can be retreived again in a well-readable format.
Upvotes: 6