Can ACTION_OPEN_DOCUMENT look like the Files app? - android

I'm using ACTION_OPEN_DOCUMENT like this:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
launcher.launch(intent);
The launcher using ActivityResultContracts.StartActivityForResult.
A picker appears, and the sidebar look like the same one you see in the Files app, showing Recent, Images, Documents, Downloads and SDCARD. This is good.
Now if I restrict it to only certain mime types by adding
intent.putExtra(Intent.EXTRA_MIME_TYPES, arraylist-of-my-types);
the sidebar looks quite different, only showing Images and Documents.
Is it possible to restrict the types without affecting the sidebar? The user will want to know where the document they choose is located, especially when using an external SD card.

TL;DR: No.
A picker appears, and the sidebar look like the same one you see in the Files app, showing Recent, Images, Documents, Downloads and SDCARD.
What the documents UI looks like will vary by device model, and there are tens of thousands of device models. The specific sidebar (or equivalent) options can vary by user. The documents UI also may not exist, especially for edge device types (watch, TV, car).
Now if I restrict it to only certain mime types... the sidebar looks quite different, only showing Images and Documents.
See above.
Is it possible to restrict the types without affecting the sidebar?
There may not be a sidebar. What appears in the sidebar (or any equivalent) is up to the developers of the document UI for that device model. You and I do not control it except in very general terms, and then not in any manner that is necessarily consistent across device models.

Related

How can I use Android scoped storage to store large app specific files?

I have an old drawing app on Android, which stores drawings (.PNG files) out on a specific folder on external storage. With Scoped Storage in Android 11, I need to find a way to save files, but I can't seem to find a solution that meets my needs. My app has its own gallery UI, like many drawing apps, so that I can control the selection/view UX.
I've tried:
MediaStore: I inserted files with MediaStore. The issue I ran into here is that I couldn't figure out a way to query just the files that my app created. Querying mediastore always returns a bunch of stuff I don't want.
Storage Access Framework. My intuition with this framework, is that I would probably spend a lot of time and potentially regret going down that road. I don't like the idea of not controlling the file selector (gallery). I also don't like relying on intents for a critical part of my app.
MANAGE_EXTERNAL_FILES. Based on the criteria defined by Google, my app wouldn't qualify to use this, though it would be great (since I could keep my old code).
Use internal file storage. I coded this up, and it's really clean, but I hesitate to roll this out, because uninstalling would mean that users lose their documents. Note that i have a Share intent, so users can "export" files one at a time.
What I want:
To write files where they aren't removed when the user uninstalls my app.
To write my files somewhere that the user can back them up one way or another.
Simplicity. I don't want to confuse existing users by changing things drastically.
Am I missing something regarding my options here? Can Mediastore effectively partition my files so that I can show them in the gallery? Does internal storage seem like the best option for me?
Just create your files in the old fashioned way in your apps sub folder in public Documents directory.
No special permissions needed.

Android Scoped Storage and External Storage

I have an app that wants to have the ability to download files locally. A user can download a file (no restrictions to file type) and should be able to save it on the device so it can be used for other purposes. I would also like the user to be able to delete the file from the app (they would know which file is downloaded and which isn't, a ticker would indicate if it's backed up locally). Say it is a pdf file -- the user would want to open it with different apps or edit it if they have the ability to, or just share it via email. Considering we cannot opt out of scoped storage anymore (requirement to target 30), I got a couple of questions.
I've tried to use Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()) and also getExternalFilesDirPath(ctx, Environment.DIRECTORY_DOWNLOADS)). While the former is deprecated, it works for me in that the Files app can be used to navigate to the file in question (and possibly open/delete the file). On the other hand, I am not being able to delete this file from my app due to lack of permissions. Obviously, the latter path is unable to be navigated to by another app (or is it? I haven't found a way, hence the question).
The other thing I've considered using is the MediaStore API but I'm struggling to see how this is an improvement over the old ways in terms of function. Disregarding moving back to manual content resolver and cursor usage, how should arbitrary files be sorted? Should I manually sort by mime types and have different methods for saving for specific media types? It sounds exceptionally tedious and counter intuitive. If this is the way, so be it, I will implement it, but it does not sound like the way to go. On the positive side, it at least sounds like a solution due to the content resolver's CRUD abilities.
I'm working on a RN app that uses a 3rd party library for the download paths, which old/new versions, respectively, use different paths (rn fetch blob and rn fetch blob util). Additionally, MediaStore API doesn't have a RN implementation as of right now, so everything would have to be done from scratch, too.
What are my options? In the short term I'm considering disabling the erase feature from the app (at least for now). Anything I am missing and should consider? Thanks in advance.

Disable Ability to Take or Upload Photo on HTML File Input with Limited File Types

Wondering if anyone can help me out here. I have an input on a webpage that should only allow document files (not images). I have the "accept" parameter like so:
accept=".txt,.rtf,.pdf,.doc,.docx,.zip"
However it seems that on mobile phones (have tested multiple iOS devices and Android) it gives the user the ability to take a photo or upload.
Does anyone know a surefire way to prevent these options from showing? Typically iOS/Android have mechanisms that will respect the functionality of the HTML (like changing the keyboard for an input type number vs text), but here it seems like it doesn't care that I am trying to limit the file type.
In my case, the server will catch it and reject the image if they do upload it, but I'd really like them not to even get to that step by hiding that option.
On iOS, I'd like it to just say "browse", and on Android I'd like it to just say "Documents".
I realize my options are probably incredibly limited here, but I just wanted to know if I'm being stupid and if anyone had run into this issue with uploading files on mobile devices.
Thanks in advance, everyone!

