Google Drive SDK

Storing Application Data

The Google Drive API includes a special hidden folder that your app can use to store application data.

What is the Application Data folder?

The 'Application Data folder' is a special folder that is only accessible by your application. Its content is hidden from the user, and from other apps. Despite being hidden from the user, the Application Data folder is stored on the user's Drive and therefore uses the user's Drive storage quota. The Application Data folder can be used to store configuration files, saved games data, or any other types of files that the user should not tamper with.

Even though users can't see the Application Data folder's content, they can see the amount of storage used by your Application Data folder in the Manage Apps dialog:

Manage apps dialog showing Application Data folder size

Your Application Data folder is deleted if users uninstall your app from their Drive. They can also delete your app's data folder manually.

Get authorization to use the Application Data folder

To be able to use your Application Data folder, request access to the following scope:

https://www.googleapis.com/auth/drive.appdata

For more information about scopes and how to request access to them, see Choose auth scopes and Authorizing Your App with Google Drive.

Working with the Application Data folder

The application specific folder is accessible using the alias appdata. This alias can be used like any other folder ID; for instance, when listing the files located in your application's folder or when creating files by listing appdata as a parent.

Much of the information you'll need to get started, including client library examples, is detailed in the Files reference.

Retrieving metadata for the Application Data folder

The following code snippets shows how to retrieve the ID and other metadata for the Application Data folder:

Java

/**
 * Print metadata for the Application Data folder.
 *
 * @param service Drive API service instance.
 */
private static void printApplicationDataFolderMetadata(Drive service) {
  try {
    File file = service.files().get("appdata").execute();

    System.out.println("Id: " + file.getId());
    System.out.println("Title: " + file.getTitle());
  } catch (IOException e) {
    System.out.println("An error occured: " + e);
  }
}

PHP

/**
 * Print metadata for the Application Data folder.
 *
 * @param Google_DriveService $service Drive API service instance.
 */
function printApplicationDataFolderMetadata($service) {
  try {
    $file = $service->files->get("appdata");

    print "Id: " . $file->getId();
    print "Title: " . $file->getTitle();
  } catch (Exception $e) {
    print "An error occurred: " . $e->getMessage();
  }
}

JavaScript

/**
 * Print metadata for the Application Data folder.
 */
function printApplicationDataFolderMetadata() {
  var request = gapi.client.drive.files.get({
    'fileId': 'appdata'
  });
  request.execute(function(resp) {
    console.log('Id: ' + resp.id);
    console.log('Title: ' + resp.title);
  });
}

.NET

/// <summary>
/// Print metadata for the Application Data folder.
/// </summary>
/// <param name="service">Drive API service instance.</param>
public static void printApplicationDataFolderMetadata(DriveService service) {
  try {
    File file = service.Files.Get("appdata").Fetch();

    Console.WriteLine("Id: " + file.Id);
    Console.WriteLine("Title: " + file.Title);
  } catch (Exception e) {
    Console.WriteLine("An error occurred: " + e.Message);
  }
}

Python

def print_application_data_folder_metadata(service):
  """Print metadata for the Application Data folder.

  Args:
    service: Drive API service instance.
  """
  try:
    file = service.files().get(fileId='appdata').execute()

    print 'Id: %s' % file['id']
    print 'Title: %s' % file['title']
  except errors.HttpError, error:
    print 'An error occurred: %s' % error

Objective-C

+ (void)printApplicationDataFolderMetadataWithService:(GTLServiceDrive *)service {
  GTLQuery *query = [GTLQueryDrive queryForFilesGetWithFileId:"appdata"];

  // queryTicket can be used to track the status of the request.
  GTLServiceTicket *queryTicket =
    [service executeQuery:query
        completionHandler:^(GTLServiceTicket *ticket, GTLDriveFile *file,
                            NSError *error) {
        if (error == nil) {
          NSLog(@"Id: %@", file.id);
          NSLog(@"Title: %@", file.title);
        } else {
          NSLog(@"An error occurred: %@", error);
        }
      }];
}

