从谷歌照片库中检索已下载的图像

14

我正在启动一个意图从相册获取照片,当我在我的相册中使用 Nexus 谷歌照片应用程序时,一切都正常。

但是如果图片不在手机上(在 Google Photos 的在线服务上),它将为我下载图片。选择图片后,我将图像发送到另一个活动进行裁剪,但在下载的情况下,由于下载尚未完成,发送到裁剪活动的图像为空。

我如何知道下载何时完成以将图像发送到裁剪活动?

这是我的代码:

private void pickFromGallery()
{
    Intent galleryIntent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(galleryIntent, RESULT_LOAD_IMG);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    try {
        // When an Image is picked
        if (requestCode == RESULT_LOAD_IMG && resultCode == Activity.RESULT_OK
                && null != data) {
            // Get the Image from data

            Uri selectedImage = data.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};

            // Get the cursor
            Cursor cursor = getApplicationContext().getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            // Move to first row
            assert cursor != null;
            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            imgDecodableString = cursor.getString(columnIndex);
            cursor.close();
            startCrop(imgDecodableString);
        }
    } catch (Exception e) {
        Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG)
                .show();
    }
    }

任何帮助将不胜感激。


1
请使用句点和逗号,一个长句子不易阅读。 - Milos Fec
3个回答

19

我认为当你从Google照片下载选定的图像时,你不能剪裁这些图像。你只能剪裁本地存储的图像。

但是,如果要检查所选图像是否可下载或来自本地存储,则可以在onActivityResult()方法中执行以下操作。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RESULT_LOAD_IMG && resultCode == Activity.RESULT_OK
                && null != data) {

                Uri selectedImageUri = data.getData();
                String tempPath = getPath(selectedImageUri, getActivity());
                String url = data.getData().toString();
                if (url.startsWith("content://com.google.android.apps.photos.content")){
                    try {
                        InputStream is = getActivity().getContentResolver().openInputStream(selectedImageUri);
                        if (is != null) {
                            Bitmap pictureBitmap = BitmapFactory.decodeStream(is);
                            //You can use this bitmap according to your purpose or Set bitmap to imageview
                        }
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }else {
                     startCrop(tempPath);

             }
         }

}

这里有一个getPath()方法,在onActivityResult()中使用。

public String getPath(Uri uri, Activity activity) {
    Cursor cursor = null;
    try {
        String[] projection = {MediaStore.MediaColumns.DATA};
        cursor = activity.getContentResolver().query(uri, projection, null, null, null);
        if (cursor.moveToFirst()) {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
            return cursor.getString(column_index);
        }
    } catch (Exception e) {
    } finally {
        cursor.close();
    }
    return "";
}

希望它能对你有所帮助。


它抛出了 FileNotFoundException :( - Zubair Rehman

2

无法从谷歌云端硬盘下载图像,请按以下步骤从云端硬盘中下载图像或文件。

要从谷歌云端硬盘下载图像或文件,您需要一个库

  • google-api-services-drive-v2-rev9-1.8.0-beta.jar()

设置控制台

  • 接下来,转到Google控制台

  • 创建一个新项目。在“服务”下,您需要启用两个选项:DRIVE API和DRIVE SDK!它们是独立的,一个不会自动开启另一个,并且您必须同时开启两者!(至少我浪费了20个小时去搞清楚这件事。)

  • 仍然在控制台上,转到API访问。创建一个客户端,将其设为Android应用程序。给它你的包ID。我认为指纹事实上并不重要,因为我相当确定我使用了错误的指纹,但还是要尽量弄对(Google提供了说明。)

  • 它会生成一个客户端ID。您将需要它。记住它。

Android代码-设置和上传

  • 首先,获取身份验证令牌:

    AccountManager am = AccountManager.get(activity); am.getAuthToken(am.getAccounts())[0], "oauth2:" + DriveScopes.DRIVE, new Bundle(), true, new OnTokenAcquired(), null);

接下来,需要设置类似于以下的OnTokenAcquired():

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

Android代码 - 下载

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

2
问题提到的是Google照片,而不是Google Drive。无论如何,您可以使用DocumentsProvider从Google Drive获取文件。 - Milos Fec
@MilosFec Google Drive是Google的一部分,而且Google總是把照片存儲在Google Drive上。 - vishal jangid
1
这不是相关的。当您安装了Google相册后,可以使用Intent.ACTION_PICK获取照片。如果您安装了Google Drive,则可以使用Intent.ACTION_OPEN_DOCUMENT获取任何文件。 - Milos Fec

0
你可以使用AsyncTask进行下载(或复制本地图像),然后处理它。
在你的Activity中创建:
private class PictureAsyncTask extends AsyncTask<Void, Void, String> {
    private Uri mUri;

    public PictureAsyncTask(Uri uri) {
        mUri = uri;
    }

    @Override
    protected String doInBackground(Void... params) {
        InputStream inputStream = null;
        try {
            inputStream = getContentResolver().openInputStream(mUri);
            String path = null; // Path of downloaded image
            // Download image from inputStream
            return path;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null
    }

    @Override
    protected void onPostExecute(String path) {
        if (path == null) {
            // Process image
            // Maybe another AsyncTask or background thread?
        } else {
            // Download failed
        }
    }
}

从onActivityResult调用它:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case RESULT_LOAD_IMG:
            if (resultCode == RESULT_OK) {
                if (data != null) {
                    Uri uri = data.getData();
                    if (uri != null) {
                        new PictureAsyncTask(uri).execute();
                    } else {
                        // No data
                    }
                } else {
                    // No picture selected?
                }
            }
            break;
    }
}

我只想知道在使用Google相册应用作为画廊时何时处理下载。 - Mostafa Addam
无论是本地图片还是下载的图片,都应该在后台线程中处理。例如,您可以使用 BitmapFactory.decodeStream(inputStream) 创建位图并对其进行处理,而不是下载它。这可能需要一些时间,因此最好不要在主线程上执行此操作。 - Milos Fec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接