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.
Related
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.
Is there any way to detect whether a folder was created by an Android app, and not by the user?
No. There's no such information stored in file system (nor in android nor in Linux in general). And even if it would, from filesystem perspective user never creates anything. It is always the app (and it's not important if app does it by itself or directed by user). App just tells the OS "create that folder for me", w/o giving any more detailed information why it wants that to be done and who is the real culprit.
EDIT: I just realised there's a case which maybe was on OP's mind - SD card. Content there can be created "by user" (which means when it got card mounted and accessed i.e. from desktop) and not by android application. But finding that out could be tricky. Some below suggest FileObserver. I am not sure. I'd maybe try to monitor mount/unmount broadcasts, then perhaps scan the sd card to see if there's anything added after unmount. But it is rather ineffective too, as if it is real sd card and user put it in machine with wrong clock, then my scan won't find much there. Other attempt is to know what is there (so build a "map" of sdcard once you see it for the first time and then compare with subsequent mounts). Still, the question remains - why you need that for? Maybe there's simplier approach to your problem
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.
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.
i'm writing an application that needs to store some data,and picture. For example place's information. this information don't need to change very often. and
I have seen that databases are
stored under /data/data/package_name/databases
I decided to store my data under /data/data/package_name/files.
With the emulator i can see all these files (databases)
under the proposed directories but moving the application on a real
device and installing a file system browser i cannot see any file
under /data. i know that there are some security constrain in (not-rooted) device. However, are there any suggestion about the solution.. where can i store these data and how? because i'm quite new to android. Thanks so much for your help.
The reason you can't see it on the device is basically just as you said; the device isn't rooted, so other apps don't have access to the /data folder.
This is okay though, because you can still store your files there. Your app has access to anything under /data/data/package_name/, you just won't be able to see it in a file browser unless you root. This is normally a good thing, to keep average users from mucking around with your databases/files.
Read up more on storage methods here.