Ruby

##
# Print metadata for the Application Data folder.
#
# @param [Google::APIClient] client
#   Authorized client instance
# @return nil
def print_application_data_folder_metadata(client)
  drive = client.discovered_api('drive', 'v2')
  result = client.execute(
    :api_method => drive.files.get,
    :parameters => { 'fileId' => 'appdata' })
  if result.status == 200
    file = result.data
    puts "Id: #{file.id}"
    puts "Title: #{file.title}"
  else
    puts "An error occurred: #{result.data['error']['message']}"
  end
end

Go

package drive_examples

// PrintApplicationDataFolderMetadata prints metadata for the Application Data folder.
func PrintApplicationDataFolderMetadata(d *drive.Service) error {
	f, err := d.Files.Get("appdata").Do()
	if err != nil {
		fmt.Printf("An error occurred: %v\n", err)
		return err
	}
	fmt.Printf("Id: %v", f.Id)
	fmt.Printf("Title: %v", f.Title)
	return nil
}

Inserting a file into the Application Data folder

Applications can use the following code snippet to store a new file in the Application Data folder:

Java

/**
 * Insert new file in the Application Data folder.
 *
 * @param service Drive API service instance.
 * @param title Title of the file to insert, including the extension.
 * @param description Description of the file to insert.
 * @param mimeType MIME type of the file to insert.
 * @param filename Filename of the file to insert.
 * @return Inserted file metadata if successful, {@code null} otherwise.
 */
private static File insertFileInApplicationDataFolder(Drive service, String title, String description,
    String mimeType, String filename) {
  // File's metadata.
  File body = new File();
  body.setTitle(title);
  body.setDescription(description);
  body.setMimeType(mimeType);
  body.setParents(Arrays.asList(new ParentReference().setId("appdata")));

  // File's content.
  java.io.File fileContent = new java.io.File(filename);
  FileContent mediaContent = new FileContent(mimeType, fileContent);
  try {
    File file = service.files().insert(body, mediaContent).execute();
    return file;
  } catch (IOException e) {
    System.out.println("An error occured: " + e);
    return null;
  }
}

PHP

/**
 * Insert new file in the Application Data folder.
 *
 * @param Google_DriveService $service Drive API service instance.
 * @param string $title Title of the file to insert, including the extension.
 * @param string $description Description of the file to insert.
 * @param string $mimeType MIME type of the file to insert.
 * @param string $filename Filename of the file to insert.
 * @return Google_DriveFile The file that was inserted. NULL is returned if an API error occurred.
 */
function insertFileInApplicationDataFolder($service, $title, $description, $mimeType, $filename) {
  $file = new Google_DriveFile();
  $file->setTitle($title);
  $file->setDescription($description);
  $file->setMimeType($mimeType);

  $parent = new ParentReference();
  $parent->setId("appdata");
  $file->setParents(array($parent));

  try {
    $data = file_get_contents($filename);

    $createdFile = $service->files->insert($file, array(
      'data' => $data,
      'mimeType' => $mimeType,
    ));

    return $createdFile;
  } catch (Exception $e) {
    print "An error occurred: " . $e->getMessage();
  }
}

JavaScript

/**
 * Insert new file in the Application Data folder.
 *
 * @param {File} fileData File object to read data from.
 * @param {Function} callback Function to call when the request is complete.
 */
function insertFileInApplicationDataFolder(fileData, callback) {
  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  var reader = new FileReader();
  reader.readAsBinaryString(fileData);
  reader.onload = function(e) {
    var contentType = fileData.type || 'application/octet-stream';
    var metadata = {
      'title': fileData.fileName,
      'mimeType': contentType,
      'parents': [{'id': 'appdata'}]
    };

    var base64Data = btoa(reader.result);
    var multipartRequestBody =
        delimiter +
        'Content-Type: application/json\r\n\r\n' +
        JSON.stringify(metadata) +
        delimiter +
        'Content-Type: ' + contentType + '\r\n' +
        'Content-Transfer-Encoding: base64\r\n' +
        '\r\n' +
        base64Data +
        close_delim;

    var request = gapi.client.request({
        'path': '/upload/drive/v2/files',
        'method': 'POST',
        'params': {'uploadType': 'multipart'},
        'headers': {
          'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
        },
        'body': multipartRequestBody});
    if (!callback) {
      callback = function(file) {
        console.log(file)
      };
    }
    request.execute(callback);
  }
}

