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);
}
Related
I am trying to download a file using the Box android SDK. The problem seems to be with the destinationFile parameter. The box.com call is checking whether the destinationFile exists - but why? I get java.io.FileNotFoundException.
destinationFile = new File(getFilesDir(), "myfile.crs");
// destinationFile = new File(getFilesDir(),"/");
try {
BoxDownload fileDownload = mFileApi.getDownloadRequest(destinationFile, fileID)
// Optional: Set a listener to track download progress.
.setProgressListener(new ProgressListener() {
#Override
public void onProgressChanged(long numBytes, long totalBytes) {
// Update a progress bar, etc.
}
})
.send();
} catch (BoxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
To do All the checks
Log.i(getClass().getName(),"Does File exists:"+(destinationFile.exists()?"Yes":"No"));
Log.i(getClass().getName(),"Is it A file:"+(destinationFile.isFile()?"Yes":"No"));
Log.i(getClass().getName(),"Is it Writable:"+(destinationFile.canWrite()?"Yes":"No"));
Log.i(getClass().getName(),"Is it A Readable:"+(destinationFile.canRead()?"Yes":"No"));
Log.i(getClass().getName(),"Path:"+destinationFile.getAbsolutePath());
you are most likely to found file does not exists then do this before using it.
if(!destinationFile.exists()){
try {
destinationFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
The answer was to create a new File. Then call .createNewFile() on the File instance. Then call all of the code I posted except to put run it in the background. That's why I was asking here - I was wondering if I was doing something incorrect for Android and I was. Box networking operations need to be done on a thread.
Too bad they never show this for downloading a file. Too bad there's not one example of downloading a file with the Android DSK on the web.
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.
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/
How to load a image from the play store using the package ID and not from local installed apps. For example when the app is not installed but you need to fetch the icon of the app.
There is an un-official API for the Playstore
Something like this might work:
GetImageRequest imgReq = GetImageRequest.newBuilder().setAppId("-7934792861962808905")
.setImageUsage(AppImageUsage.ICON)
.setImageId("1")
.build();
session.append(imgReq, new Callback<GetImageResponse>() {
#Override
public void onResult(ResponseContext context, GetImageResponse response) {
try {
FileOutputStream fos = new FileOutputStream("icon.png");
fos.write(response.getImageData().toByteArray());
fos.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
});
session.flush();
The important part is the .setImageUsage(AppImageUsage.ICON) you could also get screenshots with this method, setting .setImageUsage(AppImageUsage.SCREENSHOT)
I have spend more then one day but not getting any working solution which provide me uploading / downloading files to Google Drive.
I have tried Google Play Service but i didn't find any method which upload / download files.
I try Google Client libraries but there are some method are not resolved.
such as :
service.files().insert(body, mediaContent).execute();
errors: The method execute() is undefined for the type Drive.Files.Insert
I can upload image through below code but this is Google Drive file up loader. I can only upload one only one file at a time.
mFile = new java.io.File(fileList.get(i));
Log.i(TAG, "Creating new contents.");
Drive.DriveApi.newContents(mGoogleApiClient).addResultCallback(
new OnNewContentsCallback() {
#Override
public void onNewContents(ContentsResult result) {
if (!result.getStatus().isSuccess()) {
Log.i(TAG, "Failed to create new contents.");
return;
}
Log.i(TAG, "New contents created.");
OutputStream outputStream = result
.getContents().getOutputStream();
byte[] byteStream = new byte[(int) mFile
.length()];
try {
outputStream.write(byteStream);
} catch (IOException e1) {
Log.i(TAG, "Unable to write file contents.");
}
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setMimeType("image/jpeg")
.setMimeType("text/html")
.setTitle("Android Photo.png").build();
// Create an intent for the file chooser, and
// start it.
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialContents(
result.getContents())
.build(mGoogleApiClient);
try {
mActivity.startIntentSenderForResult(
intentSender, REQUEST_CODE_CREATOR,
null, 0, 0, 0);
publishProgress(1);
} catch (SendIntentException e) {
Log.i(TAG, "Failed to launch file chooser.");
publishProgress(0);
}
}
});
But still fighting for downloading a file.
I got the solution. We should never use Android API for complete Drive access. We should work on pure java code as Google also said that to access Drive for broad access use java libraries.
I remove all the code related to Google play services. I am now using completely using java and easily upload, delete, edit, download all whatever I want.
One more thing Google doc doesn't provide a detail description about Google Drive in respective to android api while when work on java libraries you can get already created methods and more.
I am not giving any code but saying that for me or for others who interested in Drive complete access use Java based codes.
Upload File to Google Drive
Drive.Files.Insert insert;
try {
final java.io.File uploadFile = new java.io.File(filePath);
File fileMetadata = new File();
ParentReference newParent = new ParentReference();
newParent.setId(upload_folder_ID);
fileMetadata.setParents(
Arrays.asList(newParent));
fileMetadata.setTitle(fileName);
InputStreamContent mediaContent = new InputStreamContent(MIMEType, new BufferedInputStream(
new FileInputStream(uploadFile) {
#Override
public int read(byte[] buffer,
int byteOffset, int byteCount)
throws IOException {
// TODO Auto-generated method stub
Log.i("chauster","progress = "+byteCount);
return super.read(buffer, byteOffset, byteCount);
}
}));
mediaContent.setLength(uploadFile.length());
insert = service.files().insert(fileMetadata, mediaContent);
MediaHttpUploader uploader = insert.getMediaHttpUploader();
FileUploadProgressListener listener = new FileUploadProgressListener();
uploader.setProgressListener(listener);
uploader.setDirectUploadEnabled(true);
insert.execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public class FileUploadProgressListener implements MediaHttpUploaderProgressListener {
#SuppressWarnings("incomplete-switch")
#Override
public void progressChanged(MediaHttpUploader uploader) throws IOException {
switch (uploader.getUploadState()) {
case INITIATION_STARTED:
break;
case INITIATION_COMPLETE:
break;
case MEDIA_IN_PROGRESS:
break;
case MEDIA_COMPLETE:
break;
}
}
}
and Download file from google drive look this
Google SDK is now android friendly. There is a full-access scope which gives you access to listing and reading all the drive files and which can be used in Android apps easily since our newer client library is Android-friendly! I also recommend watching this talk from Google IO which is explains how to integrate mobile apps with Drive
The library makes authentication easier
/** Authorizes the installed application to access user's protected data. */
private static Credential authorize() throws Exception {
// load client secrets
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new InputStreamReader(CalendarSample.class.getResourceAsStream("/client_secrets.json")));
// set up authorization code flow
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY, clientSecrets,
Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(dataStoreFactory)
.build();
// authorize
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
The library runs on Google App Engine
Media Upload
class CustomProgressListener implements MediaHttpUploaderProgressListener {
public void progressChanged(MediaHttpUploader uploader) throws IOException {
switch (uploader.getUploadState()) {
case INITIATION_STARTED:
System.out.println("Initiation has started!");
break;
case INITIATION_COMPLETE:
System.out.println("Initiation is complete!");
break;
case MEDIA_IN_PROGRESS:
System.out.println(uploader.getProgress());
break;
case MEDIA_COMPLETE:
System.out.println("Upload is complete!");
}
}
}
File mediaFile = new File("/tmp/driveFile.jpg");
InputStreamContent mediaContent =
new InputStreamContent("image/jpeg",
new BufferedInputStream(new FileInputStream(mediaFile)));
mediaContent.setLength(mediaFile.length());
Drive.Files.Insert request = drive.files().insert(fileMetadata, mediaContent);
request.getMediaHttpUploader().setProgressListener(new CustomProgressListener());
request.execute();
You can also use the resumable media upload feature without the service-specific generated libraries. Here is an example:
File mediaFile = new File("/tmp/Test.jpg");
InputStreamContent mediaContent =
new InputStreamContent("image/jpeg",
new BufferedInputStream(new FileInputStream(mediaFile)));
mediaContent.setLength(mediaFile.length());
MediaHttpUploader uploader = new MediaHttpUploader(mediaContent, transport, httpRequestInitializer);
uploader.setProgressListener(new CustomProgressListener());
HttpResponse response = uploader.upload(requestUrl);
if (!response.isSuccessStatusCode()) {
throw GoogleJsonResponseException(jsonFactory, response);
}
I also tried this, I was searching for tutorials to upload some user data to their own account. But I did not found anything. Google suggests google firebase storage instead of google drive. If you think, how WhatsApp uses google drive to upload data. Then my answer is that google provides special service to WhatsApp. So use firebase storage, it is easy and very cheap and also updated. Use documentation to use them very properly. The docs are really awesome.