Ive been reading up on where to store my files, and I am still not sure what route I should take. I am writing an application that will store images and pdf's (totaling 300MB or so). I would like the app installed on the internal storage, and then allow the user to store the pdfs and some images on there choice of storage. Is it possible to allow the user to choose which storage they use for those files only even I have this in my manifest:
android:installLocation="internalOnly"
Essentially I would like to have the user choose this when the applications start.
If it is, would I just need to have a flag in application that if the user chose external and if the external storage was available, had enough space, then save files to it. Every time the user opened the app I would check to make sure the files are available. If the users chose internal it would use openFileOutput. Does this all seem right, is this possible?
Or should I just consider making it completely internal only, because without these PDF's and images the app is not usable.
It sounds like you can set the installLocation as following to accomplish exactly what you want:
android:installLocation="preferExternal"
From the documentation:
If you declare "preferExternal", you request that your application be
installed on the external storage, but the system does not guarantee
that your application will be installed on the external storage. If
the external storage is full, the system will install it on the
internal storage. The user can also move your application between the
two locations.
If you set it to internalOnly, the user cannot move the application from internal storage to external storage, so above solution is probably your best option.
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.
For my current project, I would like to allow a user to create a sqlite database file and have them enter some content. Then the user has the option to sign into their google drive account and upload this file. Afterwards, after the user makes further edits, the new database file is uploaded to replace the old file. Finally, if the user has multiple devices, the database should be downloaded from the google drive and replace the existing file stored on the device.
Currently, I have successfully setup Google Drive SDK authentication and I can sign in to the app with my account.
My main question is, how do I upload a sqlite database file to the APP FOLDER when I choose to press a sync button? (This method should be called when the user needs to sync)
Additionally, how do I upload a sqlite database file to the APP FOLDER?
Your question is a bit broad, but I'll try to send you in the right direction.
First you have to decide if to use the REST Api or GDAA. Both will accomplish the same (actually the GDAA's functionality is a bit narrower now, but for your situation will do).
The big difference is that GDAA will handle on-line / off-line states for you, where with the REST Api, you have to implement some kind of non-UI thread (sync service) synchronization. Also, there are latency issues you must be aware when using GDAA.
Next, the process of uploading SQLite database is the same as any other binary data stream.
Grab the 'xxx.db' file, make output stream (or byte[] buffer) and create a GooDrive file with title + mimetype metadata, push the stream into it's content and send it on it's merry way. The only difference between a standard folder and an app folder is the parent of the file.
You get an ID you can subsequently use to download the file to the device. Or you can use search by metadata (title in your case) to get this ID. Again it comes as input stream and you dump it to an 'xxx.db' file on your device.
The second portion of your question deals with multiple devices. None of the apis will notify you about a change in GooDrive, so you must implement one of the 2 strategies:
1/ Polling (ouch), preferably in sync service with sync intervals the system gives you.
2/ GCM message broadcasted to the devices / users who are interested (not trivial, but efficient ... and sexy).
Another pitfall you must be aware when using multiple devices with GDAA is described in SO 29030110 and SO 22874657.
In case you decide to play with the 2 apis, I maintain basic CRUD implementation demos for both the REST and GDAA. The GDAADemo has also an option to work with the app folder.
Good Luck
I have read the android official documentation regarding android storage.
I understand there are:
1) internal storage: which is app-private. deleted when the app is removed. cannot be accessed by user nor other apps.
2) external storage -
2.a) private: app-private. deleted when the app is removed. cannot be accessed by user nor other apps.
2.b) public: the user and other apps can access and even edit.
from the official documentation:
Saving files that are app-private
If you are handling files that are not intended for other apps to use
(such as graphic textures or sound effects used by only your app), you
should use a private storage directory on the external storage by
calling getExternalFilesDir(). This method also takes a type argument
to specify the type of subdirectory (such as DIRECTORY_MOVIES). If you
don't need a specific media directory, pass null to receive the root
directory of your app's private directory.
So what is the difference between (1) and (2.a) ?
So what is the difference between (1) and (2.a) ?
There is no 2.a that meets your description. There is app-specific external storage that is removed on an uninstall, though the user and other apps can certainly get at it. Hence, it is not app-private.
You may wish to read some recent blog posts that I wrote that cover internal storage and external storage.
external storage means a space for applications and files
private means space for system files
I need to get write permissions to the lib directory of my application (i.e. /data/data/com.my.app/lib/) and store a file there, and I need to do it from my application. Is it possible? and if so, how?
EDIT
By my application I mean using Java. /data/data/com.my.app/lib/ is the path to the lib directory of the same application.
EDIT
Unfortunately, as LeffelMania said, I couldn't find any convenient way to do it. Fortunately, we solved this problem in a better way - we convinced the developers of the library to make it more dynamic :). Thanks again LeffelMania.
It is not possible to directly write into another app's file space. Your app has write access to its own space and external storage (SD card) with permission.
However, I can imagine a couple ways to do this, depending on what you're trying to do, specifically.
1) Write the file to the SD card from one app. Have the other check if it's there and read from it when it opens. Make sure to write it to your own proprietary folder - don't clog the user's storage space. If applicable to your situation, delete the file and your folders on the SD card from the other app once you've read the file.
2) Register a custom BroadcastReceiver in the recipient app, and stick the data you need to transfer inside of an Intent that you will send from the other app. You should use your own action String so that no other application in the system attempts to use your Broadcast.
I want to lock files that is on the sdcard of android.
I need to lock them so no one except my software can delete copy move or send them over bluetooth or any other way.
How can I do it?
There is no way to lock a file in Android; even if there was, the files would only be locked when your application was running which wouldn't stop other apps accessing the file when the user hadn't started your app.
SD Cards are usually formatted with FAT (or FAT32) and this is the case with Android. FAT offers very limited file permissions so you can't restrict access to the files this way. Again, even if you could do something like this, this wouldn't offer any protection if the user took the SD Card out of their phone and put it their PC.
If you want to keep your application's files private you need to put them in the phone's internal storage in the area reserved for you application. Each application runs with a different User ID and each application's data directory is protected using UNIX-style file permissions which prevents other applications from reading them. So while this will stop other applications having access to your files it wouldn't stop a reasonably determined user with root access to their phone copying them off.
Have a look at the Context.openFileInput(), Content.openFileOutput() and Context.getFilesDir() methods for details on how to store files in the phone's internal storage.
You cannot do this on any platform (let alone Android) using a regular SD card. Sorry!
I think you want to encrypt the file. While the file can still be moved around, it will be useless to anything but your application. People will be able to copy, move, delete but the contents won't be compromised.