Files in the Google Drive Android API, represented by the
DriveFile
interface, are specialized
resources with Metadata
, a
DriveId
, and
DriveContents
. The binary content of
a file is encapsulated in the DriveContents
class.
You can choose to work with the file contents either by using the InputStream
and OutputStream
classes, or by working with the ParcelFileDescriptor
.
The access methods available to you depend on the mode the file was opened in.
Mode | Method | Class |
---|---|---|
MODE_READ_ONLY |
getInputStream |
InputStream |
MODE_WRITE_ONLY |
getOutputStream |
OutputStream |
MODE_READ_WRITE |
getParcelFileDescriptor |
ParcelFileDescriptor |
Lifecycle of a Drive file
The Drive Android API lets your app access files even if the device is offline. To support offline cases, the API implements a sync engine that runs in the background to merge upstream and downstream changes as network access is available and to resolve conflicts.
The lifecycle of a DriveFile
object:
- Perform an initial download request if the file is not yet synced to the local context but the user wants to open the file. The API handles this automatically when a file is requested.
- Open the contents of a file. This creates a temporary duplicate of the file's binary stream that is only available to your application.
- Read or modify the file contents, making changes to the temporary duplicate.
- Commit or discard any file content changes that have been made.
- If there are changes, the Drive service puts the file contents into a queue for upload to sync them back to the server.
Reading files
Because the Drive Android API automatically handles downloading the file contents if the file has not been synced locally, the process of reading from a file is similar to using local storage. The basic steps to read a file are:
- Retrieve the
DriveFile
object. - Open the file contents.
- Retrieve and process the contents using the
InputStream
or theParcelFileDescriptor
class, depending on the mode used. - Close the file contents.
Opening the file contents
In order to be able to read a file, you must start by opening its
DriveContents
resource in DriveFile.MODE_READ_ONLY
or
DriveFile.MODE_READ_WRITE
mode, depending on whether you prefer to work with
the InputStream
or ParcelFileDescriptor
class.
The
DriveResourceClient.openFile
method retrieves the locally synced file
resource and opens it. If the file is not synced with the local storage,
it retrieves the file from the Drive service and returns a DriveContents
resource. For example:
A DriveContents
resource contains a temporary copy of the file's binary stream
that is only available to your application. If multiple applications attempt to
access the same file, there are no race conditions between DriveContents
resources. In this situation, the last write operation is the final
state of the content.
Handling the response requires you to check if the call was successful.
If the call was successful, you can retrieve the DriveContents
resource. This
resource contains methods to retrieve an InputStream
or ParcelFileDescriptor
to read the file's binary contents.
The following example demonstrates how to retrieve a file's DriveContents
:
Listening to the download progress
Opening a file can require a long I/O operation if the file is not yet synced
locally. You can attach a
OpenFileCallback
to inform users of the
download progress in a ProgressDialog
to improve the user experience.
To listen to the download progress, open the file contents with a
DownloadProgressListener
, as shown in this example:
In the event that the file has already been synced locally, the system does not
call the onProgress
listener.
Reading from the input stream
A DriveContents
resource provides a java.io.InputStream
you can use to read
the binary contents of the opened file. The sample below illustrates how to read
from a DriveContents
resource and convert the binary contents into a String
object. However, you can consume the input stream in whatever way your
application and data format require.
Writing files
Writing to a file follows a similar procedure to reading a file, with the
difference being that you use either the OutputStream
or the
ParcelFileDescriptor
class to write to the file, determined by the mode you
opened the file in.
Opening the file contents
Just as with reading files, you must open contents in order to write to a file.
You can use either the DriveFile.MODE_WRITE_ONLY
or DriveFile.MODE_READ_WRITE
to open the contents in a writable mode, depending on whether you intend to
overwrite the content with an OutputStream
or append to the content with a
ParcelFileDescriptor
. You can optionally use a OpenFileCallback
to
listen to the download status
if the latest version of the file is not already synced to the device.
The following example shows how to open and retrieve the file contents:
Your application must handle the opening call to verify that the DriveContents
resource is successfully opened. Once the contents are open, you can make
modifications to them.
Making modifications
The DriveContents
resource provides a java.io.OutputStream
that lets you write
or append binary data to the file contents.
The example below illustrates how to append "Hello world" to a DriveContents
object.
Each DriveContents
resource is a temporary duplicate of the file you are trying
to modify and is only accessible within your application. Once you're done
with the output stream, you must either commit any changes that you made, making
them visible in the user's Drive, or discard the changes.
The next section demonstrates how to finalize the write operation.
Closing the file contents
You must close each opened DriveContents
resource to free related resources,
notifying the system whether you want to keep or discard any changes made. In
order the keep the changes permanently, use the
DriveResourceClient.commitContents
method, passing in the DriveContents
object to close.
Task<Void> commitTask =
getDriveResourceClient().commitContents(driveContents, null);
You can also use this method to submit simultaneous metadata changes. For example:
To discard the changes you made to the temporary DriveContents
resource, use the
DriveResourceClient.discardContents
method to avoid writing changes to the file in the user's Drive.
Any committed changes are synced to the user's Drive on the next scheduled sync task.