我正在尝试将Android上的图片直接上传到Google云存储。但API似乎不起作用。他们有一些与App引擎绑定的Java示例。我没有看到任何被证明适用于Android的示例。
在Android上,我尝试使用json api上传图片。我能够上传图像对象,但它似乎已损坏。此外,生成身份验证令牌似乎也很棘手。
我现在很震惊。这个世界上有没有人尝试使用Java客户端或Json API从Android上传图像/视频并成功了?请有人指出我正确的方向。来自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;
}
我在这里遇到两个问题。
上传到服务器的文件已损坏。它与我上传的图像不同。它很糟糕。
授权密钥经常过期。就我而言,我使用的是gsutil生成的身份验证码。
答案 0 :(得分:14)
由于没有人回答这个问题,让我更新解决这个问题的方法。我最终关注了这个https://github.com/pliablematter/simple-cloud-storage项目。
我可以从我的Android应用上传图片/视频到GCS。
答案 1 :(得分:8)
已修复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;
}
答案 2 :(得分:3)
这段代码非常适合我将文件从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 :(得分:2)
Hpsaturn的回答对我有用。他错过了几点回答。如何获取服务帐户ID和p12文件。要获得这两个,请打开console.developers.google.com并选择您的项目。启用云存储API。您会看到一条消息来创建凭据。转到API管理器中的凭据并通过选择服务帐户密钥创建凭据,然后按照图像中的详细信息进行操作。您将从此屏幕获得服务帐户ID和p12文件。
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("myuser-801@xxxyyyzzz.iam.gserviceaccount.com") //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:+'
答案 4 :(得分:1)
我已经尝试了以上所有答案,并且它们都没有直接开箱即用。 以下是我所做的工作(仅通过编辑上述评论):
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中的依赖项您只需要这三行。 (请记住,如果您使用可能会损坏整个项目的所有谷歌依赖项。在我的情况下,一些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'
答案 5 :(得分:0)
不出所料,上述解决方案都不适合我。原因,在上述所有答案中,他们使用的是 .P12 文件,而我得到了一个 JSON 文件作为 api 密钥。一开始我不知道这两个不同的键,我以为我做错了,经过一天紧张的谷歌文档,stackoverflow,我终于能够上传到存储。以上答案均未显示如何为 JSON 文件执行此操作,并且代码有点简单,因此我发布了此答案,希望对某人有所帮助:
上传文件.java
public class UploadFile {
public static Storage setCredentials(InputStream credentialFile) {
InputStream credentialsStream = null;;
Credentials credentials = null;
try {
credentialsStream = credentialFile;
credentials = GoogleCredentials.fromStream(credentialsStream);
} catch (IOException e) {
e.printStackTrace();
return null;
}
return StorageOptions.newBuilder()
.setProjectId("YOUR_PROJECT_ID").setCredentials(credentials)
.build().getService();
}
@RequiresApi(api = Build.VERSION_CODES.O)
public static String transmitImageFile(Storage storage, String srcFileName, String newName) {
File file = new File(srcFileName);
byte[] fileContent = null;
try {
fileContent = Files.readAllBytes(file.toPath());
} catch (IOException e) {
e.printStackTrace();
return null;
}
if (fileContent == null)
return null;
if (fileContent.length == 0)
return null;
BlobInfo.Builder newBuilder = Blob.newBuilder(BucketInfo.of("YOUR_BUCKET_NAME"), newName);
BlobInfo blobInfo = newBuilder.setContentType("image/png").build();
Blob blob = storage.create(blobInfo, fileContent);
String bucket = blob.getBucket();
String contentType = blob.getContentType();
Log.e("TAG", "transmitImageFile: "+contentType);
System.out.println("File " + srcFileName + " uploaded to bucket " + bucket + " as " + newName);
return newName;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private String currentPhotoPath;
private String imageName;
public static final int REQUEST_IMAGE_CAPTURE = 1;
private File photoFile = null;
private String[] permissions;
public static final int PERMISSION_REQ_CODE = 200;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView= findViewById(R.id.textView);
permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE, Manifest.permission.ACCESS_COARSE_LOCATION};
PermissionsRequest();
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dispatchTakePictureIntent();
ReadFromAsset();
}
});
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try {
photoFile = createImageFile();
} catch (Exception ex) {
ex.printStackTrace();
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this, getPackageName(), photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
String fileName = "temp";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg");
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
imageName = image.getName();
return image;
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Storage storage = UploadFile.setCredentials(getAssets().open("GoogleMapDemo.json"));
UploadFile.transmitImageFile(storage, currentPhotoPath, "sampleImage.jpg");
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
Log.e("TAG", "ImagePath: " + currentPhotoPath);
Log.e("TAG", "ImageName: " + imageName);
}
}
private void PermissionsRequest() {
if (ContextCompat.checkSelfPermission(getApplicationContext(), permissions[0]) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(getApplicationContext(), permissions[4]) != PackageManager.PERMISSION_GRANTED) {
AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this);
builder1.setTitle("AAtten");
builder1.setMessage("Permissions");
builder1.setCancelable(false);
builder1.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
acceptPermissions();
}
});
builder1.setNegativeButton("SAIR", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
//Creating dialog box
AlertDialog alert1 = builder1.create();
alert1.show();
}
}
private void acceptPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getApplicationContext(), permissions[0]) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplicationContext(), permissions[1]) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplicationContext(), permissions[2]) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplicationContext(), permissions[3]) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplicationContext(), permissions[4]) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplicationContext(), permissions[5]) != PackageManager.PERMISSION_GRANTED)
requestPermissions(permissions, PERMISSION_REQ_CODE);
else {
if ((ContextCompat.checkSelfPermission(getApplicationContext(), permissions[0]) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(getApplicationContext(), permissions[1]) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(getApplicationContext(), permissions[2]) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(getApplicationContext(), permissions[3]) != PackageManager.PERMISSION_GRANTED) || ContextCompat.checkSelfPermission(getApplicationContext(), permissions[4]) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplicationContext(), permissions[5]) != PackageManager.PERMISSION_GRANTED)
requestPermissions(permissions, PERMISSION_REQ_CODE);
}
}
}
private void ReadFromAsset(){
String string = "";
try {
//InputStream inputStream = new FileInputStream(String.valueOf(getAssets().open("key.p12")));
InputStream inputStream = getAssets().open("GoogleMapDemo.json");
int size = inputStream.available();
byte[] buffer = new byte[size];
inputStream.read(buffer);
string = new String(buffer);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("TAG", "ReadFromAsset: "+string );
}
}
现在谷歌关于如何在应用程序中创建资产文件夹并在该文件夹中添加json密钥文件。在 onActivityResult 类中,您将传递 json 文件的名称。
在 UploadImage 类中,在各自的字段中提供您的 projectID 和 bucketName。您可以在该 json.file 中找到 projectID
依赖
android{
packagingOptions{
exclude 'META-INF/INDEX.LIST'
exclude 'META-INF/DEPENDENCIES'
}
}
implementation platform('com.google.cloud:libraries-bom:16.2.1')
implementation 'com.google.cloud:google-cloud-storage'
implementation 'com.google.cloud:google-cloud-core:1.94.0'
麦菲斯特
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE">
<application
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.personalgooglestoragecheck"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application
文件路径.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path
name="my_images"
path="/" />
<external-path
name="external"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
希望这对某人有所帮助。如有任何问题,请随时提出。
编辑 1:
显然 Files.readAllBytes() 是在 Java 7 中引入的,并且仅适用于 Android api 26 或更高版本。如果您想针对较低版本,请使用 fileinputstream 并删除所有 @requireannotation 标记。