I have folders on my Google Drive account and i want to add files in specific folder. How can I do it? In example needed DriveId (EXISTING_FOLDER_ID), but I don't know DriveID my folder, I know name only.
#smokybob. I don't know if it helps with the original question, but per your comment:
Here's a code snippet that should get you folder/file DriveId. The 'title', 'mime' and 'fldr' arguments are optional. In case you pass null for 'fldr', the search is global (within the app's FILE scope), otherwise within the specified folder (not in subfolders, though). It uses the simplest - 'await()' flavor, that has to be run off the UI thread.
Be careful though, the folder / file names are not unique entities in the Google Drive Universe. You can have multiple files / folders with the same name in a single folder !
GoogleApiClent _gac; // initialized elsewhere
//find files, folders. ANY 'null' ARGUMENT VALUE MEANS 'any'
public void findAll(String title, String mime, DriveFolder fldr) {
ArrayList<Filter> fltrs = new ArrayList<Filter>();
fltrs.add(Filters.eq(SearchableField.TRASHED, false));
if (title != null) fltrs.add(Filters.eq(SearchableField.TITLE, title));
if (mime != null) fltrs.add(Filters.eq(SearchableField.MIME_TYPE, mime));
Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build();
MetadataBufferResult rslt = (fldr == null) ?
Drive.DriveApi.query(_gac, qry).await() :
fldr.queryChildren(_gac, qry).await();
if (rslt.getStatus().isSuccess()) {
MetadataBuffer mdb = null;
try {
mdb = rslt.getMetadataBuffer();
if (mdb != null) {
for (Metadata md : mdb) {
if (md == null) continue;
DriveId dId = md.getDriveId(); // here is the "Drive ID"
String title = md.getTitle();
String mime = md.getMimeType();
// ...
}
}
} finally { if (mdb != null) mdb.close(); }
}
}
In general terms, you can get the 'DriveId' you need from:
file / folder name as shown in the code above, or
the string identifier you've got from 'encodeToString()'. I use it for caching MYROOT folder id, for instance, or
the string identifier you've got from 'getResourceId()'. This is the string you see in the html address. But since your only scope is FILE, don't count on using it to open something your app did not create.
Both 2 and 3 identifiers are strings, so they may be confused. Identifier 2 is faster when retrieving Drive ID (via decodeFromString()). Identifier 3 is slower to retrieve (via fetchDriveId()), but usefull if you need to take your ID elsewhere (Apps Script, for instance). See also SO 21800257
As far as creation of files / folders is concerned, I have some code on GitHub here. If you look at awaits\MainActivity.java ... buildTree(), you will see the creation of folders / files recursively when building a simple folder tree.
OK. I experienced the same issue with the Drive demos on Github: https://github.com/googledrive/android-demos
At the bottom of the readme, it says:
If you actually want to run this sample app (though it is mostly
provided so you can read the code), you will need to register an OAuth
2.0 client for the package com.google.android.gms.drive.sample.demo with your own debug keys and set any resource IDs to those that you
have access to. Resource ID definitions are on:
com.google.android.gms.drive.sample.demo.BaseDemoActivity.EXISTING_FOLDER_ID
com.google.android.gms.drive.sample.demo.BaseDemoActivity.EXISTING_FILE_ID
They didn't really specify how exactly one should get and set the resourceID for the EXISTING_FOLDER_ID and EXISTING_FILE_ID constants defined in the BaseDemoActivity file and after reading seanpj comment above, I used his method number 3 to find the DriveIDs so that I can add it to the demo app so that it runs properly.
All one needs to do is to go to Drive on your PC then click on the "link" button at the top.
A portion of the link says "id=XXXXXXXXXXX". Copy that and paste it into the BaseDemoActivity file in the demo app. Do this for both a file and a folder that you create yourself on Drive.
The Demo app should now run successfully.
you can use query to find folder
Query query = new Query.Builder().addFilter(Filters.and(
Filters.eq(SearchableField.TITLE, "folder name"),
Filters.eq(SearchableField.TRASHED, false))).build();
I fount one sample tutorial
http://wiki.workassis.com/android-google-drive-api-deleted-folder-still-exists-in-query/
in this tutorial they are calling asynchronously
If you have the metadata for the folder (or a DriveFolder object, from which you can get the metadata), you can just call getDriveId.
If you have the web resource, you can get the DriveId using that resource id using fetchDriveId
Related
I'm running a query on the Android SDK for Google Drive to check if a directory with a specific name exists or creating it otherwise (directory name is the resource title on Google Drive).
The problem I'm having with the following code is that it never finds my folder and creates a new one every time and I'm not sure why. It successfully finds the directory if the SDK created it itself.
public static final String FOLDER_NAME_CORE = "My Core Folder";
MetadataBuffer meta = Drive.DriveApi.query(mGoogleApiClient, new Query.Builder()
.addFilter(Filters.eq(SearchableField.TRASHED, false))
.addFilter(Filters.eq(SearchableField.TITLE, FOLDER_NAME_CORE ))
.setSortOrder(new SortOrder.Builder().addSortDescending(SortableField.MODIFIED_DATE).build())
.build()).await().getMetadataBuffer();
if (metadataBufferResult.getCount() > 0) {
Log.d(TAG, "Creating new folder");
...
} else {
Log.d(TAG, "Using existing folder");
}
I've tried making the folder publicly shared but it didn't change anything (as expected). Does anyone know what I have to change to make it find the existing folder instead? As far as I know this list is the only possible search options.
I hope you are aware of the supported scopes.
I think there are 2 things that cause your problem and you will have to re-think your app's logic.
First, GDAA (unlike the REST Api), introduces some latency, so the file/folder may not exist on the Drive for awhile, even if you got your DriveId (see this).
Second, the fact that you use TITLE as an indicator of existence does not work in the GooDrive universe, since TITLE is not unique (you already know that).
I would recommend this approach:
when your (GDAA based) app creates a file/folder, wait until you get it's ResourceId. That confirms it's existence (again here).
always check for the existence of a file/folder in the Drive using it's ResourceId (turned into DriveId)
Let's say I use the Google Drive API to select a file that I want to open. I have this code to do so:
// Getting the drive ID for the file
DriveId driveId = (DriveId) data
.getParcelableExtra(OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
// Getting the selected file
DriveFile googleDriveFile = Drive.DriveApi.getFile(googleApiClient,
driveId);
googleDriveFile.open(googleApiClient, DriveFile.MODE_READ_ONLY,
null).setResultCallback(
new ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
if (result.getStatus().isSuccess()) {
Is there any way for me to get the file name of this file? (Not the drive ID, but its actual name?)
I'm trying to validate the chosen file (by checking its type, which is in the name), and I can't think of a way to do this other than get the name. The type is .cblite, a Couchbase Lite database file. Normally I'd just filter the Drive picker by MIME type, but .cblite (to my knowledge) isn't one of those options. Instead I'm trying to validate by file name.
Is there a way to do this? (Or is there a way to filter MIME types by miscellaneous/unidentified types?)
Yes, once you have DriveId, you can get metadata. And one of the metadata fields is getTitle() which will get you the file / folder name. Look at this code snippet:
DriveFile googleDriveFile = Drive.DriveApi.getFile(googleApiClient, driveId);
MetadataResult mdRslt = googleDriveFile .getMetadata(googleApiClient).await();
if (mdRslt != null && mdRslt.getStatus().isSuccess()) {
mdRslt.getMetadata().getTitle();
}
The 'await' flavor here is used for convenience, it must be run off-ui thread. Or just turn it into a callback style.
Good Luck
I have yet another hurdle to climb with my GOOGLE DRIVE SDK Android App. I am uploading scanned images with tightly controlled index fields - user defined 'tags' from local dictionary. For instance XXX.JPG has index words "car" + "insurance". Here is a simplified code snippet:
...
body.setTitle("XXX.JPG");
body.setDescription("car, insurance");
body.setIndexableText(new IndexableText().setText("car insurance"));
body.setMimeType("image/jpeg");
body.setParents(Arrays.asList(new ParentReference().setId(...)));
FileContent cont = new FileContent("image/jpeg", new java.io.File(fullPath("xxx.jpg")));
File gooFl = _svc.files().insert(body, cont).execute();
...
Again, everything works great, except when I start a search, I get results that apparently come from some OCR post process, thus rendering my system's DICTIONARY unusable. I assume I can use a custom MIME type, but then the JPEG images become invisible for users who use standard GOOGLE DRIVE application (local, browser-based ... ). So the question is: Can I upload MIME "image/jpeg" files with custom indexes (either Indexable, or Description fields) but stop GOOGLE from OCR-ing my files and adding indexes I did not intend to have?
Just to be more specific, I search for "car insurance" and instead of my 3 files I indexed this way, I get unmanageable pile of other results (JPEG scanned documents) that had "car" and "insurance" somewhere in them. Not what my app wants.
Thank you in advance, sean
...
Based on Burcu's advise below, I modified my code to something that looks like this (stripped to bare bones):
// define meta-data
File body = new File();
body.setTitle("xxx.jpg");
body.setDescription(tags);
body.setIndexableText(new IndexableText().setText(tags));
body.setMimeType("image/jpeg");
body.setParents(Arrays.asList(new ParentReference().setId(_ymID)));
body.setModifiedDate(DateTime.parseRfc3339(ymdGOO));
FileContent cont =
new FileContent("image/jpeg",new java.io.File(fullPath("xxx.jpg")));
String sID = findOnGOO(driveSvc, body.getTitle());
// file not found on gooDrive, upload and fix the date
if (sID == null) {
driveSvc.files().insert(body, cont).setOcr(false).execute();
driveSvc.files().patch(gooFl.getId(), body).setOcr(false).setSetModifiedDate(true).execute();
// file found on gooDrive - modify metadata and/or body
} else {
// modify content + metadata
if (contentModified) {
driveSvc.files().update(sID, body, cont).setOcr(false).setSetModifiedDate(true).execute();
// only metadata (tags,...)
} else {
driveSvc.files().patch(sID, body).setOcr(false).setSetModifiedDate(true).execute();
}
}
...
It is a block that uploads or modifies a Google Drive file. The two non-standard operations are:
1/ resetting the file's 'modified' date in order to force the date of file creation - tested, works OK
2/ stopping the OCR process that interferes with my apps indexing scheme - will test shortly and update here
For the sake of simplicity, I did not include the implementation of "findInGOO()" method. It is quite simple 2-liner and I can supply it upon request
sean
On insertion, set the ocr parameter to false:
service.files().update(body, content).setOcr(false).execute();
all you guys who know things I don't :-)
I've run into this problem that may not be actually a problem, only a revelation that I don't know what I'm doing. AGAIN!
I'm uploading a JPEG with some description and indexable keywords. Works like a charm. But I can't figure out how to add/modify meta data later, without creating another instance of the file. So, when I add a picture of my dog with description "dog", I end up with what I wanted. But if I try to modify the metadata by either using:
gooFl = drvSvc.files().insert(meta).execute();
or
gooFl = drvSvc.files().insert(meta,null).execute();
I end up with a new file (of the same name) on GOOGLE Drive.
See the code snippet below:
File meta = new File();
meta.setTitle("PicOfMyDog.jpg");
meta.setMimeType("image/jpeg");
meta.setParents(Arrays.asList(new ParentReference().setId(ymID)));
File gooFl = null;
if (bNewJPG == true) {
meta.setDescription("dog");
meta.setIndexableText(new IndexableText().setText("dog"));
gooFl = drvSvc.files().insert(meta,
new FileContent("image/jpeg", new java.io.File(fullPath("PicOfMyDog.jpg"))))
.execute();
} else {
meta.setDescription("dick");
meta.setIndexableText(new IndexableText().setText("dick"));
// gooFl = drvSvc.files().insert(meta).execute();
gooFl = drvSvc.files().insert(meta,null).execute();
}
if (gooFl != null)
Log.d("atn", "success " + gooFl.getTitle());
It is the "else" branch I'm asking about. First file one has meatadata "dog", second "dick".
So, what's the solution. Do I delete the previous instance (and how)? Is there another syntax / method I don't know about?
thank you, sean
If you need to modify the metadata, use files.patch.
drvSvc.files().patch(id, meta).execute();
In cases you need both modify the metadata and the file contents, use files.update.
drvSvc.files().update(id, meta, content).execute();
Insertions make POST requests that always create a new resource.
You need to use Files.Patch if you want to update only Metadata. files().insert always creates a new file.
A full list of File commands and what operations you need to use can be found in the API Reference
This question would be related mostly to Android, however it is a little more general.
I can upload and download files using getFile and such API calls, however, I am trying to access a directory which exists already on Dropbox and list it's content.
Using the API, I would like to be able to reference the directory at path '/path/to/dir/' and list all the Entry objects inside it using Entry.contents.
I've tried this and it doesn't work:
Entry dir = new Entry();
dir.path = "/path/to/dir";
Log.d(TAG, "isDir ? " + Boolean.toString(dir.isDir));
for (Entry entry : dir.contents) {
Log.d(TAG, entry.filename());
}
The directory is not empty. isDir returns false and no filenames are printed.
Is there a way to do this, or do I need to use the search method?
All I want is the list of files in an existing directory.
Thanks a lot
This can be done with the metadata function:
String path2Dir = "path/to/dir";
Entry dir = mDropboxApiInstance.metadata(path2Dir, null, true, null);
List<Entry> contents = dir.contents;
for (Entry dropboxFile : contents){
// do stuff with remote file's data
}