.NET

/// <summary>
/// Insert new file in the Application Data folder.
/// </summary>
/// <param name="service">Drive API service instance.</param>
/// <param name="title">Title of the file to insert, including the extension.</param>
/// <param name="description">Description of the file to insert.</param>
/// <param name="mimeType">MIME type of the file to insert.</param>
/// <param name="filename">Filename of the file to insert.</param>
/// <returns>Inserted file metadata, null is returned if an API error occurred.</returns>
private static File insertFile(DriveService service, String title, String description,
    String mimeType, String filename) {
  // File's metadata.
  File body = new File();
  body.Title = title;
  body.Description = description;
  body.MimeType = mimeType;
  body.Parents = new List<ParentReference>() {new ParentReference() {Id = "appdata"}};

  // File's content.
  byte[] byteArray = System.IO.File.ReadAllBytes(filename);
  MemoryStream stream = new MemoryStream(byteArray);

  try {
    FilesResource.InsertMediaUpload request = service.Files.Insert(body, stream, mimeType);
    request.Upload();

    File file = request.ResponseBody;
    return file;
  } catch (Exception e) {
    Console.WriteLine("An error occurred: " + e.Message);
    return null;
  }
}

Python

def insert_file_in_application_data_folder(service, title, description, mime_type, filename):
  """Insert new file in the Application Data folder.

  Args:
    service: Drive API service instance.
    title: Title of the file to insert, including the extension.
    description: Description of the file to insert.
    mime_type: MIME type of the file to insert.
    filename: Filename of the file to insert.
  Returns:
    Inserted file metadata if successful, None otherwise.
  """
  media_body = MediaFileUpload(filename, mimetype=mime_type, resumable=True)
  body = {
    'title': title,
    'description': description,
    'mimeType': mime_type
    'parents': [{'id': 'appdata'}]
  }

  try:
    file = service.files().insert(
        body=body,
        media_body=media_body).execute()
    return file
  except errors.HttpError, error:
    print 'An error occured: %s' % error
    return None

Objective-C

+ (void)insertFileInApplicationDataFolderWithService:(GTLServiceDrive *)service
                                               title:(NSString *)title
                                         description:(NSString *)description
                                            mimeType:(NSString *)mimeType
                                                data:(NSData *)data
                                     completionBlock:(void (^)(GTLDriveFile *, NSError *))completionBlock {
  GTLDriveFile *file = [GTLDriveFile object];

  file.title = title;
  file.descriptionProperty = description;
  file.mimeType = mimeType;
  file.parents = [NSArray arrayWithObjects: @"appdata", nil];

  GTLUploadParameters *uploadParameters =
    [GTLUploadParameters uploadParametersWithData:data MIMEType:mimeType];
  GTLQueryDrive *query =
    [GTLQueryDrive queryForFilesInsertWithObject:file
                                uploadParameters:uploadParameters];

  // queryTicket can be used to track the status of the request, more information can
  // be found on https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Uploading_Files
  GTLServiceTicket *queryTicket =
    [service executeQuery:query
        completionHandler:^(GTLServiceTicket *ticket,
                            GTLDriveFile *insertedFile, NSError *error) {
        if (error == nil) {
          // Uncomment the following line to print the File ID.
          // NSLog(@"File ID: %@", insertedFile.identifier);
          completionBlock(insertedFile, nil);
        } else {
          NSLog(@"An error occurred: %@", error);
          completionBlock(nil, error);
        }
      }];
}

Ruby

