Where should my Java desktop app cache its downloaded assets? - java

I have a Java desktop application that downloads tens to hundreds of MB of image and music data as part of its normal operation. It maintains a disk cache of this data. If part or all of the cache is removed, the app will notice and re-download the missing data.
This is a 20-year-old app and historically it has placed the data in a hidden (~/.myapp) directory under user.home. I'm planning an update, and I'm wondering if there are canonical locations for storing application cache data for Windows, MacOS and Linux, and if so, if there are standard ways of accessing those paths from Java.
The only precedents I'm aware of are Gradle and IntelliJ, both desktop Java apps. Gradle does what my app does currently; it creates a ~/.gradle directory and dumps data there. IntelliJ apparently tries to use more canonical paths as of the 2020 edition; e.g., on Macs it saves cache data to ~/Library/Application Support/JetBrains/<product><version>.
Is there a library that will provide me with the canonical location my app cache on each OS? If not, does someone have a list somewhere so I can create the directories in the right places manually?

Related

How to save application data for use across users in OS X

I have a Mac Java application that needs to persist data across reboots. The data needs to be saved so that any user has access to it. E.g. an SQLite database file that can be used for all users.
It looks like the /Library/Application Support/ folder is supposed to be used for this, but I'm not able to write to it without making my app run as root or changing the permissions of the file to rwxrwxrwx.
What is the proper way to save application-level data on Mac?
The developer documentation covering this is a bit of a large topic:
https://developer.apple.com/library/Mac/referencelibrary/GettingStarted/GS_DataManagement_MacOSX/_index.html#//apple_ref/doc/uid/TP40009046
https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010672
According to the File System Programming guide you should make a specific subdirectory inside /Library/Application\ Support for your app to store app data common to all users on the system. I'd use reverse domain name notation such as com.yourcompany.yourapp or something else unlikely to collide with another app's use of the common directory for this.
You might also look into using an existing app bundler for OS X such as https://bitbucket.org/infinitekind/appbundler rather than hard code paths to file locations.

Android clears my application's folder files

I'm working on an application that downloads many files to the SD card.For a device that doesn't have SD Card. It uses the internal storage.
Whenever the storage goes lower than 500Mb, the operating system clears the folder i'm using to store files these files. Did anybody have a problem like this?.
I think that this problem is related to memory swap for the internal storage(When it gets lower than 500MB, it clears the application folder).
Your help is appreciated.
The documentation can help you out here
If you'd like to cache some data, rather than store it persistently,
you should use getCacheDir() to open a File that represents the
internal directory where your application should save temporary cache
files.
When the device is low on internal storage space, Android may delete
these cache files to recover space. However, you should not rely on
the system to clean up these files for you. You should always maintain
the cache files yourself and stay within a reasonable limit of space
consumed, such as 1MB. When the user uninstalls your application,
these files are removed.
The documentation does not say what hard limit is considered while trying to recover space. Whether there is enough space on the internal storage is also not under your control. Repopulate the cache if you find that it is missing and try to maintain a low overhead on the cached files.
As an example I wrote an app a while back that downloads image and sound snippets and caches them. If they are available in the cache I return them. If not I attempt to download them again and put a placeholder image where the actual data is supposed to reside.
Another solution is to store your data in a directory that is not considered a cache by the android OS. However you run the risk of overpopulating the user's disk with data and your data will not be removed when the application has been uninstalled.
In which directory you are saving your downloaded files?
Please take a look at:
http://developer.android.com/reference/android/os/Environment.html
and
http://developer.android.com/training/basics/data-storage/files.html
Also keep in mind the definition of "ExternalStorage":
"Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. It is a filesystem that can hold a relatively large amount of data and that is shared across all applications (does not enforce permissions). Traditionally this is an SD card, but it may also be implemented as built-in storage in a device that is distinct from the protected internal storage and can be mounted as a filesystem on a computer."

Expansion Files - Copying and Using

