What is the real difference between ACTION_GET_CONTENT and ACTION_OPEN_DOCUMENT?

I'm having a hard time understanding the difference between ACTION_OPEN_DOCUMENT and ACTION_GET_CONTENT intents when they are used to open an openable document. If I am supporting Andriod before KitKat, which does not support ACTION_OPEN_DOCUMENT, should I just settle with ACTION_GET_CONTENT?

The documentation says this:

ACTION_OPEN_DOCUMENT is not intended to be a replacement for ACTION_GET_CONTENT. The one you should use depends on the needs of your app:

  • Use ACTION_GET_CONTENT if you want your app to simply read/import data. With this approach, the app imports a copy of the data, such as an image file.
  • Use ACTION_OPEN_DOCUMENT if you want your app to have long term, persistent access to documents owned by a document provider. An example would be a photo-editing app that lets users edit images stored in a document provider.

Doesn't ACTION_GET_CONTENT also use document providers in KitKat? What would prevent me from having "long term, persistent access" and what exactly does that mean?

Basically, what is the difference between the following two snippets?

ACTION_GET_CONTENT

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");

ACTION_OPEN_DOCUMENT

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("*/*");

Solution 1:

Doesn't ACTION_GET_CONTENT also use document providers in KitKat?

Not necessarily. That depends on the implementation of the app that is publishing the content. Also note that DocumentProvider is a specific type of ContentProvider.

What would prevent me from having "long term, persistent access"

The Uri that you get back from ACTION_GET_CONTENT may have a temporary permission grant with it for your app, to be able to read and/or write the content. That grant will eventually lapse (e.g., when your process terminates). So, for example, saving the Uri as a string in a database may be pointless.

Part of the Storage Access Framework includes the concept that a provider of content can offer permission grants that can last for an extended period ("long-term, persistent"). While there's nothing stopping an app from offering such persistent permissions with ACTION_GET_CONTENT on API Level 19+, they will be more common with ACTION_OPEN_DOCUMENT.

Basically, what is the difference between the following two snippets?

The user experience will be somewhat different, as ACTION_OPEN_DOCUMENT provides a standardized file explorer-style interface, whereas ACTION_GET_CONTENT is a traditional chooser dialog, followed by some app-specific UI.

From your standpoint as a consumer of this content, ACTION_GET_CONTENT is if you want to use the content now; ACTION_OPEN_DOCUMENT is if you want to use the content now and later.

Edit: Links to documentation:

ACTION_OPEN_DOCUMENT

ACTION_GET_CONTENT

From the Common Intents example for opening a specific type of file:

Instead of retrieving a copy of a file that you must import to your app (by using the ACTION_GET_CONTENT action), when running on Android 4.4 or higher, you can instead request to open a file that's managed by another app by using the ACTION_OPEN_DOCUMENT action and specifying a MIME type. To also allow the user to instead create a new document that your app can write to, use the ACTION_CREATE_DOCUMENT action instead. For example, instead of selecting from existing PDF documents, the ACTION_CREATE_DOCUMENT intent allows users to select where they'd like to create a new document (within another app that manages the document's storage)—your app then receives the URI location of where it can write the new document.

Whereas the intent delivered to your onActivityResult() method from the ACTION_GET_CONTENT action may return a URI of any type, the result intent from ACTION_OPEN_DOCUMENT and ACTION_CREATE_DOCUMENT always specify the chosen file as a content: URI that's backed by a DocumentsProvider. You can open the file with openFileDescriptor() and query its details using columns from DocumentsContract.Document.