I am writing a game in java, and i would like to save my game. I am going to save it as a set of XML documents in a zip file. What i would like to know is if their is a way i can do this transparently so that the user cannot edit these files, or find them. I have thought about just making the files hidden, but that seems like a dirty and ugly way to do this. The thing i like least about the hidden files is that they don't seem compatible between systems. If their was anyway to save the files to the jar and read them from it that would also be equally as acceptable. Also there doesn't seem like a good way in java to make a file hidden. Any help would be greatly appreciated.
What i would like to know is if their is a way i can do this transparently so that the user cannot edit these files, or find them.
Ultimately, no.
Anything that you do to store state on the local machine can ultimately be reverse engineered and that state can be retrieved by a privileged user.
But there are various things you could do to make it difficult for people to "cheat". For instance, you could encrypt the file, or generate a seeded hash to detect "tinkering".
Hiding files on Java 7 is simple:
Path path = FileSystems.getDefault().getPath("directory", "hidden.txt");
Boolean hidden = path.getAttribute("dos:hidden", LinkOption.NOFOLLOW_LINKS);
if (hidden != null && !hidden) {
path.setAttribute("dos:hidden", Boolean.TRUE, LinkOption.NOFOLLOW_LINKS);
}
(Copied from: http://javarevisited.blogspot.com/2012/01/how-to-hide-file-java-program-example.html)
On earlier versions of Java you needed to call an external Windows application or call a native library to do it. But note that:
"hidden" files are only hidden from users who don't bother to look
they work differently on different platforms; e.g. for Linux/Unix based systems, "hidden" just means that the filename starts with a ".".
Related
Ok, the question is quite simple.
I have a Java program, which I am extracting some save-files to an external location.
Right now, I use C:/ApplicationName, however, that is a very bad way to do that.
I know alot of locations i could use, for instance:
%Appdata%
C:\Program Files (x86)
C:\Users\Users\Documents (Ive seen some indie games use this.)
Other locations?
But I can't figure out, when to use the proper one.
And if i want to support Linux and OSX, is there a libary, which supports that, or do i manually have to wrap them into an if/else with System.getProperties("os.name")?
Keep in mind that sometimes when games save to a specific directory, they aren't built to be cross-platform.
There are two ways you could do this. The first (and personally my preferred version) is to save in the directory of the application. This also has the advantage of being portable. However, the saves are linked to the application, so if the user deletes the application and reinstalls later they'll lose their data (which may or may not be a good thing).
Another option is to use System.getProperty().
Specifically, you can use:
System.getProperty("user.dir");
System.getProperty("user.home");
System.getProperty("user.name");
To figure out where to put your files.
This will be a lot more complicated, so the first method is preferred.
If it's data the user does not need direct access to, such as stored application/game state data, then it's appropriate to store it in the user's application data directory. Try this:
1) Determine the OS.
2) Get the user home directory.
System.getProperty("user.home");
3) Append OS-specific application directory:
Mac: /Library/Application Support/MyApp
Windows: \\Application Data\\MyApp
Linux: MyApp (there's no convention here that I know of)
If the data needs to be exported, such as saving a document from your application, then ask the user where to store the file via a file dialog, defaulting to their Documents directory.
When we want to load a static file e.g. a picture, a sound file, a file containing information about a game map,... we can store them as resources in jar file and use getClass.getResource("images/splash.png") (also getResourceAsStream) to load and use them. But when we want to read and write into a file like settings file, I don't think using resources is a good way, because i think resources are designed to store read/only files that are not supposed to change, like splash screen image or a game's background music; These are my reasons to think this way:
That is why return value of getResourceAsStream is an instance of InputStream and we don't have a similar function which gives us an OutputStream, because we're not supposed to alter resource files.
Writing into resources changes program .jar file and i guess it's not a good thing at all; Because if we do so: we can't use check-sums to verify file, if we are a limited user and system administrator doesn't give us write permission we can't make changes into main .jar file, user-specific preferences are hard or impossible to implement,...
So, my questions are:
Which parts of my thoughts and assumptions are right or wrong?
If they're right what is the best(I mean short and portable between OSs and Computers) way to store files like that? (Application setting/preferences, A game save file, ...)
(#Some user who may wants to mark this as duplicate: I don't think my question is a duplicate, i searched in the site, I admit it has some common parts with some questions but it's not duplicate!)
Your three observations in #2 above are valid reasons not to store settings in a resource file, regardless of the APIs provided.
There are a variety of ways to save settings in Java, including:
The Java system property "user.home" provides the user's home directory, to which the user should have write access. You can create an application-specific subdirectory underneath it.
Java provides a Preferences API. This may store settings in a directory or (on Windows) in the registry.
OSGI provides a preferences API.
If you're using the Eclipse RCP, you can write to the configuration directory using a ConfigurationScope. See the Eclipse FAQ "What is a preference scope").
In the recent versions of windows, you can hit the start menu and start typing to search for files across the filesystem. Is there a way to do that programmatically in Java?
My specific purpose is to allow the user to choose a file or directory. The user could start typing a file name directly inside the application and it could start showing suggestions. Much easier than navigating directories in a typical file chooser.
This post details a way to do this in Windows, by accessing the native functionality:
Query Windows Search from Java
And this one details how you can do something similar (using mdfind) under Mac OS:
http://lists.apple.com/archives/Java-dev/2006/Oct/msg00224.html
What you're asking for in the second part of your question could be done with a simple:
File dir = new File( "/path/to/dir" );
String[] contents = dir.listFiles();
The first part is a bit harder, but it could be accomplished inside Java using the same technique called recursively. (for(String fl: contents){ /* do the above */ })
You don't want to worry about supporting wrappers around command line calls here. That is anti-platform independent.
you could write JNI code to wrap+expose any windows native functionality.
If it's just for autocomplete style behavior in a file dialog, you don't need to wrap the native functionality, you can just use standard stuff in java.io.
Sounds unlikely ti be a part of Java, since Java is supposed to be platform-independent. Such searches should require some sort of index over all files, to be efficient, also.
For my app I download some resources like images and small mp3 and save them in the external storage (at /mnt/sdcard/Android/data/com.example.packagename/cache for example.
But I don't want that if a user explores that folder finds all the resources in a "common format".
One of my options is to remove the extensions (I know it's easy to guess the file type even if it have not extension but is a basic protection against most users)
I have noticed most of the programs that have their caches at the external storage don't have their cache as raw files.
I wonder if is there any easy way (with some class or something) for "hiding" those files and access them transparently or I must implement my own system
(It is not vital that these files remain hidden but I'd like keep those resources "unknown" unless a user takes a special trouble to see them)
Thanks
You can use ObjectOutputStream, it will save data as binary data, when the user tries to open it, even using Text Editor, it will show corrupted data, and here some sample how to use it Writing objects to file with ObjectOutputStream
I'm currently developing an application for a company which includes livescoring. The XML-files I access (from the net like: "http://company.com/files/xml/livescoring.xml") are not intended to be public and should only known to me.
I was wondering if it is possible for anyone to decode the .apk file and read my original .java files (which include the link to the XML files).
So, I renamed the .apk file to .zip and could access the "classes.dex", which seemed to include the .java files (or classes). Googling led me to a tool named "AvaBoxV2" which decoded this "classes.dex" file. Now I have a folder including an "out" folder where files named .smali exist. I opend one of these with an editor and finally there is the link to the xml file. Not good. :(
Is there a way to encrypt my app or the classes.dex file? I don't want to tell that company, that anyone can access the original xml-files. Maybe signing the app probably helps?
Also, do you know a really noob-friendly tutorial to prepare apps (signing, versioning,...) for Google Market?
Thanks in advance!
The .java source code is not included in the APK.
It is possible to disassemble the Dalvik bytecode into bytecode mnemonics using a tool like baksmali, but there's no way a user can recover the original .java source.
Furthermore, you can use a tool like proguard (included in the Android SDK) to obfuscate your byte code, making it hard to interpret the behavior of the disassembled bytecode.
You can make small tricks too, like storing the link string in some sort of obfuscated form, and then de-obfuscating it at run-time in your app (a simple example would be to use base 64 encoding, but someone could probably reverse that quickly if they wanted to).
That said, it's pretty trivial for someone to run tcpdump and sniff the network traffic between your device and the server, and get the URL that way, so there's no way to completely prevent anyone from getting this value.
Yeah, its impossible to fully prevent something like this. Its the same on a desktop application, or any other application.
As mentioned, obfuscation will help, but people who are persistent can still get past it. Especially for something like a url like that.
One solution of making it much more tricky for hackers is to use PHP on your webserver and some sort of token system to determine if the request is coming from your app or not... That would get a bit tricky though, so I don't really suggest it.