##
# Insert new file in the Application Data folder
#
# @param [Google::APIClient] client
#   Authorized client instance
# @param [String] title
#   Title of file to insert, including the extension.
# @param [String] description
#   Description of file to insert
# @param [String] parent_id
#   Parent folder's ID.
# @param [String] mime_type
#   MIME type of file to insert
# @param [String] file_name
#   Name of file to upload
# @return [Google::APIClient::Schema::Drive::V2::File]
#   File if created, nil otherwise
def insert_file_in_application_data_folder(client, title, description, mime_type, file_name)
  drive = client.discovered_api('drive', 'v2')
  file = drive.files.insert.request_schema.new({
    'title' => title,
    'description' => description,
    'mimeType' => mime_type,
    'parents' => [{'id' => 'appdata'}]
  })
  media = Google::APIClient::UploadIO.new(file_name, mime_type)
  result = client.execute(
    :api_method => drive.files.insert,
    :body_object => file,
    :media => media,
    :parameters => {
      'uploadType' => 'multipart',
      'alt' => 'json'})
  if result.status == 200
    return result.data
  else
    puts "An error occurred: #{result.data['error']['message']}"
    return nil
  end
end

Go

package drive_examples

// InsertFileInApplicationDataFolder creates a new file in the Application Data folder.
func InsertFileInApplicationDataFolder(d *drive.Service, title string, description string,
	mimeType string, filename string) (*drive.File, error) {
	m, err := os.Open(filename)
	if err != nil {
		fmt.Printf("An error occurred: %v\n", err)
		return nil, err
	}
	f := &drive.File{Title: title, Description: description, MimeType: mimeType}
	p := &drive.ParentReference{Id: "appdata"}
	f.Parents = []*drive.ParentReference{p}
	r, err := d.Files.Insert(f).Media(m).Do()
	if err != nil {
		fmt.Printf("An error occurred: %v\n", err)
		return nil, err
	}
	return r, nil
}

Listing files from the Application Data folder

The following code snippets shows how to programmatically list all files stored in the Application Data folder:

Java

/**
 * List all files contained in the Application Data folder.
 *
 * @param service Drive API service instance.
 * @return List of File resources.
 */
private static List<File> listFilesInApplicationDataFolder(Drive service) {
  List<File> result = new ArrayList<File>();
  Files.List request = service.files().list();
  request.setQ("'appdata' in parents");

  do {
    try {
      FileList files = request.execute();

      result.addAll(files.getItems());
      request.setPageToken(files.getNextPageToken());
    } catch (IOException e) {
      System.out.println("An error occurred: " + e);
      request.setPageToken(null);
    }
  } while (request.getPageToken() != null &&
           request.getPageToken().length() > 0);

  return result;
}

PHP

/**
 * List all files contained in the Application Data folder.
 *
 * @param Google_DriveService $service Drive API service instance.
 * @return Array List of Google_DriveFile resources.
 */
function listFilesInApplicationDataFolder($service) {
  $result = array();
  $pageToken = NULL;

  do {
    try {
      $parameters = array();
      if ($pageToken) {
        $parameters['pageToken'] = $pageToken;
      } else {
        $parameters['q'] = "'appdata' in parents";
      }
      $files = $service->files->listFiles($parameters);

      $result = array_merge($result, $files->getItems());
      $pageToken = $files->getNextPageToken();
    } catch (Exception $e) {
      print "An error occurred: " . $e->getMessage();
      $pageToken = NULL;
    }
  } while ($pageToken);
  return $result;
}

JavaScript

/**
 * List all files contained in the Application Data folder.
 *
 * @param {Function} callback Function to call when the request is complete.
 */
function listFilesInApplicationDataFolder(callback) {
  var retrievePageOfFiles = function(request, result) {
    request.execute(function(resp) {
      result = result.concat(resp.items);
      var nextPageToken = resp.nextPageToken;
      if (nextPageToken) {
        request = gapi.client.drive.files.list({
          'pageToken': nextPageToken
        });
        retrievePageOfFiles(request, result);
      } else {
        callback(result);
      }
    });
  }
  var initialRequest = gapi.client.drive.files.list({
    'q': '\'appdata\' in parents'
  });
  retrievePageOfFiles(initialRequest, []);
}

