I'm trying to make a Java game updater launcher for my game. Similar to how minecraft works. However, minecraft has only a few .jar's to download wheras I would need to redownload all of my game assets. Is there any easy way for Java to check a file for which operations need to be taken? One idea I had was using .7z files since those can be compressed really small. That wouldn't work though because I can't seem to get Java to hook onto 7zip operations. Another idea I had was if it determined if an update was needed it would read a file with a set of commands like this:
remove assets/models/malecharacter.obj
add assets/models/alien.obj
...etc
But I'm not sure this is very efficient and I am also not able to find a lot of help with managing files. Any help and ideas would be appreciated.
I made a Game Launcher in Java recently, I still have a few problems to solve like how to update the launcher itself.
Anyhow, for the game updates/versions I just have a "versions" folder with a folder for each downloaded version, it might not be the prettiest of solutions but it works for multiple versions and it's easy to make.
My launcher checks a URL from my dedicated server which has all available versions, which I call it versionlist, then since the versions folder on the server obeys a path order I can call any versions which are in the versionlist. I download the selected version and extract it to a separate version folder on the user's pc.
Related
I was working on an update launcher for a java .jar application. I have several .jar-archives and a main.jar. My launcher adds/replaces the necessary jars when updating.
I am just not sure what criterias to look after. So I'll describe how the process works and you might tell me if I forgot something.
Load and compare version.xml file from ftp update server
Make a list of updated items with the help of both version.xml files
Check (to be sure) if those files which are still valid really do exist on hard drive (either add them to the list of items that needs to be downloaded...shouldn't happen anyway)
Create a list of files that needs to be downloaded (those items are on the server in a compressed form)
Download all needed files to /temp folder
Unpack all files to /temp/unpack
Move all unpacked files to /data folder (or where they belong to)
Update local version.xml
Check if all files match the actual version-file-list
I am really not sure if I forgot something? If some users mess around with files in /data my updater recognizes this and proposes a "repair-update" where all missing files are beeing redownloaded. But what about users messing around with version.xml? I should store that encrypted. Is it necessary to keep the downloaded version.xml from update server open so that noone can change while checking version and updating? Or am I worried too much about all that?
Does all this work out so far and is it secure enough to not creaty messy installations on a users pc after patch?
Do you intend to use the System Tray class from Java 1.6 to notify the user of the update? To me, it seems like something like this would involve implementing an OSGi updater (sorta like how Eclipse project does it in the IDE). Also, the JVisualVM.exe tool (that comes with JDK) is an excellent example of this sort of thing and maybe you could get ideas from that although I suspect its coded in C++.
I made a simple command-line based game in java, only two classes (using Eclipse). But I was wondering how I can make this into a usable application for anyone, without running it through eclipse (ie send it to someone who knows nothing about java but would still be able to play the game)? Thanks!
You want to create a runnable jar file.
Eclipse has an option for this in the "Export" menu. For more options, search for "executable jar file" here or on Google.
You want to make sure that you also include any jar files your code depends on as well (Eclipse can also do that for you).
Users will be able to start this by double-clicking on the file on most platforms. If you need better integration (such as a custom icon), you will need to bundle it up further into an OS-specific executable. But for starters, a simple runnable jar works fine.
send it to someone who knows nothing about java
You need to get them to at least install the Java runtime on their machine (if it is not already there).
Just to be clear, "command-line" and "knows nothing about java" are probably not going to work very well for you given that:
java is OS agnostic, therefore, if you send (presumably) a jar file to say...your grandma and she has a mac and you have a PC chances are her getting it to work is not going to be "out of the box easy" so to speak.
Left with this, I think you have a couple choices...first off, you do need to package your classes - a runnable jar will work fine. Aside from that, you will most likely have to build OS specific scripts (batch scripts for Windows, shell scripts for unix, etc.) and you will have to hand these out with your jar file. That being said, the intended user will still need to have java installed, and the batch scripts themselves are not likely to be trivial endeavors.
Your next option would be to use JNLP. However, I don't think JNLP has a command line mode, so you will likely have to simulate a console with something like a JTextArea.
As far as I see it, your last option it to use one of the many products (not sure if there are any free ones) that package java into native code. I think Exe4j is one such example - but, like I said, I am not sure if there are any free ones and I am not sure how hard they are to use.
Best of luck, and if you can't get your jar to work you should probably move that to its own question.
I have a jar. I want the jar to be able to make a copy of itself while running. I understand windows may have problems with this. How would I do this, or am I over thinking it?
Edit: To explain a bit more....
I'm writing a repackagable firmware deployment system... http://code.google.com/p/heimdall-one-click/ The idea is that a ROM developer from XDA can make his own, then pack it up in a cross-platform deployable one-click packaging nearly as easily as it is to deploy the firmware.
My program takes alot of the work out by automating the tasks... I'm trying to automate packaging of the one-click deployable packaging system.... give the developers a form to fill out which will change the header information, then they select their firmware files to be deployed. I'm trying to keep it all in one jar.
As josh says, it would be nice if you tell why do you want to do this in order to help.
Answering only what have you post, copying the jar is just copying another file. There is the issue that it might be blocked by the OS (Windows); another issue is how do you locate it in the machine and if the user running the process has the permissions needed.
Once those two issues are solved, it is just a copy operation, the OS could not care less that if the order to copy comes from the process run from the file or from another one.
EDIT to asnwer changes in the first post.
As I told before, in the end copying a file is a OS issue. If you want to copy the current jar in Windows, then the jar must not be locked by other process so it becomes an OS question rather than a Java one.
Possible workarounds:
The faster (but dirtiest) is to launch a .bat that does a sleep of a few seconds and then does the copy. Immediately after launching it, your close your java app. If you need to continue doing things in Java, after copying the file, the .bat launches the java app again (with the appropiate parameters).
A variant of the previous is slightly sleazier... launch your java app from a .bat, and the first thing that .bat does is copying your jar to the PC temp directory. Be sure to document it well so your users do not get scared!
JNI library to unlock a file. There are several programs that (Unlocker) that try to unlock files; do not know to which point it is effective or how will it affect the JVM.
I believe you can use:
File file = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
to get a reference to the path to the .JAR file.
Then you just make a copy of it:
http://download.oracle.com/javase/tutorial/essential/io/copy.html
Your operating system might not allow this, but I think it should.
I'm looking for a non-webstart/jnlp solution.
I'd like to add to my app an update feature that checks in an ftp or http server and downloads the last version (if there is a newer one) replacing the libs that has been changed.
How can i do that? I want to implement something like JDownloaders updates.
Thanks
It looks like you just described exactly how to do it. Add an update feature that checks an FTP or HTTP server and downloads the latest version.
Remember that you cannot download and overwrite a file which is in use. So you have two options for a design from where I sit:
When you start up the application, copy all of the jar and library files to a /temp folder of some sort before running them. Then, when you download the update, overwrite the files in the original place. The next time the application starts up, it will use the new files.
When you start up the application, first startup an updater. Have it connect to the server and compare all of the file versions. It will be able to overwrite any of the application files because it doesn't use them. It only uses the updater jar. Once this is done and everything has been updated, then start a new process from the updater with the actual application. You will also need to put some code in to be able to update the updater jar. Either make the main application be able to update the updater, or use the first technique and run the updater from a copy of the updater jar.
Remember when you download the files that you should be downloading them to a temporary location and then moving them to the right place when they're done. This will make sure that you never leave your application in a "half-downloaded" state.
Beyond that, getting this to work is going to be about a lot of testing. Good luck!
Have a look at http://code.google.com/p/getdown/
According to this question on stackoverflow it seem to be a viable alternative for web start (at least worth having a look at).
I am currently working on desktop software based on java.It's quite a big code base (more than 40 jar files).
I wish to provide an automatic update functionality. The desktop software constantly checks one back end system to see if there are new versions of the jar files available.
The problem now is: How to replace the updated jar files?
If you deploy your application using Java Webstart (JNLP), you get this mechanism almost for free...
From http://mindprod.com/jgloss/javawebstart.html
The key benefit for Java Web Start is automatic update without having to download the entire program every time.
Easiest would be to check for updates on each startup, download the updates and then launch your application. I think this is the way that Java Web Start works (see aioobes answer).
More complex would be to use either the netbeans or eclipse framework for your application. Both are rather complex and you will have to rewrite your application to work with them. This solution supports live updates.
As far as I am aware there is no easy way to update a running application. It is possible to load new versions of a class with a different classloader, but not possible to unload old versions while they are still referenced.
You can make a little server and a launcher which downloads the newest version, replaces the old one, and starts the jar with:
Runtime.getRuntime().exec("java yourjar -jar");
And you terminate the launcher with:
System.exit(1)
You can also serialize down your state (keep it in memory) and then create a new ClassLoader instance pointing to the new .jar files. Then serialize up your state again using this new classloader. You have just changed the underlaying .jars within a executing product.
Please note that you do not need to change the classloader for everything only for the part that is actually using the .jar files. This can be tricky to conclude what parts that are. And you might get nasty linking errors if done wrongly. So..
.. to keep it simple, use WebStart or a preloader that updates the .jars and then starts the main app (basically what WebStart does for you).
A reason for rolling your own, is that you can use your own format for the .jars, encryption, other packing formats etc.
After reading some answers to many auto-update questions, I thought of a solution. This is how I would implement a secure auto-update for a Java/Kotlin jar application.
Assumption: the installer will contain two jars: a launcher and the main application. Any shortcuts created will point to the launcher, but still be the name of the application. The release will contain the main application and the installer.
The launcher is launched first:
First check if an update has already been downloaded as app_name_update.jar
if an update has been downloaded, rename app_name_update.jar to app_name.jar
Start app_name.jar
This part does not have to be in the launcher, but it's preferred as to not slow down the main application: at this point, the launcher should check for an update (e.g. GitHub releases API) and download it to {CWD}/unverified_app_name_update.jar.
Compare the hash of unverified_app_name_update.jar to an online location containing hashes for all published versions. hashes.txt would be an example found in the same github repository. If the software is open-source, GPG signed commits is a must and the launcher should check if the latest update is a verified commit! If its a proprietary application, keep the hashes.txt at a separate URL from the release where your company does not control the infrastructure (e.g. GitHub).
Main app launched:
No need to check for updates unless updates are mandatory, in which case check for update -> if update found, start loading animation "updating" while you can detect that the launcher is still running. Ensure that the launcher has no race condition while loops!
I found ready project to solve automatically updating.
You can update your app, in your cases you can update jars and resources of your desktop app. The idea of the this is next: wrap you app with starter which can control updating and running you app. In details you can find here.