web-dev-qa-db-ja.com

AndroidからGCSへの画像のアップロード

Androidから直接Googleクラウドストレージに画像をアップロードしようとしています。しかし、APIが機能していないようです。いくつかのJavaサンプルが関連付けられていますApp Engineに追加しました。Androidで動作することが証明されているサンプルはありません。

Androidでは、json apiを使用して画像をアップロードしてみました。画像オブジェクトをアップロードできますが、壊れているようです。さらに、認証トークンの生成も難しいようです。

私は今これに悩まされています。この地球上の誰かが、AndroidJavaクライアントまたはJson APIを使用して)から画像/ビデオをアップロードしようとして成功しましたか?誰かが私を正しい方向に向けることができますか? 。このGoogleのStorage APIは非常に残念な体験でした。誰かが体験した場合は、体験を共有してください。以下は、GCSのJSON APIを使用しようとしているときにAndroidから試行しているコードです。 。

private static String uploadFile(RichMedia media) {
    DefaultHttpClient client = new DefaultHttpClient();
    Bitmap bitmap = BitmapUtils.getBitmap(media.getLocalUrl());
    HttpPost post = new HttpPost(GCS_ROOT + media.getLocalUrl() + "_" + System.currentTimeMillis());
    if(media.getType() == RichMedia.RichMediaType.PICTURE) {
        post.setHeader("Content-Type", "image/jpeg");
    } else {
        post.setHeader("Content-Type", "video/mp4");
    }
    post.setHeader("Authorization", "AIzaSyCzdmCMwiMzl6LD7R2obF0xSgnnx5rEfeI");
    //post.setHeader("Content-Length", String.valueOf(bitmap.getByteCount()));
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    byte[] byteArray = stream.toByteArray();

    try {
        post.setEntity(new StringEntity(new Gson().toJson(byteArray).toString()));
        HttpResponse response = client.execute(post);
        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        String eachLine = null;
        StringBuilder builder = new StringBuilder();
        while ((eachLine = reader.readLine()) != null) {
            builder.append(eachLine);
        }
        L.d("response = " + builder.toString());
        JSONObject object = new JSONObject(builder.toString());
        String name = object.getString("name");
        return  name;
    } catch (IOException e) {
        L.print(e);
    } catch (JSONException e) {
        L.print(e);
    }
    return null;
}

ここで2つの問題が発生しています。

  1. サーバーにアップロードされたファイルが破損しています。アップロードした画像とは異なります。腐っています。

  2. 認証キーは非常に頻繁に期限切れになります。私の場合、gsutilによって生成された認証コードを使用しています。

21
Gopinath

誰もこの質問に答えていないので、この問題の解決方法を更新しましょう。私はこの https://github.com/pliablematter/simple-cloud-storage プロジェクトに従っています。

AndroidアプリからGCSに画像/動画をアップロードできます。

15
Gopinath

Android向けに修正:

Android Studioの設定:

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>

主な実装:

    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クラス:

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;
}
8
Hpsaturn

このコードスニペットは、Androidから直接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クラスはAndroid標準ライブラリに含まれていないため、ダウンロードして httpclient をプロジェクトに含める必要があります。

3
Juniper

Hpsaturnの答えは私のために働いた。彼はいくつかの点に答えなかった。サービスアカウントIDとp12ファイルを取得する方法。これら2を取得するには、console.developers.google.comを開いてプロジェクトを選択します。 Cloud Storage APIを有効にします。資格情報を作成するメッセージが表示されます。 API Managerで認証情報に移動し、サービスアカウントキーを選択して認証情報を作成し、画像の詳細に従います。この画面からサービスアカウントIDとp12ファイルを取得します。

enter image description here

Hpsaturnは、マニフェストで定義されたカスタムアプリケーションクラスであるAppDataについても言及していません。皆さんの便宜のために、ここでは完全なCloudStorageクラスを添付しています。

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、私はgradleで次の依存関係のみを使用しました。

「com.google.apis:google-api-services-storage:+」をコンパイルします

2
Winster

私は上記のすべての答えを試しましたが、箱から出してすぐにうまくいくものはありませんでした。これは私がそれを機能させるために行ったものです(上記のコメントから編集することによってのみ):

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;
}
}

いくつかの行を編集して、私とgradleの依存関係が機能するようにしました。必要なのはこれら3つだけです。 (プロジェクト全体に損傷を与える可能性があるすべてのgoogle depenacnesを使用すると、私の場合、Androidの一部の機能が動作しなくなることに注意してください)

    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' 

それを必要とする人々のための完全なプロジェクト: https://github.com/Fahad-alkamli/Chat-app

1
Fahad Alkamli