.NET

/// <summary>
/// List all files contained in the Application Data folder.
/// </summary>
/// <param name="service">Drive API service instance.</param>
/// <returns>List of File resources.</returns>
public static List<File> listFilesInApplicationDataFolder(DriveService service) {
  List<File> result = new List<File>();
  FilesResource.ListRequest request = service.Files.List();
  request.Q("'appdata' in parents");

  do {
    try {
      FileList files = request.Fetch();

      result.AddRange(files.Items);
      request.PageToken = files.NextPageToken;
    } catch (Exception e) {
      Console.WriteLine("An error occurred: " + e.Message);
      request.PageToken = null;
    }
  } while (!String.IsNullOrEmpty(request.PageToken));
  return result;
}

Python

def list_files_in_application_data_folder(service):
  """List all files contained in the Application Data folder.

  Args:
    service: Drive API service instance.
   Returns:
    List of File resources.
  """
  result = []
  page_token = None
  while True:
    try:
      param = {}
      if page_token:
        param['pageToken'] = page_token
      else:
        param['q'] = "'appdata' in parents"
      files = service.files().list(**param).execute()

      result.extend(files['items'])
      page_token = files.get('nextPageToken')
      if not page_token:
        break
    except errors.HttpError, error:
      print 'An error occurred: %s' % error
      break
  return result

Objective-C

+ (void)listFilesInApplicationDataFolderWithService:(GTLServiceDrive *)service
                                    completionBlock:(void (^)(NSArray *, NSError *))completionBlock {
  // The service can be set to automatically fetch all pages of the result. More information
  // can be found on https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Result_Pages.
  service.shouldFetchNextPages = YES;

  GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
  query.q = @"'appdata' in parents";
  // queryTicket can be used to track the status of the request.
  GTLServiceTicket *queryTicket =
    [service executeQuery:query
        completionHandler:^(GTLServiceTicket *ticket, GTLDriveFileList *files,
                            NSError *error) {
          if (error == nil) {
            completionBlock(files.items, nil);
          } else {
            NSLog(@"An error occurred: %@", error);
            completionBlock(nil, error);
          }
        }];
}

Ruby

##
# List all files contained in the Application Data folder.
#
# @param [Google::APIClient] client
#   Authorized client instance
# @return [Array]
#   List of File resources.
#
def list_files_in_application_data_folder(client)
  drive = client.discovered_api('drive', 'v2')
  result = Array.new
  page_token = nil
  begin
    parameters = {}
    if page_token.to_s != ''
      parameters['pageToken'] = page_token
    else
      parameters['q'] = "'appdata' in parents"
    end
    api_result = client.execute(
      :api_method => drive.files.list,
      :parameters => parameters)
    if api_result.status == 200
      files = api_result.data
      result.concat(files.items)
      page_token = files.next_page_token
    else
      puts "An error occurred: #{result.data['error']['message']}"
      page_token = nil
    end
  end while page_token.to_s != ''
  result
end

Go

package drive_examples

// ListFilesInApplicationDataFolder lists all files contained in the Application Data folder.
func ListFilesInApplicationDataFolder(d *drive.Service) ([]*drive.File, error) {
	var fs []*drive.File
	pageToken := ""
	for {
		request := d.Files.List()
		// If we have a pageToken set, apply it to the query
		if pageToken != "" {
			request = request.PageToken(pageToken)
		} else {
			request = request.Q("'appdata' in parents")
		}
		r, err := request.Do()
		if err != nil {
			fmt.Printf("An error occurred: %v\n", err)
			return fs, err
		}
		fs = append(fs, r.Items...)
		pageToken = r.NextPageToken
		if pageToken == "" {
			break
		}
	}
	return fs, nil
}

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.