fellow developers.
Let's imagine the following scenario: A group of friends is playing Minecraft on a server. That server has a resource pack associated (file server.properties, field resource-pack). That resource pack is a ZIP file hosted by Dropbox, and the respective Dropbox share link is what goes on field resource-pack.
All good, for now. Resource pack loads flawlessly.
However, those friends need to update the resource pack with their custom textures every now and then. I'd like to automate that process in the best way possible. To provide a custom texture, one needs 2 files: a .png file and a .properties file. Those are fairly easy to make. Then, those files need to be put in the following directory (Dropbox):
/ResourcePack.zip/assets/minecraft/optifine/cit/
The problem here is that the Dropbox API can't upload to existing ZIP files, and the resource pack has to be a ZIP file, int order for Minecraft to recognize it. Also, I don't want to download the ZIP file, extract, put the files inside, compress and upload again, because it's quite a large file and that would take some time.
My Java application looks like this:
What the application does now, is accept dragged files and send them to the Dropbox path:
/ResourcePack/assets/minecraft/optifine/cit/
But not:
/ResourcePack.zip/assets/minecraft/optifine/cit/
I was told the Dropbox API can't handle uploads to ZIP files, and I also can't find anything on the documentation here.
Can anyone think of a solution, other than downloading the full resource pack, and uploading it back everytime someone wants to add custom textures?
Thank you.
EDIT:
So, as Adriaan suggested, I can simply use a direct link to the unzipped directory structure of the resource pack.
The problem is now another:
When a player joins the server, and downloads the resource pack for the first time ever, everything is fine. However, it gets cached in his local machine, in the following path:
/.minecraft/server-resource-packs/
So, when the resource pack is updated with new custom textures, minecraft will just load the cached resource pack and ignore any updates present in Dropbox. This results in the player not seeing the new custom textures.
I've learned about the resource-pack-sha1 field in server.properties. It looks just like what I need, but I can't quite understand how to use it.
Thanks in advance.
You can store the unzipped directory structure. DropBox allows downloading a directory as a zip file.
You can force dropbox to do a direct download by changing the dl=0 at the end of the URL to dl=1 see this help page
If the remark on the page you linked is still true "This is not yet used to verify the integrity of the resource pack, but improves the effectiveness and reliability of caching." then you could just enter a random new value into resource-pack-sha1 to trigger all clients to download the new pack.
If you need the actual digest then you could follow this mini tutorial
to generate an SHA1 for your server.properties:
visit this website: http://onlinemd5.com/
Upload your resourcepack
copy the SHA1 and paste it into your server.properties for the resource-pack-sha1 option
all done!
If you don't want to upload your resource pack to someone else's server you could download a tool to determine the digest locally.
Note: DropBox offers a content hash via their API, but it's not an SHA1 over the complete file. Rather they split the file in 4 MB blocks and determine the SHA256 for each, concatenate them and SHA256 the result again. If there's a way to change the hashing algorithm used by Minecraft this could be used.
EDIT: Is it an option to rename the resource pack directory on DropBox when you change its contents? This will circumvent the caching and hashing issue. Clients will just need to change the resource pack URL accordingly.
Related
Here the problem: my app will generate some files, and I want to give to the users the opportunity to exchange these files between them.
This requires 3 steps:
Saving the data: easily done in Storage implementing the
functions required by the Externalizable class;
Sharing the data: done (probably, right now it's impossible to check if the
result is correct because the missing step 3) with the sharing
methods offered by the framework, as soon as I understood I needed
to use as mimetype "application/octect-stream";
importing the downloaded data (shared by another user): this one I can't manage to
find a way to make it work. Loading the files from the app's Storage
is easy, but accessing to the folders out of the app's Storage is
something I can't manage to do.
I used FileSystemStorage in the hope of gaining access at least to the Download folder that (mostly) every phone has, but apparently I can't manage to accomplish the task
Using the FileSystemStorage on Android, for example, I have access to
/storage/emulated/0
/storage/emulated/legacy
file:///system
The first two being related to the Storage of the app.
Acceding to file:/// I obtain a long list of folders, a partial list including
media
logs
sdcard
Removable
...
root
...
But when I try to access some of these, they all appear to be empty. Either I make some mistake or the app can't see their content.
So I wonder if there is a way to accomplish the task, namely to have access to the files (probably in the Download folder) the user has downloaded, to import them.
Phone apps live in isolation within the phone. Android literally creates a separate Linux user for every app so they don't step on each other and damage the phone. iOS does similar tricks.
As a result apps can't just write a file to downloads and can't just list all the files there. This would violate the users privacy. So the native API to share a file is usually separate from the files API. We do have a share API in the CN class which lets you share images etc. to an arbitrary OS app. See isNativeShareSupported and share.
Ok, maybe I found a solution for reading the files from the Download folder in an extension of CodenameOne called FileChooser.
According to this blog post it should give access to, between the others, the Download folder (at least in Android).
I'm going to try it and, when everything is ready and tested, edit this reply to say how it worked out for me.
I am trying to make an app that uses a bunch text files as a base for most of its actions and this text files can be updated from a web server.
Currently my app is able to download a batch of text files via a zipped archive, but I was wondering if there was a way to check if I already had the contents of the zip file before downloading them.
What I had now was that I would download and unzip followed by a line by line check to see if the current files where different from the recently downloaded files.
This is seemingly very inefficient but I do not know of any other way.
If anybody has any suggestions and can either give a small example or point me to one I would greatly appreciate it.
To assemble what BackSlash and the others already said in the comments:
One possible solution could be to:
Create a hash of the file when the file is being created (good) or
after download (bad)
Store this hash somewhere (e.g. inside the filename instructions-d41d8cd98f00b204e9800998ecf8427e.zip)
Client: Query the server with the string
Server: Check the transmitted hash against the hash of the newest version
Server: Respond accordingly (e.g
by using the HTTP built-in 304 response)
Client: Act upon the response of the server
I need to load "configuration" type files for my program in Android, they are both .bin files containing dictionary data for the NLP library. I'm a bit new to Android still, and I'm having trouble finding a folder to place the files in so I can access them when the activity starts.
I also need to create/save/load a filetype specific to my program, and I don't know where to put it either. All I've been able to find on here is people using the getAssetManager() function to fetch input streams, but I explicitly need File objects for me to be able to load them into my pre-existing desktop software code I'd like to reuse (plus the libraries require them anyway)
I've also seen people using a "res/raw" folder, however the ADT did not generate this "raw" file when I made the project - so I'm not sure what to do there either.
Here is how I usually start the software in the desktop version, but I need to fetch these files in an Android environment:
brain.start(new File("memboric.core"), new File("en_pos_maxent.bin"), new File("en_sent.bin"));
core = brain.getInterpreter().getCore();
The memboric.core file can be generated, but I need to know WHERE and HOW to do so.
Thank you very much for your time, feel free to direct me to other resources if you feel this question is inadequate.
TLDR; how do I load "static" files for the software to function (needs to be included with software), and how to create/load/save "personal" files into an appropriate area of the device?
Use Context.getFilesDir(). Your application can read and write files in that folder and they'll automatically get deleted if your application gets uninstalled.
From that point forward, you can create, delete and read from files like any other Java application.
the "raw"-folder you can create it on your own. So check this out, which shows how to handle files in Android: http://developer.android.com/training/basics/data-storage/files.html
I wanted to know where should I keep my resources like I am displaying some images, playing some media files while making executable jar? Should I include it in executable jar or I should keep outside the executable jar?
If I keep the resources outside the jar what URL location URL should I pass in my program to access the images?
Actually the problem is I want to make distributable copy of my jar file.
If I give location of my local system for accessing the images and media files it will work in my system but what when I distribute it in other systems?
It depends on your application.
You can pack resources into the jar. Typically it is good for resources that are never changed: company logo, icons etc. You can read them using getClass().getResourceAsStream().
Other solution is to download the files from server (e.g. over HTTP). This solution is good for media that you do not want to pack together with application. For example video clip you want to play to user. Or, probably localized icons from the previous example or localized messages for multi-lingual applications.
The resources that you are downloading can be cached. You can use User's temporary directory (System.getProperty("java.io.tmpdir")) or sometimes using preferences API.
This isn't a radical answer but you could, in essence, create a resources project for images, properties and the like (media even).
You can then add your resources project (henceforth referred to as "MyProjectWsResources") as a child to your code project (henceforth referred to as "MyProjectWsClient"). Since MyProjectWsResources is in MyProjectWsClient's build path, it makes referencing your resources easier. If you're unclear of what putting something in your project's build path entails, it's saying anything in MyProjectWsResources's src folder is in MyProjectWsClient when it goes to referencing for information (as long as you're not using absolute paths :))
Why go for the approach of multiple projects? IMO, it separates code from resources so you download resources and code separately and your clients need not download the resources projects repeatedly when there are updates to your code only (I feel updates to code are far more frequent as compared to updates to resources). Lesser server bandwidth (important if you're using Java WS or any other packaging/system which I now realize you probably aren't).. still, hope this helps :)
I want to make distributable copy of my jar file.
Fist I will address the only sentence in your question that was not a question.
A great way to distribute a Swing desktop application to multiple users from the click of a link on the net, is Java Web Start.
Deployment with JWS would mean the resources would need to be in a Jar. For best results with the 'auto updating' nature of JWS, the Jar(s) for media would be:
referenced from a separate, sand-boxed, extension so they can be shared with other applications, and loaded/updated separately and lazily (as needed).
Compression:
uncompressed, for video, sound and image
compressed for textual information (HTML, RTF, CSV..)
Put in a path in the Jar that is known to the application. (e.g. /resources/video/vidNNN.mp4)
Resources in Jars are an embedded-resource and must be accessed by URL (or InputStream as mentioned by Alex, but URL is more robust). Quoting the info. page.
URL urlToResource = this.getClass().getResource("/path/to/the.resource");
During development, it is generally best to arrange a build that assembles the resources in the same way the end user will get them - to build the app. each run.
In other cases you might want to leave the resources at a public location on the server and access them as needed, but this effectively makes the server necessary for running the media related parts of the app. It seems your resources are both static (user does not change them) and an 'application resource'.
We have to make a Java application demo available on Internet using JWS. It goes pretty well; all that's missing is making working directory files available for the application.
We know about the getResource() way... The problem is that we have different plugins for the same application and each one require different files (and often different versions of the same files) in their working directory to work properly. So we just change the working directory when we want the application to have a different behavior.
Currently, the demo is packaged in a signed jar file and it loads correctly until it requires a file from the working directory. Obviously, the Internet users of this demo don't have the files ready. We need a way to make these files available to the WebStart application (read/write access) in its working directory.
We've thought of some things, like having the application download the files itself when it starts, or package them in the jar and extract them on startup.
Looking for advices and/or new ideas. I'll continue working on this... I'll update if I ever find something reliable.
Thank you very much!
I said I would share what I found in my research for something that would fit my needs. Here's what I have so far.
I have found that the concept of current working directory (CWD) does not really make sense in the context of a Java Web Start (JWS) application. This had for effect that I stopped trying to find the CWD of a JWS and started looking for other options.
I have found that (no, I didn't know that) you can refer (using getResource()) to a file in the root directory of a JAR file by simply adding a '/' in front of its name. ("/log4j.properties", for example.) The impact of this is that I can now take any file which is only referred to in a read-only manner in the root of that JAR file (which is really only a ZIP file). You can refer to any file in the root of the JAR file using AnyClass.class.getResourceAsStream. That rules out the problem with read-only files required to run the application, at the cost of a switch in the code telling whether the application is run from a valid CWD or from a JWS context. (You can very simply set a property in the JNLP file of the JWS application and check if that property is set or not to know where to look for the file.)
For write-only files (log files in my case), I used the property , adding a directory with the name of the application: <user.home>/.appname and added log files to it.
Read/write files (which I don't have in my case) would probably simply go at the same place than write-only files. The software could deal with uploading them somewhere if needed, once modified, I guess.
That's the way I deal with the problem for now.
Note there is a service you can explicitly ask for, to get file access to the computer (unless you go all the way and ask for full access (which requires signed jar files)).
Then you need to determine where these files need to go - basically you have no idea what is where and whether you may actually write anywhere. You can create tmp-files but those go away.
Would a file system abstraction talking to the JNLP-server do so you store the users data on the server?