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
}
}
Related
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.
I have an android app that saves an image into the Google Drive and shares the weblink to my Google App Engine server (python).
// Create client
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
// handling results after uploading
final DriveOperationResult<Metadata> driveOperationResultHandler = new DriveOperationResult<Metadata>() {
#Override
public void onDriveOperationSucceeded(Metadata result) {
try {
// Successfully fetched metadata
onSuccess(driveId,
result.getOriginalFilename(),
result.getWebContentLink(),
result.getWebViewLink(),
result.getAlternateLink(),
result.getEmbedLink());
} finally {
mGoogleDriveClient.disconnectAsync();
}
}
Note: result.getEmbedLink() always returns null. Also, result.getAlternateLink() and result.getWebContentLink() are not accessible. I am using Google Drive Android API.
I need to post the link to another server from the google app engine. How do I get a shareable link from google app engine [python] or android?
or
How do I change the permission on the link so that anyone with the link can read?
In python, you must do something like this
#decorator.oauth_required
def get(self):
try:
http = decorator.http()
service = discovery.build("drive", "v2", http=http)
# Make the list of every files in the user's Drive
# Take every fields we will need after
fields = "items(id,title,,alternateLink)
list = service.files().list(fields=fields).execute()
Then use the alternateLink property to get a link that can be shared for opening the file in the relevant Google editor or viewer
Having Google Drive account with folders and files. I want to make android application for adding and geting files to there. Class QUERY is useful, but it can work with data making by application only
The Android Drive API only works with the https://www.googleapis.com/auth/drive.file scope. This means that only files which a user has opened or created with your application can be matched by a query.
Help, please, how can I add files to any folder, that was created via webinterface early?
You want to avoid using full drive scope unless you really need it. Users much prefer that your app have a narrower scope, as it makes it easier to trust you with their data. There are a couple of methods that you can accomplish most folder use cases while still only requiring file scope:
Use the OpenFileActivity to have the user select the folder that they want the file to be added to.
You can do this by configuring the OpenFileActivityBuilder to only display the folder mimetypes.
IntentSender intent = driveApi.newOpenFileActivityBuilder()
.setActivityTitle("Pick a destination folder")
.setMimeType(new String[] { DriveFolder.MIME_TYPE } })
.build();
startIntentSenderForResult(intent, REQUEST_CODE, null, 0, 0, 0);
Alternatively, if you have a corresponding web app that created the folder, just use the same developer console entry for both apps and you should already have access to the folder.
Don't use the latest google API, it was just released a few weeks ago. It currently only works with the drive.file scope, hasn't yet implemented a number of capabilities (e.g. setting multiple parents), and in my experience, contains some bugs that need to be fixed as well.
com.google.android.gms.common.api.GoogleApiClient
Use this API instead:
com.google.api.services.drive.Drive
try {
List<String> scopes = new ArrayList<String>();
scopes.add("https://www.googleapis.com/auth/drive.appdata");
scopes.add(DriveScopes.DRIVE);
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(m_context, scopes);
credential.setSelectedAccountName(m_account.name);
//Get token cannot be run from the main thread;
//Trying to get a token right away to see if we are authorized
token = credential.getToken();
if(token == null){
Log.e(TAG, "token is null");
}else{
Log.i(TAG, "GDrive token: " + token);
g_drive = new Drive.Builder(
AndroidHttp.newCompatibleTransport(),
new GsonFactory(), credential).build();
} catch ( UserRecoverableAuthException e) {
....
}
I've spent the last six hours pouring over documents from Google and I still don't know how to get started with this. All I want to do is make it so my existing Android app can read files from Google Drive, upload new files to Google Drive, and edit existing files on Google Drive.
I've read that Drive SDK v2 was focused solely on making it easy for Android (and mobile in general) developers to use it, and yet there seems to be virtually nothing in their documentation about it.
Ideally, I'd like someone to point at some decent documentation, example, or tutorial covering how to do this (keep in mind I'm using Android. They have plenty of stuff on how to use Drive with the Google App Engine; I have already looked at it and I have no idea how to go from that to an Android app.)
I need to know which libraries I need to download and add to my project, what I need to add to my manifest, and how I can ultimately get a list of files from Google Drive, download one, and then upload a modified version.
Ideally, I'd like it to handle accounts automatically, the way that the officially Google Drive app does.
Edit: Claudio Cherubino says that Google Play Services is now available and will make this process a lot easier. However, there's no sample code available (yet, he says it's coming soon... they said Google Play Services was "coming soon" 4 months ago, so there's a good chance this answer will continue to be the only completely working example of accessing Google Drive from your Android application into 2013.)
Edit 2X: Looks like I was off by about a month when I said Google wouldn't have a working example until next year. The official guide from Google is over here:
https://developers.google.com/drive/quickstart-android
I haven't tested their methods yet, so it's possible that my solutions from September 2012 (below) are still the best:
Google Play Services is NOT REQUIRED for this. It's a pain in the butt, and I spent well over 50 hours (edit: 100+ hours) figuring it all out, but here's a lot of things that it'll help to know:
THE LIBRARIES
For Google's online services in general you'll need these libraries in your project: (Instructions and Download Link)
google-api-client-1.11.0-beta.jar
google-api-client-android-1.11.0-beta.jar
google-http-client-1.11.0-beta.jar
google-http-client-android-1.11.0-beta.jar
google-http-client-jackson-1.11.0-beta.jar
google-oauth-client-1.11.0-beta.jar
guava-11.0.1.jar
jackson-core-asl-1.9.9.jar
jsr305-1.3.9.jar
For Google Drive in particular you'll also need this:
google-api-services-drive-v2-rev9-1.8.0-beta.jar (Download Link)
SETTING UP THE CONSOLE
Next, go to Google Console. Make a new project. Under Services, you'll need to turn on two things: DRIVE API and DRIVE SDK! They are separate, one does not automatically turn the other on, and YOU MUST TURN BOTH ON! (Figuring this out wasted at least 20 hours of my time alone.)
Still on the console, go to API Access. Create a client, make it an Android app. Give it your bundle ID. I don't think the fingerprints thing is actually important, as I'm pretty sure I used the wrong one, but try to get that right anyways (Google provides instructions for it.)
It'll generate a Client ID. You're going to need that. Hold onto it.
Edit: I've been told that I'm mistaken and that you only need to turn on Drive API, Drive SDK doesn't need to be turned on at all, and that you just need to use the Simple API Key, not set up something for Android. I'm looking into that right now and will probably edit this answer in a few minutes if i figure it out...
THE ANDROID CODE - Set Up and Uploading
First, get an auth token:
AccountManager am = AccountManager.get(activity);
am.getAuthToken(am.getAccounts())[0],
"oauth2:" + DriveScopes.DRIVE,
new Bundle(),
true,
new OnTokenAcquired(),
null);
Next, OnTokenAcquired() needs to be set up something like this:
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
#Override
public void run(AccountManagerFuture<Bundle> result) {
try {
final String token = result.getResult().getString(AccountManager.KEY_AUTHTOKEN);
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
Drive.Builder b = new Drive.Builder(httpTransport, jsonFactory, null);
b.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
#Override
public void initialize(JSonHttpRequest request) throws IOException {
DriveRequest driveRequest = (DriveRequest) request;
driveRequest.setPrettyPrint(true);
driveRequest.setKey(CLIENT ID YOU GOT WHEN SETTING UP THE CONSOLE BEFORE YOU STARTED CODING)
driveRequest.setOauthToken(token);
}
});
final Drive drive = b.build();
final com.google.api.services.drive.model.File body = new com.google.api.services.drive.model.File();
body.setTitle("My Test File");
body.setDescription("A Test File");
body.setMimeType("text/plain");
final FileContent mediaContent = new FileContent("text/plain", an ordinary java.io.File you'd like to upload. Make it using a FileWriter or something, that's really outside the scope of this answer.)
new Thread(new Runnable() {
public void run() {
try {
com.google.api.services.drive.model.File file = drive.files().insert(body, mediaContent).execute();
alreadyTriedAgain = false; // Global boolean to make sure you don't repeatedly try too many times when the server is down or your code is faulty... they'll block requests until the next day if you make 10 bad requests, I found.
} catch (IOException e) {
if (!alreadyTriedAgain) {
alreadyTriedAgain = true;
AccountManager am = AccountManager.get(activity);
am.invalidateAuthToken(am.getAccounts()[0].type, null); // Requires the permissions MANAGE_ACCOUNTS & USE_CREDENTIALS in the Manifest
am.getAuthToken (same as before...)
} else {
// Give up. Crash or log an error or whatever you want.
}
}
}
}).start();
Intent launch = (Intent)result.getResult().get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, 3025);
return; // Not sure why... I wrote it here for some reason. Might not actually be necessary.
}
} catch (OperationCanceledException e) {
// Handle it...
} catch (AuthenticatorException e) {
// Handle it...
} catch (IOException e) {
// Handle it...
}
}
}
THE ANDROID CODE - Downloading
private java.io.File downloadGFileToJFolder(Drive drive, String token, File gFile, java.io.File jFolder) throws IOException {
if (gFile.getDownloadUrl() != null && gFile.getDownloadUrl().length() > 0 ) {
if (jFolder == null) {
jFolder = Environment.getExternalStorageDirectory();
jFolder.mkdirs();
}
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(gFile.getDownloadUrl());
get.setHeader("Authorization", "Bearer " + token);
HttpResponse response = client.execute(get);
InputStream inputStream = response.getEntity().getContent();
jFolder.mkdirs();
java.io.File jFile = new java.io.File(jFolder.getAbsolutePath() + "/" + getGFileName(gFile)); // getGFileName() is my own method... it just grabs originalFilename if it exists or title if it doesn't.
FileOutputStream fileStream = new FileOutputStream(jFile);
byte buffer[] = new byte[1024];
int length;
while ((length=inputStream.read(buffer))>0) {
fileStream.write(buffer, 0, length);
}
fileStream.close();
inputStream.close();
return jFile;
} catch (IOException e) {
// Handle IOExceptions here...
return null;
}
} else {
// Handle the case where the file on Google Drive has no length here.
return null;
}
}
One last thing... if that intent gets sent off, you'll need to handle when it returns with a result.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 3025) {
switch (resultCode) {
case RESULT_OK:
AccountManager am = AccountManager.get(activity);
am.getAuthToken(Same as the other two times... it should work this time though, because now the user is actually logged in.)
break;
case RESULT_CANCELED:
// This probably means the user refused to log in. Explain to them why they need to log in.
break;
default:
// This isn't expected... maybe just log whatever code was returned.
break;
}
} else {
// Your application has other intents that it fires off besides the one for Drive's log in if it ever reaches this spot. Handle it here however you'd like.
}
}
THE ANDROID CODE - Updating
Two quick notes on updating the last modified date of a file on Google Drive:
You must provide a fully initialized DateTime. If you do not, you'll get a response of "Bad Request" from Google Drive.
You must use both setModifiedDate() on the File from Google Drive and setSetModifiedDate(true) on the update request itself. (Fun name, huh? "setSet[...]", there's no way people could mistype that one...)
Here's some brief sample code showing how to do an update, including updating the file time:
public void updateGFileFromJFile(Drive drive, File gFile, java.io.File jFile) throws IOException {
FileContent gContent = new FileContent("text/csv", jFile);
gFile.setModifiedDate(new DateTime(false, jFile.lastModified(), 0));
gFile = drive.files().update(gFile.getId(), gFile, gContent).setSetModifiedDate(true).execute();
}
THE MANIFEST
You'll need the following permissions: GET_ACCOUNTS, USE_CREDENTIALS, MANAGE_ACCOUNTS, INTERNET, and there's a good chance you'll need WRITE_EXTERNAL_STORAGE as well, depending on where you'd like to store the local copies of your files.
YOUR BUILD TARGET
Right click your project, go into it's properties, and under Android change the build target to Google APIs if you must. If they aren't there, download them from the android download manager.
If you're testing on an emulator, make sure its target is Google APIs, not generic Android.
You'll need a Google Account set up on your test device. The code as written will automatically use the first Google Account it finds (that's what the [0] is.) IDK if you need to have downloaded the Google Drive app for this to have worked. I was using API Level 15, I don't know how far back this code will work.
THE REST
The above should get you started and hopefully you can figure your way out from there... honestly, this is just about as far as I've gotten so far. I hope this helps A LOT of people and saves them A LOT of time. I'm fairly certain I've just written the most comprehensive set up guide to setting up an Android app to use Google Drive. Shame on Google for spreading the necessary material across at least 6 different pages that don't link to each other at all.
It's 2015, things have changed!
Get the 'Drive API for Android' with gradle:
compile 'com.google.android.gms:play-services-drive:7.8.0'
There's some new doco (although still lackluster IMO):
https://developers.google.com/drive/web/quickstart/android
And for those about to go caving...the biggest problem I encountered thus far is that there is absolutely no way of distinguishing folders that have been permanently deleted from folders that are normal...you can find them, you can create folders and files within them, only writing to the file DriveContents will always fail.
Check this video from Google I/O to learn how to integrate your Android app with Drive:
http://www.youtube.com/watch?v=xRGyzqD-vRg
Please be aware that what you see in the video is based on Google Play Services:
https://developers.google.com/android/google-play-services/
Take a look at Google's DrEdit Example, which has a folder called android/. Copy it, follow the readme, and it should work (works for me on an Android emulator with KitKat).
.
P.S.
Sorry for reviving this, but the new Google Drive Android API doesn't support full Drive access, only drive.file and drive.appdata authorization scopes, so if you need full access you have to go back to the good 'ol Google API's Client for Java (which the DrEdit example uses).
I am trying to design an app which downloads the appropriate sound files from my Google cloud storage account. The app does not access the users account but my own.
My reading has led me to believe that the most appropriate model is
The Service account
https://code.google.com/p/google-api-java-client/wiki/OAuth2#Service_Accounts
Unfortunately the developers have decided not to provide an example with Android. They do provide a nice example with just plain Java, which works
http://samples.google-api-java-client.googlecode.com/hg/storage-serviceaccount-cmdline-sample/instructions.html?r=default
I tried to adapt this for Android and have run into problems.
GoogleCredential credential =
new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY).setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(STORAGE_SCOPE)
.setServiceAccountPrivateKeyFromP12File(new File("key.p12")).build();
In Google's example they pass the key.p12 file , However on Android when I put the file in the res/raw folder it seems the only way I have of accessing it is as an input stream. I can't find an elegant way to get a file to pass to JSON.
This all leads me to believe I must be doing something wrong.
Should I be using the key.p12
Should I be using the "service account model".
Is there an example out there /
Thanks
Ryan
An Update
I managed to achieve my goal of getting it to work but my solution feels clunky to me and I am sure it is not the way intended
What I did was add the key.p12 as a raw/resource which I opened as as input stream. Which I then converted to the private key using the libraries as seen in the example.
http://www.flexiprovider.de/examples/ExampleSMIMEsign.html
My code looks like this
Security.addProvider(new de.flexiprovider.core.FlexiCoreProvider());
// Next, we have to read the private PKCS #12 file, since the the
// private key used for signing is contained in this file:
DERDecoder dec = new DERDecoder(getResources().openRawResource(
R.raw.key));
PFX pfx = new PFX();
try {
pfx.decode(dec);
SafeBag safeBag = pfx.getAuthSafe().getSafeContents(0)
.getSafeBag(0);
PKCS8ShroudedKeyBag kBag = (PKCS8ShroudedKeyBag) safeBag
.getBagValue();
char[] password = "my password from google api".toCharArray();
privKey = kBag.getPrivateKey(password);
new AsyncLoadStorage(this).execute();
} catch (ASN1Exception e) {
But the whole thing is ugly and I would like a cleaner solution
Google documentation is actually pretty misleading. They haven't updated their console links (keep on asking you to look for "register apps" link, which doesn't exist), and their JAVA api for GCS doesn't work in Android (GcsService service = GcsServiceFactory.createGcsService();). Seems like they expect you to access GCS from App engine only.
So, here's what one needs to do:
You probably don't want users to have to sign into GCS or Google (think of Snapchat app).
But you still want authentication, so your data isn't completely in public view; its only accessible through your apps.
You'd want to have a service account P2K file, which you can bundle along with app, so your users don't have to login anywhere.
From https://cloud.google.com/console/project, click Project > APIs & Auth > Credentials > Create new Client ID > Service Account. This would let you download P2K file.
Store this in res/raw/private_key.p2k, and then use the following code to authenticate your android app to query GCS.
This works without any problems for me:
String STORAGE_SCOPE = "https://www.googleapis.com/auth/devstorage.read_write";
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
Log.d("testing", "checking if I can create a credential");
httpTransport = AndroidHttp.newCompatibleTransport();
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(resources_.openRawResource(R.raw.gcs_privatekey),
"password".toCharArray());
PrivateKey key = (PrivateKey) keystore.getKey("privatekey", "password".toCharArray());
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountPrivateKey(key)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton(STORAGE_SCOPE))
// .setServiceAccountUser(SERVICE_ACCOUNT_EMAIL)
// .setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.build();
credential.refreshToken();
String URI = "https://storage.googleapis.com/" + BUCKET_NAME;
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
GenericUrl url = new GenericUrl(URI);
HttpRequest request = requestFactory.buildGetRequest(url);
HttpResponse response = request.execute();
String content = response.parseAsString();
Log.d("testing", "response content is: " + content);
new Storage.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName("appname").build();
Here is what I did to transform the inputStream key to a PrivateKey object :
PrivateKey serviceAccountPrivateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), MyClass.class.getResourceAsStream("/privatekey.p12"), "notasecret", "privatekey", "notasecret");
// Build service account credential.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(ACCOUNT_ID)
.setServiceAccountScopes(Collections.singleton(StorageScopes.DEVSTORAGE_FULL_CONTROL))
//.setServiceAccountPrivateKeyFromP12File(f)
.setServiceAccountPrivateKey(serviceAccountPrivateKey)
.build();
I don't know your exact situation, but could you just make these files completely public so that no auth at all is required to download them?