I have been looking at a few different tutorials, however am really struggling to see exactly how the Expansion Files can be firstly copied to a location that the user cannot access adn the how to use them in my actual app.
I will have a lot of key images within the Expansion file and therefore would also need to prevent users from playing the game until everything is downloaded.
Finally, I would have to also access a density based section for a lot of the images, along with a handful of raw files such as videos, this is what I currently have to work out which folder to open within the extension files.
String ExpansionFolder = "";
switch (getResources().getDisplayMetrics().densityDpi)
{
case DisplayMetrics.DENSITY_MEDIUM:
ExpansionFolder = "mdpi";
break;
case DisplayMetrics.DENSITY_HIGH:
ExpansionFolder = "hdpi";
break;
default: // This cover XHDPI, XXHDPI, TVDPI
ExpansionFolder = "xhdpi";
break;
}
Some sample code that i can use would be much appreciated.
I don't have sample code, because i haven't used expansion files myself, but specific answers to your questions do seem to be available at Android Developer APK Expansion Files page.
how the Expansion Files can be firstly copied to a location that the user cannot access adn the how to use them in my actual app.
from the "Storag Location" section of the Android developer page on expansion files (APK Expansion Files):
When Google Play downloads your expansion files to a device, it saves them to the system's shared storage location. To ensure proper behavior, you must not delete, move, or rename the expansion files. In the event that your application must perform the download from Google Play itself, you must save the files to the exact same location.
The specific location for your expansion files is:
[shared-storage]/Android/obb//
[shared-storage] is the path to the shared storage space, available from getExternalStorageDirectory().
[package-name] is your application's Java-style package name, available from getPackageName().
For each application, there are never more than two expansion files in this directory. One is the main expansion file and the other is the patch expansion file (if necessary). Previous versions are overwritten when you update your application with new expansion files.
If you must unpack the contents of your expansion files, do not delete the .obb expansion files afterwards and do not save the unpacked data in the same directory. You should save your unpacked files in the directory specified by getExternalFilesDir(). However, if possible, it's best if you use an expansion file format that allows you to read directly from the file instead of requiring you to unpack the data. For example, we've provided a library project called the APK Expansion Zip Library that reads your data directly from the ZIP file.
Note: Unlike APK files, any files saved on the shared storage can be read by the user and other applications.
From http://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String):
getExternalFilesDir
Returns the absolute path to the directory on the primary external filesystem (that is somewhere on Environment.getExternalStorageDirectory()) where the application can place persistent files it owns. These files are internal to the applications, and not typically visible to the user as media.
I will have a lot of key images within the Expansion file and therefore would also need to prevent users from playing the game until everything is downloaded.
From the "Downloading the Expansion Files" section of APK Expansion Files:
In most cases, Google Play downloads and saves your expansion files to the device at the same time it installs or updates the APK. This way, the expansion files are available when your application launches for the first time. However, in some cases your app must download the expansion files itself by requesting them from a URL provided to you in a response from Google Play's Application Licensing service.
The basic logic you need to download your expansion files is the following:
When your application starts, look for the expansion files on the shared storage location (in the Android/obb/[package-name]/ directory).
If the expansion files are there, you're all set and your application can continue.
If the expansion files are not there:
a. Perform a request using Google Play's Application Licensing to get your app's expansion file names, sizes, and URLs.
b. Use the URLs provided by Google Play to download the expansion files and save the expansion files. You must save the files to the shared storage location (Android/obb/[package-name]/) and use the exact file name provided by Google Play's response.
Note: The URL that Google Play provides for your expansion files is unique for every download and each one expires shortly after it is given to your application.
In addition to the LVL, you need a set of code that downloads the expansion files over an HTTP connection and saves them to the proper location on the device's shared storage. As you build this procedure into your application, there are several issues you should take into consideration:
The device might not have enough space for the expansion files, so you should check before beginning the download and warn the user if there's not enough space.
File downloads should occur in a background service in order to avoid blocking the user interaction and allow the user to leave your app while the download completes.
A variety of errors might occur during the request and download that you must gracefully handle.
Network connectivity can change during the download, so you should handle such changes and if interrupted, resume the download when possible.
While the download occurs in the background, you should provide a notification that indicates the download progress, notifies the user when it's done, and takes the user back to your application when selected.
To simplify this work for you, we've built the Downloader Library, which requests the expansion file URLs through the licensing service, downloads the expansion files, performs all of the tasks listed above, and even allows your activity to pause and resume the download. By adding the Downloader Library and a few code hooks to your application, almost all the work to download the expansion files is already coded for you. As such, in order to provide the best user experience with minimal effort on your behalf, we recommend you use the Downloader Library to download your expansion files. The information in the following sections explain how to integrate the library into your application.
You may also find Steps to create APK expansion file useful, if you haven't already seen it, though I don't know if Google has changed anything regarding expansion files since that question and its answers were posted.

