So I'm making this android application, that needs to read data from user-provided CSV files.
The CSV files are more confortably edited on a desktop computer, so I have no editor in the app, which is 'read-only' ; I assume there is a file on the phone's SD card.
Following the Data Storage documentation, I managed to write a dumb version that reads the file from external storage, hard coding the folder location relative to whetever getExternalStorageDirectory returns. So for the moment I have :
private static final String CSV_FILE = "/Android/foo/bar.csv"
...
File f = new File(Environment.getExternalStorageDirectory(), CSV_FILE);
Then I would connect my phone to a PC, create a "foo" folder in the "/Android" folder (that exists on my phone), copy the "bar.csv" file, and everythings goes fine.
Now obviously, this is not acceptable if I want to distribute the application. So I have a few questions :
The natural solution is to softcode the file location, and in any other system I would rely on a built-in "file manager" or something, to let the user browse to the right file.
Surprisingly I could not find such a control, and it seems like there are lots of third-party File Browser app. Does it mean it is not "customary" to ask a user to choose a file on their phone ? Should I write my own 'file browser' ?
Are there conventions about how I should name my "foo" dir ? I've seen apps creating dir with a name that looks like a java package, am I mistaking it with internal storage ?
There is also a getExternalStoragePublicDirectory method that takes a "directory type' constants. In my situation, would it make 'sense' to assume the file is in DIRECTORY_DOWNLOADS ? (or in some subfolder of DIRECTORY_DOWNLOADS ?)
Should I bother about how a lambda user will put a file on their phone ? To me plugging the phone on my PC is simple enough, but is that really easy on all droids ?
Sorry if all of that sounds trivial, just trying to clear my mind before doing something stupid.
Thanks.
Does it mean it is not "customary" to ask a user to choose a file on their phone ?
Correct. Android, like iOS, tries to get away from "files" as much as possible.
Should I write my own 'file browser' ?
There are certainly plenty of third-party applications for file browsing, some of which support ACTION_PICK or similar operations (e.g., OI File Manager). I will be surprised if nobody has written a reusable component for this.
Are there conventions about how I should name my "foo" dir ? I've seen apps creating dir with a name that looks like a java package, am I mistaking it with internal storage ?
No, you are probably seeing the results of getExternalFilesDir(). If you are only supporting API Level 8 or higher, I'd just use that. If you are supporting earlier versions of Android, you might consider finding out the appropriate directory for your app that would be used via getExternalFilesDir() and use that "manually" for older Android versions.
There is also a getExternalStoragePublicDirectory method that takes a "directory type' constants. In my situation, would it make 'sense' to assume the file is in DIRECTORY_DOWNLOADS ? (or in some subfolder of DIRECTORY_DOWNLOADS ?)
That is for downloads -- more accurately, things the user downloaded that they want to hang onto independent of any installed app. It does not sound like this fits your scenario.
Should I bother about how a lambda user will put a file on their phone ?
What is a "lambda user"? To quote the Bard, "but, for mine own part, it was Greek to me" :-)
To me plugging the phone on my PC is simple enough, but is that really easy on all droids ?
It is somewhat more painful on Android 3.x and higher, as Android moves away from USB Mass Storage mode (think USB thumb drives) and to MTP (think MP3 player) for its USB file transfer protocol. While this has overall benefits, it is annoying for OS X and Linux users, as neither have built-in MTP support. Also, it assumes the user has a USB cable handy. Your overall setup also assumes the user has a desktop OS handy.
Nowadays, more developers would probably go the route of creating a Web app rather than a desktop app, and syncing the data to the device over the Internet. This eliminates the need for fussing with cables and does not tie the user to one specific "desktop" machine for data entry. It does, however, require Internet access, which may or may not be suitable for your situation.
Related
I'm looking for a way to make my VR Android app (for Samsung Galaxy S7 and S9) able to write files to the SD card (e.g. by downloading a .zip file and unzipping it there).
The app is mostly going to be used by people, who don't know a lot about Android/smartphones and don't want to have to deal with anything complicated (not necessarily seniors but close enough), that's why I want to make it as easy as possible for them, which also includes making choices myself (and setting it up for them) instead of showing complicated dialogs.
Special requirements:
The files must not be deleted when the app is uninstalled - that's why I can's use getExternalFilesDirs() (Storage Volume).
The folder everything happens in has to be easily accessable, so the zip files can be transfered to the SD card on your PC too (instead of downloading them through the app in case they are too big) without having to go down a huge amount of levels and remembering a long folder path.
Using Storage Access Framework isn't a good alternative either because not only is picking folders nothing that's especially VR friendly but it also requires knowledge about folders most of the users simply won't have and/or won't want to deal with every time they open my app. But: If there was a way to only show this once (on the very first start after installing the app) and maybe even set the root folder to the folder I chose, so the users only have to hit "accept", that would be worth a try (unless there's an easier way).
Yes, I did set the android.permission.WRITE_EXTERNAL_STORAGE permission and also enabled the "force allow apps on external storage" developer setting but trying to write to the SD card still throws an "Access Denied" exception.
Are there any others ways to write to the SD card that are VR friendly?
So, I want to read a very specific file from any connected USB OTG drive. It's a text file that should be stored on a USB stick and I need to read that file, which has a specific name, say myFile.txt. While I understand this kind of getting user input is dumb and not user-friendly, it's what I'm told to implement.
But my problem is, that there are many mount points for USB Drives. on my phone it's /storage/USBStorage1, while on my friend's it's /storage/[HEX_ID]. I tried to get all of them, but it's not possible. in Nexus phones it mounts on /mnt/media_rw/[HEX_ID] which requires root access.
I searched around a little and found SAF, but I didn't find anything on how to use it to open any file without user's direct selection. I don't want the picker to show up. I just want to check if [USB_OTG_PATH]/myFile.txt exists or not, and if it exists I want to read it.
And on a sidenote, do I need to have root acces to read /mnt folders (except media_rw)?
I didn't find anything on how to use it to open any file without user's direct selection
That is because there is no option for this.
I just want to check if [USB_OTG_PATH]/myFile.txt exists or not, and if it exists I want to read it.
That is not supported.
If your file is located in one of the directories returned by getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs(), then you can access it directly using normal Java file I/O. However, AFAIK, that directory needs to be created as part of running your app — another developer ran into problems trying to create the directories ahead of time. So, for your use case, this approach is unlikely to be practical, though with luck I am wrong and it proves useful to you.
do I need to have root acces to read /mnt folders (except media_rw)?
In general, yes, though in practice the answer varies by device, Android OS version, etc.
I am working on a project that needs to store some .txt to android, and get it from the computer for other use. From what I read from the documentation, I know that there are two types of storage: 1 Internal, which is somewhere deep in the phone that is private to the app. 2 External, which includes the SD card and the Internal Storage of the phone. I want to store it to External->Internal, and I am using this line of code to do that:
public String WalkDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/Walks/";
When I logged WalkDir, LogCat says "/storage/emulated/0", I stopped the app, checked with the adb shell, and there is no folder "0" but "legacy". I unplugged the phone and plugged it back in, the "Walks" folder is now in the root directory, and I don't need adb shell to access it.
So my question is, can you help explain how this system works? Why did "0" disappear? What is "legacy"? Why is the file in Internal Storage when I unplug&plug it?
Thank you very much!
Those are what in Linux are called symlinks (like shortcuts in Windows) that various system apps in Android are using..
/storage, /sdcard are sym linked folders,that means when you open one of those, it redirects to the original(/data/media/0), as for the 0 is just a multi user feature implemented in android 4.2, but only enabled on tablet androids.
Why do this Sym-Link?: simple so it dosent break apps(not only file explorer type of app, but all apps).
Still dont get, why it would break?.Simple. android api have lots of ways to write/read files from folders, u can do manually,u can get the data path, u can get the sdcard path, etc,etc. so to not break that they just does these sym links, thats why in one app the storage contentents are listed on /sdcard but on others, is /storage, etc,etc. one example of an app that broke because of these changes to android is titanium backup, u need to change the internal storage on it, so it work.
2 mount points pointing to the same storage device and partition.
If you create something in one folder, it will show up in the other. Same applies for deleting stuff.
They do not take away more storage space, as it is only available once but shown twice.
You also don't need to worry about it in any way because file browsers normally set their default directory to one of these locations.
As far as i know, Google changed the mount points in Android 4.2 to /storage/emulated/0/ due to them switching to MTP and EXT4(?) for the sdcard. The other mount points are still there for compatibility.
I am messing around with node.js on Android through this project, and I need a way to deploy js files to a private directory (to hide the source code, and prevent users from tampering) which also physically exists on the filesystem (an apparent requirement for node.js).
Is it correct to place my javascript files in /data/data/com.skabbes.android/node_modules? And if not, what would be the correct way to accomplish my goal?
Well, if you are wanting to store something on the internal storage, it is not recommended to use an absolute path like /data/data/..../ because while that may be the correct path, it can potentially change with different devices or different Android versions because /data/data/ the internal file structure is not specified in official Android documentation.
I also want to point out that even if you are storing information in the /data/ directory it is still possible that someone could access it if they have a rooted phone.
But, what you should do is see This. That will save information on the internal storage of the device and neither the user nor other apps can access the files you save with that method unless the device is rooted.
You should use the getFilesDir() method of Context which basically abstracts the absolute path.
It will most probably be something like /data/data/<package-name>/files but it's a better way to make sure your app is compatible with all versions of Android and all devices.
I have an application which writes and reads from a specific file on the SD card.
What i would like is a way to encrypt the whole SD card or a minimum of That specific folder. So if the phone is stolen no one can read the content of that folder.
However, i also want the application to still be able to interact with the folder and the password isn't required until someone looks at the folder specifically (using astro etc) or inserts it into a PC to view.
Is this possible? thanks
You'll need to do this manually, look into javax.crypto for getting the crypto bit done relatively painlessly.
This won't be possible with an ordinary (unmodified) android system (I assume).
If you are talking about your own app - you could implement your own file level encryption in your application.
For everything else, I'd say you need to modify android to include some kind of encrypted file system and the relevant UI for it.