Android intent ACTION_VIEW with share options

I'm using an intent with ACTION_VIEW to view a photo on android, but it doesnt open with any of the options the gallery has when viewing other pictures (specifically share). Anyone know how to make it have those options?
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(location, mimeType);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
gives me a viewer like this:
but just viewing in the gallery, i get all this stuff:
these issues are similar, but had no answer
Intent Action_View for image opens gallery with no delete option
Android image intent : sharing/editing options
and the interesting thing is both of those issues talk about those options ALREADY being available... so im not sure what im doing wrong.
but it doesnt open with any of the options the gallery has when viewing other pictures (specifically share)
There are ~2 billion Android devices, made up of thousands of device models. Many of those device models will ship with 1+ activities that support your Intent structure, and many of the actual devices will have other apps that support it, installed by users. None have to offer a "share" option.
Anyone know how to make it have those options?
Strictly speaking, you can't.
Those image-viewing apps were written by developers, and those developers can do whatever they want. Perhaps there are different activities for internal use vs. ACTION_VIEW. Perhaps it is the same activity, but they only offer those options when the activity is reached internally (vs. from outside apps via ACTION_VIEW). Perhaps they only share certain Uri schemes or MIME types. Perhaps they do not share images because it is Tuesday.
And, again, the behavior will be different on different devices, based on which image-viewing apps the user has and chooses to use.
If you want to have a "share" option, put it in your app. If you want that share option to be on the screen that shows the image, show the image in your app. Right now, you are delegating all of that to third-party apps, and those apps do not have to do what you want.

Can StorageActionFramework ACTION_OPEN_DOCUMENT request a single file?

Is there a way to use the StorageActionFramework ACTION_OPEN_DOCUMENT intent to request info for a specific file? More specifically, I have a URI for a particular file, which I obtained from MediaStore. I would like to find out if it has write access and, if so, delete it. Further, I'd like to do this without any UI (none is needed in this particular context).
The documentation says how to do it for a class of files using intent.addCategory (Intent.CATEGORY_OPENABLE), for example. And to restrict it to a certain type of file, intent.setType ("image/*"), for example. But I don't see anything to restrict it to a specific file.
Also, I realize that once you receive a set of files from the StorageActionFramework, you can view properties for individual files.
It appears that if I could use ACTION_OPEN_DOCUMENT to get the SAF's URI, I could then use DocumentsContract.deleteDocument() to delete it.
More Context
In my situation, the user has invoked the camera app from within my app and taken one or more pictures. My code then queries the MediaStore to determine the file name(s) for the new image(s). Then I desire to move the file(s) to a directory specific to my app. This works fine for files located in "internal" and "external" storage but not for removable storage.
In the long run, this solution is inadequate as clearly it will use to much permanent storage (although that is mitigated by the fast pace which storage size is increasing). However my app does need control over image files which are taken via the app and, thus, leaving them on the removable storage will potentially break the app.
Another complicating factor is the lack of an Android API for taking multiple photos and saving them to a prescribed location. There is such an API for taking a single photo but that will not work for my application. Thus, I am relegated to letting the camera app save its files where it wants to and then moving them afterward.
Some other apps simply make a copy of photos and store the copy in a private directory. I could do that but that exacerbates the storage problem even more. The long term solution will probably be using cloud storage in combination with a local private cache.
Is there a way to use the StorageActionFramework ACTION_OPEN_DOCUMENT intent to request info for a specific file?
No. For starters, the Storage Access Framework has little to do with files.
The closest thing that would fit the overall structure would be if you could supply a starting Uri, to allow users to choose and open a document nearby that one. That would be a nice feature but is not supported.
The documentation says how to do it for a class of files using intent.addCategory (Intent.CATEGORY_OPENABLE), for example.
No. CATEGORY_OPENABLE means that the Uri that you get back should work with openInputStream(), openOutputStream(), and related methods, and that a query() on the Uri should be able to return the OpenableColumns. It has little to do with files.
And to restrict it to a certain type of file, intent.setType ("image/*")
That limits the content to a particular MIME type (or wildcard). It has little to do with files.
I would like to find out if it has write access and, if so, delete it
You might have write access to change the contents, via openOutputStream(). I am not aware that you have a means of deleting the underlying content.
Further, I'd like to do this without any UI
The only reason to use ACTION_OPEN_DOCUMENT is to show a UI, to allow the user to choose a piece of content.
My code then queries the MediaStore to determine the file name for the new image
Since there is no requirement for a camera app to update the MediaStore, this does not seem like it will be especially reliable.
Another complicating factor is the lack of an Android API for taking multiple photos and saving them to a prescribed location. There is such an API for taking a single photo but that will not work for my application
Since there is no requirement for a camera app to allow the user to take multiple photos in succession, this does not seem like it will be especially reliable.

Categories

Resources