application size issue

I'm building a dictionary application and I have a problem right now. My application's is 16MB and when I install it on a phone, Database files copies to the data folder and in the manage apps section I see that my application size is 32MB (my app+data folder).
I don't cheat user, I want to say, my app is 16MB, but when user install it , it become 32MB. Why? this is a negative point and I want to solve it. I want my app uses only 16MB in users phone. just that
How I can fix this? I have to read and write in assets folder directly or there is other solution? this is a problem in low storage size phones. how I can fix this?
I am not sure how your database is structured in terms of whether it is a pre-loaded database wherein you just include you .db file with all the data OR is it something where in you push all your DB content with the app and then at the time of app installation you actually install all you data in the DB.
In case of the latter situation you double the size of your app because you already have data content (in files) which you want to use to populate your database (say 16 mb in this case). Then you use these files to actually create your DB file (which is 16mb again) and this doubles the size of the app.
So what you could do is pre-populate your DB content in a .db file and then just use this file directly as the Db file in your app (this will keep it to 16mb). Follow this tutorial :
http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
Hope this helps.
Not sure I fully understand your situation.
Do you have a roughly 16MB dictionary, that is packaged inside your app as string constants in your code or some resource file or something (to make it 16MB) and then, when your app installs or first launches, you also write this dictionary into your app's database?
If so, then now you have 2 copies of your dictionary around to make it 32MB.
To solve this, either keep only one copy in your app, or download the dictionary from somewhere to get it into your database rather than storing it as a constant in your app.

Why is the jar file size increasing when I run the application?

I'm developing a mobile application using j2me. In my mobile app I connect with another device through bluetooth and perform some operations.
In my mobile application the jar file size is 80KB
I deploy the application in "Nokia c2-00" mobile. When I execute the application the memory of the jar file increases every time. Each time I execute the application the jar file size increases by 5 to 10 KB.
For example I deploy the application in nokia phone (At that time the jar size is 80KB on the mobile) and after running and exiting the application I check the size (it will become 85 KB, after that it increases to 90KB, etc) the size is increased.
I cannot understand why my app size is increased. Please help me figure out why the jar file is increasing in size and how to stop it from doing that.
What kind of thing is your app doing? I have seen this phenomenon when deploying MIDlets to Nokia S40 handsets before, and I attributed it to the app writing data to RMS. So the display is showing space consumed by the JAR, and by the MIDlet itself.
Does this sound like what could be happening?
Move a copy of the inflated / expanded JAR file back to your development platform, extract it and compare it with the original JAR contents to see what is being changed.
Something in your app or some library that your app is using may be adding some file containing some state to the JAR. That's a bad thing to do. The format of a ZIP/JAR file doesn't allow component files to be rewritten in-place. Instead, the new version of the component file has to be appended ... resulting in the JAR file growing.
This is a weird case. The jar should not grow once it is installed... For the jar to grow, its contents must be unpacked and re-packed together with the additional files into a new jar file. This scenario is unlikely to happen.
Anyway, can you share your jar and jad file? I'm thinking of testing this myself.

Categories