Uploading image from Android to GCS
Since no one is answering this question, let me update the way I solved this problem. I ended up following this https://github.com/pliablematter/simple-cloud-storage project.
I could upload Pictures/Videos to GCS from my Android app.
Fixed for Android:
Android Studio config:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/android-support-v4.jar')
compile files('google-play-services.jar')
compile 'com.wu-man:android-oauth-client:0.0.3'
compile 'com.google.apis:google-api-services-storage:v1-rev17-1.19.0'
compile(group: 'com.google.api-client', name: 'google-api-client', version:'1.19.0'){
exclude(group: 'com.google.guava', module: 'guava-jdk5')
}
}
AndroidManifiest:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
Main implementation:
new AsyncTask(){
@Override
protected Object doInBackground(Object[] params) {
try {
CloudStorage.uploadFile("bucket-xxx", "photo.jpg");
} catch (Exception e) {
if(DEBUG)Log.d(TAG, "Exception: "+e.getMessage());
e.printStackTrace();
}
return null;
}
}.execute();
CloudStorage Class:
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.StorageObject;
public static void uploadFile(String bucketName, String filePath)throws Exception {
Storage storage = getStorage();
StorageObject object = new StorageObject();
object.setBucket(bucketName);
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard,filePath);
InputStream stream = new FileInputStream(file);
try {
String contentType = URLConnection.guessContentTypeFromStream(stream);
InputStreamContent content = new InputStreamContent(contentType,stream);
Storage.Objects.Insert insert = storage.objects().insert(bucketName, null, content);
insert.setName(file.getName());
insert.execute();
} finally {
stream.close();
}
}
private static Storage getStorage() throws Exception {
if (storage == null) {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<String>();
scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
Credential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(ACCOUNT_ID_PROPERTY) //Email
.setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
.setServiceAccountScopes(scopes).build();
storage = new Storage.Builder(httpTransport, jsonFactory,
credential).setApplicationName(APPLICATION_NAME_PROPERTY)
.build();
}
return storage;
}
private static File getTempPkc12File() throws IOException {
// xxx.p12 export from google API console
InputStream pkc12Stream = AppData.getInstance().getAssets().open("xxx.p12");
File tempPkc12File = File.createTempFile("temp_pkc12_file", "p12");
OutputStream tempFileStream = new FileOutputStream(tempPkc12File);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = pkc12Stream.read(bytes)) != -1) {
tempFileStream.write(bytes, 0, read);
}
return tempPkc12File;
}
This snippet of code works for me great for uploading files from Android directly to GCS.
File file = new File(Environment.getExternalStorageDirectory(), fileName);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
FileBody filebody = new FileBody(file,ContentType.create(mimeType), file.getName());
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("file", filebody);
httppost.setEntity(multipartEntity.build());
System.out.println( "executing request " + httppost.getRequestLine( ) );
try {
HttpResponse response = httpclient.execute( httppost );
Log.i("response", response.getStatusLine().toString());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
httpclient.getConnectionManager( ).shutdown( );
MultipartEntityBuilder class is not included into android standard libraries so you need to download httpclient and include into your project.
Hpsaturn's answer worked for me. He missed to answer a few points. How to get service account id and p12 file. For getting these 2, open console.developers.google.com and choose your project. Enable Cloud Storage API. You see a message to create credentials. Go to credentials in API manager and create credential by selecting Service account key and follow the details in image. You will get the service account id and p12 file from this screen.
Hpsaturn also missed to mention AppData, which is your custom Application class defined in manifest. For everyone's convenience, I am attaching the complete CloudStorage class here.
package com.abc.xyz.utils;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import com.abc.xyz.app.AppController;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;
import com.google.api.services.storage.model.StorageObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wjose on 8/20/2016.
*/
public class CloudStorage {
private static final String TAG = "CloudStorage";
public static void uploadFile(String bucketName, String name, Uri uri)throws Exception {
Storage storage = getStorage();
StorageObject object = new StorageObject();
object.setBucket(bucketName);
File sdcard = Environment.getExternalStorageDirectory();
//File file = new File(sdcard,filePath);
File file = new File(uri.getPath());
InputStream stream = new FileInputStream(file);
try {
String contentType = URLConnection.guessContentTypeFromStream(stream);
InputStreamContent content = new InputStreamContent(contentType,stream);
Storage.Objects.Insert insert = storage.objects().insert(bucketName, null, content);
insert.setName(name);
StorageObject obj = insert.execute();
Log.d(TAG, obj.getSelfLink());
} finally {
stream.close();
}
}
static Storage storage = null;
private static Storage getStorage() throws Exception {
if (storage == null) {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<String>();
scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
Credential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId("[email protected]") //Email
.setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
.setServiceAccountScopes(scopes).build();
storage = new Storage.Builder(httpTransport, jsonFactory,
credential).setApplicationName("MyApp")
.build();
}
return storage;
}
private static File getTempPkc12File() throws IOException {
// xxx.p12 export from google API console
InputStream pkc12Stream = MyApplication.getInstance().getAssets().open("xxxyyyzzz-0c80eed2e8aa.p12");
File tempPkc12File = File.createTempFile("temp_pkc12_file", "p12");
OutputStream tempFileStream = new FileOutputStream(tempPkc12File);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = pkc12Stream.read(bytes)) != -1) {
tempFileStream.write(bytes, 0, read);
}
return tempPkc12File;
}
}
btb, I used only following dependency in the gradle.
compile 'com.google.apis:google-api-services-storage:+'
I have tried all the above answers and none of them worked for me straight out of the box. Here is what i have done to make it working(only by editing from the above comments):
package Your page name;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Environment;
import android.util.Log;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.StorageObject;
import java.io.File;
import java.io.*;
import java.io.InputStream;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
public class CloudStorage {
static Activity activity=null;
//http://stackoverflow.com/questions/18002293/uploading-image-from-android-to-gcs
static Storage storage=null;
public static void uploadFile(Activity activity2,String bucketName, String filePath)
{
activity=activity2;
try {
Storage storage = getStorage();
StorageObject object = new StorageObject();
object.setBucket(bucketName);
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(filePath);
InputStream stream = new FileInputStream(file);
try {
Log.d("Alkamli","Test");
String contentType = URLConnection.guessContentTypeFromStream(stream);
InputStreamContent content = new InputStreamContent(contentType, stream);
Storage.Objects.Insert insert = storage.objects().insert(bucketName, null, content);
insert.setName(file.getName());
insert.execute();
} finally {
stream.close();
}
}catch(Exception e)
{
class Local {}; Log.d("Alkamli","Sub: "+Local.class.getEnclosingMethod().getName()+" Error code: "+e.getMessage());
e.printStackTrace();
}
}
private static Storage getStorage() {
try {
if (storage == null)
{
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<String>();
scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
Credential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId("Service-Email-Address") //Email
.setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
.setServiceAccountScopes(scopes).build();
storage = new Storage.Builder(httpTransport, jsonFactory,
credential)
.build();
}
return storage;
}catch(Exception e)
{
class Local {}; Log.d("Alkamli","Sub: "+Local.class.getEnclosingMethod().getName()+" Error code: "+e.getMessage());
}
Log.d("Alkamli","Storage object is null ");
return null;
}
private static File getTempPkc12File() {
try {
// xxx.p12 export from google API console
InputStream pkc12Stream = activity.getResources().getAssets().open("Service-key.p12");
File tempPkc12File = File.createTempFile("temp_pkc12_file", "p12");
OutputStream tempFileStream = new FileOutputStream(tempPkc12File);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = pkc12Stream.read(bytes)) != -1) {
tempFileStream.write(bytes, 0, read);
}
return tempPkc12File;
}catch(Exception e)
{
class Local {}; Log.d("Alkamli","Sub: "+Local.class.getEnclosingMethod().getName()+" Error code: "+e.getMessage());
}
Log.d("Alkamli"," getTempPkc12File is null");
return null;
}
}
I only edited few lines to make it work for me and for the dependencies in gradle You will need only these three. (Keep in mind that if you use all google depenacnes that may damage your whole project. in my case some of android's functions wouldn't work anymore )
compile 'com.google.api-client:google-api-client:1.20.0'
compile 'com.google.oauth-client:google-oauth-client-jetty:1.20.0'
compile 'com.google.apis:google-api-services-storage:v1-rev17-1.19.0'
The full project for people needing it : https://github.com/Fahad-alkamli/Chat-app