Create folder in drive with rest v2 in android app - android

I am trying to create a folder in Drive and using below
String folderName = UrlConstants.APP_NAME + "_dont_delete";
File fileMetadata = new File();
fileMetadata.setTitle(folderName);
fileMetadata.setMimeType("application/vnd.google-apps.folder");
File file = null;
try {
file = driveService.files().insert(fileMetadata)
.setFields("id")
.execute();
} catch (IOException e) {
e.printStackTrace();
}
However it is not creating folder in drive , instead it is creating a document named 'Untitled'.
Thanks in advance.

In Drive API for Android, note that working with folders has slight differences when compared to Google Drive API. Folders in the Drive API for Android are specialized resources within metadata and a DriveId and to create a folder, call DriveFolder.createFolder for the root folder. Then, pass the metadata containing the title and other attributes to set the values for the folder.
For a full working example, see the CreateFolderActivity sample in the Google Drive Android API Demos app.

The CloudRail SDK allows you to do that in a pretty simple way:
GoogleDrive service = new GoogleDrive(
this,
"[Google Drive Client Identifier]",
"[Google Drive Client Secret]",
"http://localhost:12345/auth",
"someState"
);
service.createFolder(
"/myFolder"
);

Related

How do you instantiate a DriveId/DriveFolder using the Google Drive Android API

I am sure this is an easy question to answer, but I've been unable to find out how to instancate a DriveId and/or DriveFolder with the Drive resource id using the Google Drive Android API v 12.
I have read the Google Drive Android API documentation and have managed to create a file on my Google Drive from my Android app in the root folder, but now I want to create the file in a specific folder and I'm unsure how to go about this.
A lot of the code I've seen (such as this Stackoverflow answer) uses the deprecated Google DriveApi to get a DriveId from the resource id of the folder.
I have tried to use the DriveId method decodeFromString but when I ran the following code, I get an error saying the DriveId is invalid:
String googleDriveFolderId = "16TwNeDF9_inOK4X5AaGnVMNycNVxxMtd";
DriveFolder projectFolder = DriveId.decodeFromString(googleDriveFolderId).asDriveFolder();
What am I doing wrong?
Create a folder
To create a folder, call DriveResourceClient.createFolder(), passing
in a reference to the parent folder and the metadata object containing
the title and other attributes to set the values for the folder.
The following code sample demonstrates how to create a new folder in
the root folder:
private void createFolder() {
getDriveResourceClient()
.getRootFolder()
.continueWithTask(task -> {
DriveFolder parentFolder = task.getResult();
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("New folder")
.setMimeType(DriveFolder.MIME_TYPE)
.setStarred(true)
.build();
return getDriveResourceClient().createFolder(parentFolder, changeSet);
})
.addOnSuccessListener(this,
driveFolder -> {
showMessage(getString(R.string.file_created,
driveFolder.getDriveId().encodeToString()));
finish();
})
.addOnFailureListener(this, e -> {
Log.e(TAG, "Unable to create file", e);
showMessage(getString(R.string.file_create_error));
finish();
});
}
on Success, try calling getDriveId().
What I am trying to do is simply not possible using the Google Drive Android API. I guess this is because the DriveResource does not get a resourceId until it has been uploaded.
See this SO answer which discusses how you aren't able to access any file or folder that isn't created by your app. I tested this and it's true - when I run a Query for a folder that I created manually in my root folder I cannot find it, but when I create a folder with the same name from my app, I get 1 query result.
Also see this SO thread which says you need to use another Google Drive API (they suggested the REST API) to be able to specify a folder programmatically (without using a popup where the user selects a folder). Unfortunately that won't work for me because I am building an offline app - precisely the reason I chose to work with Google Drive.
I ended up making a compromise and working with the root folder - luckily for me my project is to be used with very specific Google accounts so I am able to do this. My code looks something like this:
private void createFile() {
// [START create_file]
final Task<DriveFolder> rootFolderTask = getDriveResourceClient().getRootFolder();
final Task<DriveContents> createContentsTask = getDriveResourceClient().createContents();
Tasks.whenAll(rootFolderTask, createContentsTask)
.continueWithTask(task -> {
DriveFolder parent = rootFolderTask.getResult();
DriveContents contents = createContentsTask.getResult();
OutputStream outputStream = contents.getOutputStream();
try (Writer writer = new OutputStreamWriter(outputStream)) {
writer.write("Hello World!");
}
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("HelloWorld.txt")
.setMimeType("text/plain")
.setStarred(true)
.build();
return getDriveResourceClient().createFile(parent, changeSet, contents);
})
.addOnSuccessListener(this,
driveFile -> {
showMessage(getString(R.string.file_created,
driveFile.getDriveId().encodeToString()));
finish();
})
.addOnFailureListener(this, e -> {
Log.e(TAG, "Unable to create file", e);
showMessage(getString(R.string.file_create_error));
finish();
});
// [END create_file]
}
If you can't compromise and use the root folder, I would suggest that you create a folder from within your app into the root folder and then save the string representation of the DriveId which you can use the next time you run the code. I haven't yet tested if the folder could be used by another instance of the app running on a different device, but I would hope so (fingers crossed).
Another option is displaying a popup so the user can select the folder manually. See this demo example.

