I am trying to create an HTML5 Application that is able to access a large amount of files. Therefore I looked at the FileSystem API to be able to read files from local filesystem.
I did a PoC using phonegap File API, and all worked as expected, I was able to produce similar results using the FileSystem API on Chrome Desktop...
However I am faced with a serious issue, while I can access my filesystem in Desktop, I can't access sdcard from Android Chrome. I tried to use this demo:
http://html5-demos.appspot.com/static/filesystem/filer.js/demos/index.html
I can select files from my local system in desktop: My Pictures, etc... But I can't do the same with Android Chrome
How can i access the device filesystem /sdcard in Android Chrome?
From this article on HTML5 Rocks:
It's important to remember that this file system is sandboxed, meaning one web app cannot access another app's files. This also means you cannot read/write files to an arbitrary folder on the user's hard drive (for example My Pictures, My Documents, etc.).
The FileSystem API was designed to allow your app to create and manipulate files which will persist between usages of your application. It cannot be used to expose arbitrary files from outside of it's sandbox.
Alternatively, the File API can be used to read, though not modify, files from the entire system. However, File API cannot be used to read arbitrary files on the system. It's usage is based on HTMLs <input type=file> tag, where the user must explicitly input the File to be read.
The above applies to an app running in Android Chrome the same as it does to Desktop Chrome, so you're out of luck unless the user is willing to use the input to grant access to the files you desire. However, you mentioned you also attempted a PoC using PhoneGap. The PhoneGap File API, though mostly acting as a wrapper around the HTML5 implementation, has some subtle differences, mainly in that it does allow for access to arbitrary files on the SD card. When using the API call window.requestFileSystem(), your success callback will have one argument, a FileSystem object, where the root property is a reference to the /sdcard folder. This can be used to traverse your sdcard and create FileReaders and FileWriters anywhere within.
Related
I am confused with the new app storage system in Android. I am not sure where my use case falls under and I need your help in telling me the right approach for this
My app captures images and generates pdf documents. Prior to Android 10, I used to store them in an app directory where the user can easily navigate to them through other files browsing app (like Files app on Samsung). In addition, these files can be accessed from within my app (so essentially read and write).
With the new storage, I am not sure how to accomplish the same thing. If I use the internal storage then user can't see them. If I use the media approach, well it seems it is only for Audio/video plus they will not be organized in a folder like I have them organized.
Am I missing something? How would I solve this problem?
Thank you
On an Android 11 device you can store your files in a subdirectory of the public Documents directory.
You can do that using classic File means or the media store or SAF.
Other apps can see them using SAF or the media store. Or with classic file means when requested all files access.
The user can see them using the default Files app on the device.
We have an Android app that allows the end-user to download and open files hosted from our server. These can be PDFs, mp4's, etc. However we don't want the user to be able to launch these files from the OS filesystem: we'd like the only way to open these downloaded files to be through our own app.
Can this be achieved by creating a proprietary file format, or some use of encryption that I'm not aware of? If so, would we need to create our own PDF reader that is capable of parsing through the obscurity that we develop, or would there be some way to internally "decrypt" the file and then open it in a standard 3rd party PDF viewer?
Internal storage is designed for holding content for which your app manages the access. This is in contrast to external storage (where the user has equal control) and removable storage (where the user has far greater control).
If you download your content to internal storage, you can use FileProvider to selectively grant short-term access to that content to viewer apps and the like.
This is not perfect:
Rooted device users can get at the content, but they can also defeat your other techniques too
A viewer might have its own "save as" or "share" or similar means of saving the content somewhere that the user controls
However, this is not significantly different than how content works on most platforms.
I need to download files on my mobile device and make them accessible for other apps (using Android and iOS).
I managed to download a file to the SD card (cordova.file.externalDataDirectory), but this only exists on Android and even then I cannot rely on every device having an SD card.
When I download to the device storage (cordova.file.dataDirectory), the file is private to my app and therefore not accessible for other apps. The file can be opened in the InAppBrowser, but I would prefer to use the respective default app.
Is there a way to get a path to a directory publicly available on all devices?
The paths returned by the solution suggested in https://stackoverflow.com/a/21375812/3432305 are both private on Android...
EDIT:
I think I should describe my use case so it's clearer what I'm trying to achieve: I want to open files from my in app chat using the respective default app (pdf viewer, image viewer etc.). Because the Cordova File Opener plugin only accepts files from the local file system, I need to save them first. But they don't necessarily need to be accessible from outside my app afterwards...
On Android, external storage directories always exist; if the device doesn't have a physical SD card, Android will emulate it. see getExternalStorageDirectory :
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.
Therefore cordova.file.externalDataDirectory will always resolve. However, for sharing data between apps, you probably want to use cordova.file.externalRootDirectory - External storage (SD card) root. See cordova-plugin-file.
This way you can store files in a place that's easier to access from another app e.g. /sdcard/my_shared_data/
On iOS, it's more difficult to share files because apps are intentionally isolated from each other due to security policy, as Apple's Inter-App Communication Guide says:
Apps communicate only indirectly with other apps on a device
You best bet on iOS is to share the data by synching it via iCloud. See the section Configuring a Common Ubiquity Container for Multiple Apps in iCloud Design Guide, which says:
... perhaps you provide two apps that interoperate and need
access to each other’s files. In both of these examples, you obtain
the needed access by specifying a common ubiquity container and then
requesting access to it from each app.
We have built an Android application which is used to collect data (for volleyball stats). This application creates a data file which we ultimately want to be transferred to desktop computers (Windows PCs and Macintoshes).
We currently write the data out as a simple character stream in the default application directory (data/data/appname/files) and specify MODE_WORLD_READABLE when we create each of these data files.
The problem is that even though the data files are MODE_WORLD_READABLE, the various utilities which we would like to use to transfer the data cannot see the data files. I assume that the problem is that they may have read access to the files, but they do not have read access to the directories in which the files are stored. Specifically, I am unable to browse to the files using the ES File Explorer app on the Android device and I am unable to browse to the files when I connect my Android device to the PC or Macintosh as a USB device.
Is my only solution to write files to the external directories, or is there something I am missing here about using MODE_WORLD_READABLE with application directories?
The file access mode for the application base directory (usually something like /data/data/com.package.app) and the top directories in it (databases, files, cache, ...) is rwxrwx--x. For other users than the application itself the relevant part is --x, which mean the directories can not be read (browsed) but they can be traversed. So you can read MODE_WORLD_READABLE files if you know exactly what you are looking for (the complete path).
We currently write the data out as a simple character stream in the
default application directory (data/data/appname/files) and specify
MODE_WORLD_READABLE when we create each of these data files.
AFAIK you cant access files from application sandbox (i.e /data/data/appname/files).If it were possible then you may never have used Content Providers.
The only solution i see here is whatever you want to achieve is only possible on Rooted Devices
hello guys i need small help in understanding file system of android
Now in windows for example we create files using paths like "c:/mytextfile.txt" or "c:/folder/mytextfile.txt".Now how can i access files and folders in android i mean whats the path like.
Does the phone support file browser instead of relying on third party apps??
Android does not have a native file browser, but there are numerous third-party ones (Astro comes to mind). The filesystem of Android is that of Linux; the path separator is / and the FS grows from a single root called /. So, you have your app packages under /data/apps, and so forth. Unless the phone is jailbroken ("rooted"), you won't get to see the whole filesystem - permissions get in the way. This applies to all Android applications, they are sandboxed - that is, they don't get access the whole filesystem. There are API calls to get the path to the current application's sandbox directory.