I have the following code for getting DriveContents of a file in Google Drive. I'm able to import and get DriveContents of MS Word, text files, etc but when the file is native to Google (Google Doc, Google Sheets, etc.) i'm not able to get the contents. My code is below:
selectedFile.open(getGoogleApiClient(), DriveFile.MODE_READ_ONLY, null).setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
public void onResult(DriveApi.DriveContentsResult result) {
try {
if (!result.getStatus().isSuccess()) {
// display an error saying file can't be opened
Log.e(TAG, "Could not get file contents");
return;
}
// DriveContents object contains pointers
// to the actual byte stream
DriveContents contents = result.getDriveContents();
BufferedReader reader = new BufferedReader(new InputStreamReader(contents.getInputStream()));
StringBuilder builder = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
builder.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
String contentsAsString = builder.toString();
contents.discard(getGoogleApiClient());
Log.i(TAG, contentsAsString);
} catch (Exception e) {
e.printStackTrace();
}
}
});
Whenever I get a Google format file, it simply returns a result that is not a success and shows the error in my logs. How can I get the file contents of those files as well? Is there something special i'm supposed to do?
I'm reading the following documentation:
https://developers.google.com/drive/android/files
Not sure if this is the best solution but I did it the following way. I check in the metadata if it's a Google format (doc, sheets, etc) and if it is, I have an AsyncTask that does the below:
// accountName is the email address the user used when choosing which account
String scope = "oauth2:https://www.googleapis.com/auth/drive.file";
token = GoogleAuthUtil.getTokenWithNotification(fragment.getActivity(), accountName, scope, null);
After doing the above, you can get the file using the API:
https://developers.google.com/drive/web/manage-downloads
The token from the above gives the Authentication header token on the downloading. We can export the file as docx, pdf, etc and download it that way.
Related
How to get media files and their details with Dropbox API v2 for Android(Java)? I have gone through the documentation for the FileMetadata , but I couldn't find the methods to get file details like file type(e.g. music, video, photo, text, ...) , file's URL and thumbnail.
this is my folders and files list Asyntask:
//login
DbxClientV2 client = DropboxClient.getClient(accessToken);
// Get files and folder metadata from root directory
String path = "";
TreeMap<String, Metadata> children = new TreeMap<>();
try {
try {
result = client.files().listFolder(path);
arrayList = new ArrayList<>();
//arrayList.add("/");
while (true) {
int i = 0;
for (Metadata md : result.getEntries()) {
if (md instanceof DeletedMetadata) {
children.remove(md.getPathLower());
} else {
String fileOrFolder = md.getPathLower();
children.put(fileOrFolder, md);
//if (!fileOrFolder.contains("."))//is a file
arrayList.add(fileOrFolder);
if (md instanceof FileMetadata) {
FileMetadata file = (FileMetadata) md;
//I need something like file.mineType, file.url, file.thumbnail
file.getParentSharedFolderId();
file.getName();
file.getPathLower();
file.getPathDisplay();
file.getClientModified();
file.getServerModified();
file.getSize();//in bytes
MediaInfo mInfo = file.getMediaInfo();//Additional information if the file is a photo or video, null if not present
MediaInfo.Tag tag;
if (mInfo != null) {
tag = mInfo.tag();}
}
}
i++;
}
if (!result.getHasMore()) break;
try {
result = client.files().listFolderContinue(result.getCursor());//what is this for ?
} catch (ListFolderContinueErrorException ex) {
ex.printStackTrace();
}
}
} catch (ListFolderErrorException ex) {
ex.printStackTrace();
}
} catch (DbxException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return result;
If you want media information, you should use listFolderBuilder to get a ListFolderBuilder object. You can use call .withIncludeMediaInfo(true) to set the parameter for media information, and then .start() to make the API call. The results will then have the media information set, where available.
Dropbox API v2 doesn't offer mime types, but you can keep your own file extension to mime type mapping as desired.
To get an existing link for a file, use listSharedLinks. To create a new one, use createSharedLinkWithSettings.
To get a thumbnail for a file, use getThumbnail.
I know that there is library available for uploading the file using Azure Storage. I have refer this for same.
But, they have not give information for how to use SAS with that. I have account name, and sas url for access and upload file there. But I don't know how to use that for uploading file.
If I use above mention library it shows me invalid storage connection string because I am not passing the key in it (Which is not required with sas). So I am confused how I can upload file.
I have refer this documentation also for uploading file using sas. but not getting proper steps to do this. They have made demo for their windows app. I want to have that in android with use of sas.
Update
I have try with below code with reference to the console app made by Azure to check and access SAS.
try {
//Try performing container operations with the SAS provided.
//Return a reference to the container using the SAS URI.
//CloudBlockBlob blob = new CloudBlockBlob(new StorageUri(new URI(sas)));
String[] str = userId.split(":");
String blobUri = "https://myStorageAccountName.blob.core.windows.net/image/" + str[1] + "/story/" + storyId + "/image1.jpg" + sas.toString().replaceAll("\"","");
Log.d(TAG,"Result:: blobUrl 1 : "+blobUri);
CloudBlobContainer container = new CloudBlobContainer(new URI(blobUri));
Log.d(TAG,"Result:: blobUrl 2 : "+blobUri);
CloudBlockBlob blob = container.getBlockBlobReference("image1.jpg");
String filePath = postData.get(0).getUrl().toString();
/*File source = new File(getRealPathFromURI(getApplicationContext(),Uri.parse(filePath))); // File path
blob.upload(new FileInputStream(source), source.length());*/
Log.d(TAG,"Result:: blobUrl 3 : "+blobUri);
//blob.upload(new FileInputStream(source), source.length());
//blob.uploadText("Hello this is testing..."); // Upload text file
Log.d(TAG, "Result:: blobUrl 4 : " + blobUri);
Log.d(TAG, "Write operation succeeded for SAS " + sas);
response = "success";
//Console.WriteLine();
} catch (StorageException e) {
Log.d(TAG, "Write operation failed for SAS " + sas);
Log.d(TAG, "Additional error information: " + e.getMessage());
response = e.getMessage();
} catch (FileNotFoundException e) {
e.printStackTrace();
response = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
response = e.getMessage();
} catch (URISyntaxException e) {
e.printStackTrace();
response = e.getMessage();
} catch (Exception e){
e.printStackTrace();
response = e.getMessage();
}
Now, when I upload text only it says me below error
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
Now, my requirement is to upload Image file. So when I uncomment code for uploading image file it is not giving me any error but even not uploading image file.
#kumar kundal
The mechanism that you have explained is completely right.
Below is the more detailed answer about uploading profile image to the Azure Server.
First create SAS url to upload Image(or any file) to blob storage:
String sasUrl = "";
// mClient is the MobileServiceClient
ListenableFuture<JsonElement> result = mClient.invokeApi(SOME_URL_CREATED_TO_MAKE_SAS, null, "GET", null);
Futures.addCallback(result, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement result) {
// here you will get SAS url from server
sasUrl = result; // You need to parse it as per your response
}
#Override
public void onFailure(Throwable t) {
}
});
Now, you have sasURL with you. That will be something like the below string:
sv=2015-04-05&ss=bf&srt=s&st=2015-04-29T22%3A18%3A26Z&se=2015-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=F%6GRVAZ5Cdj2Pw4tgU7IlSTkWgn7bUkkAg8P6HESXwmf%4B
Now, you need to append the sas url with your uploading url. See below code in which I have appended the SAS url with my uploading request.
try {
File source = new File(filePath); // File path
String extantion = source.getAbsolutePath().substring(source.getAbsolutePath().lastIndexOf("."));
// create unique number to identify the image/file.
// you can also specify some name to image/file
String uniqueID = "image_"+ UUID.randomUUID().toString().replace("-", "")+extantion;
String blobUri = MY_URL_TO_UPLOAD_PROFILE_IMAGE + sas.replaceAll("\"","");
StorageUri storage = new StorageUri(URI.create(blobUri));
CloudBlobClient blobCLient = new CloudBlobClient(storage);
CloudBlobContainer container = blobCLient.getContainerReference("");
CloudBlockBlob blob = container.getBlockBlobReference(uniqueID);
BlobOutputStream blobOutputStream = blob.openOutputStream();
byte[] buffer = fileToByteConverter(source);
ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);
int next = inputStream.read();
while (next != -1) {
blobOutputStream.write(next);
next = inputStream.read();
}
blobOutputStream.close();
// YOUR IMAGE/FILE GET UPLOADED HERE
// IF YOU HAVE FOLLOW DOCUMENT, YOU WILL RECEIVE IMAGE/FILE URL HERE
} catch (StorageException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
I hope this information help you lot for uploading the file using blob storage.
Please let me know if you have any doubt apart from this. I can help in that.
Uploading a pic to BLOB storage . I got it after searching for hours .Take a look :-
Uploading the photo image is a multistep process:
First you take a photo, and insert a TodoItem row into the SQL database that contains new meta-data fields used by Azure Storage.
A new mobile service SQL insert script asks Azure Storage for a Shared Access Signature (SAS).
That script returns the SAS and a URI for the blob to the client.
The client uploads the photo, using the SAS and blob URI.
So what is a SAS?
It's not safe to store the credentials needed to upload data to the Azure Storage service inside your client app. Instead, you store these credentials in your mobile service and use them to generate a Shared Access Signature (SAS) that grants permission to upload a new image. The SAS, a credential with a 5 minute expiration, is returned securely by Mobile Services to the client app. The app then uses this temporary credential to upload the image.
for further queries and detail analysis. Visit this official documentation https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-upload-data-blob-storage/
I am developing android app which share the content to friends using Google Drive.So is it possible to share file programatically using google drive in android?
Yes that is possible, if you don't include a standard share functionality in your app but want to upload specifically to Google Drive you are going to have to use the Google Drive APIs. It's a little more complex so I'm not going to post a full solution but I will show you the important parts. I suggest you take a look at one of these example projects:
Google Docs Upload Example
Google Drive Quickstart Example
But anyway here are the important parts:
First you have to create an API client which will look something like this:
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this);
// Add Drive API
mGoogleApiClient.addApi(Drive.API);
// Set Scope
mGoogleApiClient.addScope(Drive.SCOPE_FILE);
// Add required callbacks
mGoogleApiClient.addConnectionCallbacks(this);
mGoogleApiClient.addOnConnectionFailedListener(this);
// Build client
mGoogleApiClient.build();
And with this API client you can upload/download/move/copy/delete files and folders etc.
Uploading a file would look something like this:
Drive.DriveApi.newContents(mGoogleApiClient).setResultCallback(new ResultCallback<ContentsResult>() {
#Override
public void onResult(ContentsResult result) {
// Check for success
if (!result.getStatus().isSuccess()) {
return;
}
// Upload file
OutputStream outputStream = result.getContents().getOutputStream();
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
try {
outputStream.write(bitmapStream.toByteArray());
} catch (IOException e1) {
Log.i(TAG, "Unable to write file contents.", e);
}
// Set meta data
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder();
metadataChangeSet.setMimeType("image/jpeg");
metadataChangeSet.setTitle("Android Photo.png");
metadataChangeSet.build();
// Create file chooser
IntentSender intentSender = Drive.DriveApi.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialContents(result.getContents())
.build(mGoogleApiClient);
// Show file chooser
try {
startIntentSenderForResult(intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.i(TAG, "Failed to launch file chooser.", e);
}
}
});
Google Drive Sharing is accomplished using Google Drive API for Java as follows
googleDrive.permissions.insert(Permission);
Permission newPermission = new Permission();
newPermission.setValue(emailvalue);
newPermission.setType(type);
newPermission.setRole(role);
try {
service.permissions().insert(fid, newPermission).execute();
showToast("Done Shared successfully!!!!!!");
} catch (IOException e) {
System.out.println("An error occurred: " + e);
}
Is there any possible way to read the text from a file on Google Drive and store it in a String? This file may contain images as well. I was looking into the Google Drive SDK but they only allow us to download the entire file. How should I go about doing this?
From Files.get() documentation.
private static InputStream downloadFile(Drive service, File file) {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
HttpResponse resp =
service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl()))
.execute();
return resp.getContent();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
You can convert InputStream to String or File as you want.
I can download the original file from Google Drive by using the following code :
public static InputStream downloadFile(Drive service, File file)
throws IOException {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
HttpResponse resp = service.getRequestFactory()
.buildGetRequest(new GenericUrl(file.getDownloadUrl()))
.execute();
return resp.getContent();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
But it looks like the connection really low when downloading many files to add into the grid view.
Therefore, I need to list thumb nail instead of original file as it will be better for the connection.
Please help me how?
Use File.getThumbnail method to get the thumbnail or File.getIconLink to get the icon link.