Accessing public Google Drive folder from Android app without authenticating

I'd like for my app to be able to read from a pre-defined shared public Google Drive folder without the user having to log in or choose a Google account.
Background / Environment
Using my desktop browser, I have created a public folder on my Google Drive that is set up to be public. Anyone with the link may access (read) the drive, so no authorization is required:
In my Android Studio project, I have gone into File > Project Structure > Dependencies and added com.google.android.gms:play-services-drive:10.2.0
I now have the ability to create a new GoogleApiClient.Builder().
Question
I have looked at various examples, but in most cases, the drive has been created by the Android application. This is not the situation I'm trying to manage.
This question is about accessing a drive that has been made public using the "folder ID" or whatever you call 0B6X74x23H.... that was assigned when the folder was originally shared and made public.
I have examined the demo code provided by Google, but that, presumably, is not for a public folder because it says:
...need to register an OAuth 2.0 client
At a minimum, I could drive the process by using http-client, going to the sharing link https://drive.google.com/drive/folders/0B6X74x23Hx7DNE13M0ZIbVI....?usp=sharing with no authentication and not need to jump through hoops. But of course, it would be cleaner to use a defined API and simply specify the public shared folder in order to list the contents and, if needed, download the files from the public folder.
When I try this code:
Scope publicFolder = new Scope(EXISTING_FOLDER_ID);
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
.addApi(Drive.API)
.addScope(publicFolder)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
This method fires:
GoogleApiClient.OnConnectionFailedListener.onConnectionFailed()
The result contains statusCode=SIGN_IN_REQUIRED. But of course, sign-in is NOT required for a folder that's public.
Here is a workaround with Jsoup
implementation 'org.jsoup:jsoup:1.11.3'
val url = "https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxx" // shared folder link
val doc = Jsoup.connect(url).get()
doc.outputSettings().prettyPrint(false)
val files = doc.select("div.WYuW0e")
for (file in files){
val fileName = file.text()
val fileID = file.attr("data-id")
val downloadLink = "https://drive.google.com/uc?export=download&id=$fileID"
//the downloadLink may open a 'Google Drive can't scan this file for viruses' page
// below we check for the new link
val doc2 = Jsoup.connect(downloadLink).get()
doc2.outputSettings().prettyPrint(false)
val elem = doc2.select("[id='uc-download-link']")
val newLink = if (elem.size != 0){
"https://drive.google.com" + elem.first().attr("href")
} else {
downloadLink
}
}

Why can't we use file name to query excel file on Google Drive?

I have an app where I want to query excel on Google Drive as and when a new excel with 'a fixed file name format' is added to the drive. Why does Google not allow us to query the file by filename instead of file id?
For example my app queries a file names August2016.xls and next month it should automatically look for a new file with file name September2016.xls. Currently this is not possible because the application should have the file id. Am I missing something? Is it possible too query a Google Drive file by file name?
The "getFilesByName" function of the "Folder" class should work:
var theXLSFile = null;
// the id of the folder that has the excel files.
var FOLDER_ID = "xxxxxxxxx";
// alternatively, could use "getFoldersByName".
var folder = DriveApp.getFolderById(folderId);
var FILE_NAME = "September2016.xls";
var files = folder.getFilesByName(FILE_NAME);
if (files.length > 0)
theXLSFile = files[0];
Reference:
https://developers.google.com/apps-script/reference/drive/folder#getFilesByName(String)
Thanks #opowell your answer helped me find the correct Google API. I am doing android development and here are the links to get started on Google Drive API & getFile function.
1) https://developers.google.com/drive/android/get-started
2) Querying for Files using com.google.android.gms.drive.query package - https://developers.google.com/drive/android/queries
3) Google sample- https://github.com/googledrive/android-demos/

Adding an already created folder to Google Drive in Android

I want use google drive in my android app to backup folders that contain text, image and video files.
My problem is that while I can upload each text, image and video file separately using the Drive API, I can't see a way to upload entire folders at once so that the organisation remains intact.
The organisation of the folders is as follows:
app>Projects>notes>photos/text/video
Ideally I would like to upload the folder "app" and along with all of its contents while keeping the parent/child structure.
Are you using Google Drive Api for Android or the REST Api ?
If you are using the REST API you can create a folder like this :
private String createFolder() throws IOException {
File fileMetadata = new File();
fileMetadata.setName("FOLDER_NAME");
fileMetadata.setMimeType("application/vnd.google-apps.folder");
File file = mService.files().create(fileMetadata)
.setFields("id")
.execute();
String Folderid = file.getId();
And then with the file id you do this :
File nFile= new File();
nFile.setName("FILE_NAME");
nFile.setParents(Collections.singletonList(Folderid));
File file = mService.nFile().create(fileMetadata).execute();
The setParents is used to create the file INSIDE the parent which is the folder just created in this example.

Finding a saved file from my app in the Android file system

I've created a new file using XmlSerializer and StreamWriter to persist data. From the test I did with my app, storing and restoring data using this method is working. Just for curiosity, I've tried to find the file created in the Android File System, without success. I've tried to find it with an Android app (ES File Explorer) and a desktop app (on Mac, Android File Transfer). In both case, I was unable to find the created file.
XmlSerializer xmlSerializer = new XmlSerializer (typeof(GAData));
TextWriter writer = new StreamWriter (FilePath);
xmlSerializer.Serialize (writer, this);
writer.Close ();
Console.WriteLine ("Data saved");
Where FilePath is define here :
// Determining the path
var documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
FilePath = Path.Combine (documentsPath, "AppData.txt");
Console.WriteLine (Path.GetFullPath (FilePath));
The last Console.WriteLine is logging : /data/data/com.domain.myapp/files/AppData.txt
The exact same code is working like a charm on iOS, and I can see the file in the File System using an app on my Mac. Why can I find it in the Android File System? Or, where is it saved if it's somewhere else?
/data/data/com.domain.myapp/files/AppData.txt
That is private internal memory. Private as only your app has access.
Your app can reach it using getFilesDir().
Other app like ES File Explorer have no access.
You should be using FilesDir from the ContextWrapper
Path.Combine(FilesDir.Path , "MyFile.text");
Example, copies a file that is in the assets folder to the local file system
if (!File.Exists(Path.Combine(FilesDir.Path , "myFile.Text")))
{
using (var asset = Assets.Open("TextToCopyTo.txt"))
{
using (var dest = File.Create(Path.Combine(FilesDir.Path , "MyFile.text")))
{
asset.CopyTo(dest);
}
}
}

Categories

Resources